diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 55285548803..3aa556b032b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -774,7 +774,8 @@ embed.go @grafana/grafana-as-code /.github/workflows/auto-milestone.yml @grafana/grafana-developer-enablement-squad /.github/workflows/backend-code-checks.yml @grafana/grafana-backend-group /.github/workflows/backend-unit-tests.yml @grafana/grafana-backend-group -/.github/workflows/backport.yml @grafana/grafana-developer-enablement-squad +/.github/workflows/backport-trigger.yml @grafana/grafana-developer-enablement-squad +/.github/workflows/backport-workflow.yml @grafana/grafana-developer-enablement-squad /.github/workflows/bump-version.yml @grafana/grafana-developer-enablement-squad /.github/workflows/release-pr.yml @grafana/grafana-developer-enablement-squad /.github/workflows/release-comms.yml @grafana/grafana-developer-enablement-squad diff --git a/.github/workflows/backport-trigger.yml b/.github/workflows/backport-trigger.yml new file mode 100644 index 00000000000..3b3758c573b --- /dev/null +++ b/.github/workflows/backport-trigger.yml @@ -0,0 +1,47 @@ +# We need secrets to backport, but they're not available for actions ran by forks. +# So this workflow is used as a 'trigger', which the backport-workflow.yml will with +# via workflow_run + +name: Backport (trigger) +on: + pull_request: + types: + - closed + - labeled + +permissions: {} + +jobs: + trigger: + # Only run this job if the PR has been merged and has a label containing "backport v" + if: | + github.repository == 'grafana/grafana' && + github.event.pull_request.merged == true && + contains(join(github.event.pull_request.labels.*.name, ','), 'backport v') + runs-on: ubuntu-latest + steps: + # TODO: save this as job summary instead? + - name: Trigger + run: | + echo "Triggering workflow" + echo "See https://github.com/${{ github.repository }}/actions/workflows/workflow_run.yml for progress" + + # Create a JSON artifact with details of this PR to pass to the backport workflow. + # The { action: 'labelled', label: 'backport-1.23.x' } can only be determined from this event payload, + # and is needed to do a backport after a PR has been merged + # + # Important that we don't run *anything* from the PR which could modify the backport_data.json file + - name: Create action data + run: | + jq '{ + action: .action, + label: .label.name, + pr_number: .number, + }' "$GITHUB_EVENT_PATH" > /tmp/pr_info.json + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: pr_info + path: /tmp/pr_info.json + retention-days: 1 diff --git a/.github/workflows/backport-workflow.yml b/.github/workflows/backport-workflow.yml new file mode 100644 index 00000000000..925c6c54bb3 --- /dev/null +++ b/.github/workflows/backport-workflow.yml @@ -0,0 +1,88 @@ +# Runs the actual backport, after being triggered by the backport-trigger.yml workflow. + +name: Backport (workflow) +run-name: "Backport for ${{ github.event.workflow_run.head_branch }} #${{ github.event.workflow_run.run_number }}" +on: + workflow_run: # zizmor: ignore[dangerous-triggers] backport-trigger.yml does not run any user code + workflows: ["Backport (trigger)"] + types: + - completed + +permissions: {} + +jobs: + backport: + # Only run this job if the triggering workflow was not skipped (and on grafana repo) + if: github.repository == 'grafana/grafana' && github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + permissions: + id-token: write + actions: read + steps: + - name: Get vault secrets + id: secrets + uses: grafana/shared-workflows/actions/get-vault-secrets@main + with: + export_env: false + # Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault + repo_secrets: | + APP_PEM=delivery-bot-app:PRIVATE_KEY + + - name: Generate token + id: generate_token + uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 + with: + app_id: ${{ vars.DELIVERY_BOT_APP_ID }} + private_key: ${{ fromJSON(steps.secrets.outputs.secrets).APP_PEM }} + + - name: Download PR info artifact + uses: actions/download-artifact@v4 + id: download-pr-info + with: + github-token: ${{ github.token }} + run-id: ${{ github.event.workflow_run.id }} + name: pr_info + + - name: Get PR info + id: pr-info + env: + PR_INFO_FILE: ${{ steps.download-pr-info.outputs.download-path }}/pr_info.json + # jq-magic to convert the JSON object into a list of key=value pairs for $GITHUB_OUTPUT + run: + jq -r 'to_entries[] | select(.value | type != "object") | "\(.key)=\(.value)"' "$PR_INFO_FILE" >> "$GITHUB_OUTPUT" + + - name: Print PR info + env: + PR_ACTION: ${{ steps.pr-info.outputs.action }} + PR_LABEL: ${{ steps.pr-info.outputs.label }} + PR_NUMBER: ${{ steps.pr-info.outputs.pr_number }} + run: | + echo "PR action: $PR_ACTION" + echo "PR label: $PR_LABEL" + echo "PR number: $PR_NUMBER" + + - name: Checkout Grafana + uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + fetch-depth: 2 + fetch-tags: false + token: ${{ steps.generate_token.outputs.token }} + persist-credentials: true + + - name: Configure git user + run: | + git config --local user.name "github-actions[bot]" + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local --add --bool push.autoSetupRemote true + + - name: Run backport + uses: grafana/grafana-github-actions-go/backport@dev + with: + token: ${{ steps.generate_token.outputs.token }} + # If triggered by being labelled, only backport that label. + # Otherwise, the action will backport all labels. + pr_label: ${{ steps.pr-info.outputs.action == 'labeled' && steps.pr-info.outputs.label || '' }} + pr_number: ${{ steps.pr-info.outputs.pr_number }} + repo_owner: ${{ github.repository_owner }} + repo_name: ${{ github.event.repository.name }} diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml deleted file mode 100644 index 1fc13807d3b..00000000000 --- a/.github/workflows/backport.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Backport PR Creator -on: - pull_request: - types: - - closed - - labeled - -jobs: - # TODO: This workflow won't work for forks because no secrets are available. - # This should, at the least, post the comment with manual backport instructions. - main: - if: github.repository == 'grafana/grafana' - runs-on: ubuntu-latest - permissions: - id-token: write - steps: - - name: Get vault secrets - id: vault-secrets - uses: grafana/shared-workflows/actions/get-vault-secrets@main - with: - # Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault - repo_secrets: | - GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY - - - name: Generate token - id: generate_token - uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 - with: - app_id: ${{ vars.DELIVERY_BOT_APP_ID }} - private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }} - - - name: Checkout Grafana - uses: actions/checkout@v4 - with: - ref: main - fetch-depth: 2 - fetch-tags: false - token: ${{ steps.generate_token.outputs.token }} - persist-credentials: true - - - name: Configure git user - run: | - git config --local user.name "github-actions[bot]" - git config --local user.email "github-actions[bot]@users.noreply.github.com" - git config --local --add --bool push.autoSetupRemote true - - - name: Run backport - uses: grafana/grafana-github-actions-go/backport@main - with: - token: ${{ steps.generate_token.outputs.token }}