diff --git a/.github/workflows/publish-technical-documentation-next.yml b/.github/workflows/publish-technical-documentation-next.yml index 80acbd233..53a5b7a7a 100644 --- a/.github/workflows/publish-technical-documentation-next.yml +++ b/.github/workflows/publish-technical-documentation-next.yml @@ -1,58 +1,21 @@ -name: "Publish Technical Documentation (next)" +name: publish-technical-documentation-next on: push: branches: - - "main" + - main paths: - "docs/sources/**" workflow_dispatch: - jobs: - test: - runs-on: "ubuntu-latest" - steps: - - name: "Check out code" - uses: "actions/checkout@v4" - - name: "Build website" - # -e HUGO_REFLINKSERRORLEVEL=ERROR prevents merging broken refs with the downside - # that no refs to external content can be used as these refs will not resolve in the - # docs-base image. - run: > - docker run -v ${PWD}/docs/sources:/hugo/content/docs/oncall/latest - -e HUGO_REFLINKSERRORLEVEL=ERROR - --rm grafana/docs-base:latest /bin/bash - -c 'echo -e "---\\nredirectURL: /hugo/content/docs/oncall/latest/\\ntype: redirect\\nversioned: true\\n---\\n" - > /hugo/content/docs/oncall/_index.md; make hugo' - sync: - runs-on: "ubuntu-latest" - needs: "test" + if: github.repository == 'grafana/oncall' + permissions: + contents: read + id-token: write + runs-on: ubuntu-latest steps: - - name: "Check out code" - uses: "actions/checkout@v4" - - - name: "Clone website-sync Action" - # WEBSITE_SYNC_TOKEN is a fine-grained GitHub Personal Access Token that expires. - # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization - # GitHub administrator to update the organization secret. - # The IT helpdesk can update the organization secret. - run: | - git clone --single-branch --no-tags --depth 1 \ - -b master https://grafanabot:${{ secrets.WEBSITE_SYNC_TOKEN }}@github.com/grafana/website-sync \ - ./.github/actions/website-sync - - - name: "Publish to website repository (next)" - uses: "./.github/actions/website-sync" - id: "publish-next" + - uses: actions/checkout@v4 + - uses: grafana/writers-toolkit/publish-technical-documentation@publish-technical-documentation/v1 with: - repository: "grafana/website" - branch: "master" - host: "github.com" - # PUBLISH_TO_WEBSITE_TOKEN is a fine-grained GitHub Personal Access Token that expires. - # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization - # GitHub administrator to update the organization secret. - # The IT helpdesk can update the organization secret. - github_pat: "grafanabot:${{ secrets.PUBLISH_TO_WEBSITE_TOKEN }}" - source_folder: "docs/sources" - target_folder: "content/docs/oncall/next" + website_directory: content/docs/oncall/next diff --git a/.github/workflows/publish-technical-documentation-release.yml b/.github/workflows/publish-technical-documentation-release.yml index 5e8b1e008..e91b642a5 100644 --- a/.github/workflows/publish-technical-documentation-release.yml +++ b/.github/workflows/publish-technical-documentation-release.yml @@ -1,4 +1,4 @@ -name: "Publish Technical Documentation (release)" +name: publish-technical-documentation-release on: push: @@ -9,85 +9,20 @@ on: paths: - "docs/sources/**" workflow_dispatch: - jobs: - test: - runs-on: "ubuntu-latest" - steps: - - name: "Check out code" - uses: "actions/checkout@v4" - - name: "Build website" - # -e HUGO_REFLINKSERRORLEVEL=ERROR prevents merging broken refs with the downside - # that no refs to external content can be used as these refs will not resolve in the - # docs-base image. - run: > - docker run -v ${PWD}/docs/sources:/hugo/content/docs/oncall/latest - -e HUGO_REFLINKSERRORLEVEL=ERROR - --rm grafana/docs-base:latest /bin/bash - -c 'echo -e "---\\nredirectURL: /hugo/content/docs/oncall/latest/\\ntype: redirect\\nversioned: true\\n---\\n" - > /hugo/content/docs/oncall/_index.md; make hugo' - sync: - runs-on: "ubuntu-latest" - needs: "test" + if: github.repository == 'grafana/oncall' + permissions: + contents: read + id-token: write + runs-on: ubuntu-latest steps: - - name: "Checkout code and tags" - uses: "actions/checkout@v4" + - uses: actions/checkout@v4 with: fetch-depth: 0 - - - name: "Checkout Actions library" - uses: "actions/checkout@v4" - with: - repository: "grafana/grafana-github-actions" - path: "./actions" - - - name: "Install Actions from library" - run: "npm install --production --prefix ./actions" - - - name: "Determine if there is a matching release tag" - id: "has-matching-release-tag" - uses: "./actions/has-matching-release-tag" - with: - ref_name: "${{ github.ref_name }}" - release_tag_regexp: "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$" - release_branch_regexp: "^release-(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$" - - - name: "Determine technical documentation version" - if: "steps.has-matching-release-tag.outputs.bool == 'true'" - uses: "./actions/docs-target" - id: "target" - with: - ref_name: "${{ github.ref_name }}" - - - name: "Clone website-sync Action" - if: "steps.has-matching-release-tag.outputs.bool == 'true'" - # WEBSITE_SYNC_TOKEN is a fine-grained GitHub Personal Access Token that expires. - # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization - # GitHub administrator to update the organization secret. - # The IT helpdesk can update the organization secret. - run: | - git clone --single-branch --no-tags --depth 1 \ - -b master https://grafanabot:${{ secrets.WEBSITE_SYNC_TOKEN }}@github.com/grafana/website-sync \ - ./.github/actions/website-sync - - - name: "Publish to website repository (release)" - if: "steps.has-matching-release-tag.outputs.bool == 'true'" - uses: "./.github/actions/website-sync" - id: "publish-release" + - uses: grafana/writers-toolkit/publish-technical-documentation-release@publish-technical-documentation-release/v2 with: - repository: "grafana/website" - branch: "master" - host: "github.com" - # PUBLISH_TO_WEBSITE_TOKEN is a fine-grained GitHub Personal Access Token that expires. - # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization - # GitHub administrator to update the organization secret. - # The IT helpdesk can update the organization secret. - github_pat: "grafanabot:${{ secrets.PUBLISH_TO_WEBSITE_TOKEN }}" - source_folder: "docs/sources" - # Append ".x" to target to produce a v..x directory. - target_folder: "content/docs/oncall/${{ steps.target.outputs.target }}.x" - # Allow the workflow to succeed if there are no changes to commit. - # This is only going to be true on tags as those events ignore the path - # filter in the workflow `on.push` section. - allow_no_changes: "true" + release_tag_regexp: "^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$" + release_branch_regexp: "^release-(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$" + release_branch_with_patch_regexp: "^release-(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$" + website_directory: content/docs/oncall diff --git a/engine/apps/alerts/migrations/0073_update_direct_paging_integration_non_default_routes.py b/engine/apps/alerts/migrations/0073_update_direct_paging_integration_non_default_routes.py new file mode 100644 index 000000000..bd9c4070d --- /dev/null +++ b/engine/apps/alerts/migrations/0073_update_direct_paging_integration_non_default_routes.py @@ -0,0 +1,82 @@ +# Generated by Django 4.2.17 on 2025-01-06 15:48 + +import logging + +from django.db import migrations +from django.db.models import Subquery, OuterRef + +logger = logging.getLogger(__name__) + + +def update_direct_paging_integration_non_default_routes(apps, schema_editor): + """ + If any of the original Direct Paging integration default routes had chatops settings or escalation chains + associated with them, simply set the non-default route to have the same settings. This will avoid any functional + differences should users start paging a team using the "important" functionality. + """ + ChannelFilter = apps.get_model("alerts", "ChannelFilter") + + logger.info("Starting update_direct_paging_integration_non_default_routes migration...") + + # 1) Gather all default route data in a dictionary keyed by alert_receive_channel_id + default_direct_paging_routes = ChannelFilter.objects.filter( + alert_receive_channel__integration="direct_paging", + is_default=True + ).values( + "alert_receive_channel_id", + "escalation_chain_id", + "telegram_channel_id", + "notify_in_telegram", + "slack_channel_id", + "notify_in_slack", + "notification_backends", + ) + + default_direct_paging_route_map = { + route["alert_receive_channel_id"]: route for route in default_direct_paging_routes + } + + # 2) Fetch all non-default direct paging routes we want to update + non_default_direct_paging_routes = list(ChannelFilter.objects.filter( + alert_receive_channel__integration="direct_paging", + is_default=False + )) + + # 3) Update them in Python memory + for non_default_route in non_default_direct_paging_routes: + default_route = default_direct_paging_route_map.get(non_default_route.alert_receive_channel_id) + if default_route: + non_default_route.escalation_chain_id = default_route["escalation_chain_id"] + non_default_route.telegram_channel_id = default_route["telegram_channel_id"] + non_default_route.notify_in_telegram = default_route["notify_in_telegram"] + non_default_route.slack_channel_id = default_route["slack_channel_id"] + non_default_route.notify_in_slack = default_route["notify_in_slack"] + non_default_route.notification_backends = default_route["notification_backends"] + + # 4) Bulk update all at once + ChannelFilter.objects.bulk_update( + non_default_direct_paging_routes, + [ + "escalation_chain_id", + "telegram_channel_id", + "notify_in_telegram", + "slack_channel_id", + "notify_in_slack", + "notification_backends", + ], + batch_size=5000, + ) + + logger.info(f"Updated {len(non_default_direct_paging_routes)} non-default direct paging integration routes") + logger.info("Finished update_direct_paging_integration_non_default_routes migration.") + + +class Migration(migrations.Migration): + + dependencies = [ + ("alerts", "0072_upsert_direct_paging_integration_routes"), + ] + + operations = [ + migrations.RunPython(update_direct_paging_integration_non_default_routes, migrations.RunPython.noop), + ]