diff --git a/.github/ci/ci-tests/test_package_release_workflow.py b/.github/ci/ci-tests/test_package_release_workflow.py index b446cd63f5..5475c65fbb 100644 --- a/.github/ci/ci-tests/test_package_release_workflow.py +++ b/.github/ci/ci-tests/test_package_release_workflow.py @@ -19,7 +19,6 @@ def action_references(workflow: str) -> list[str]: def test_workflow_selects_an_immutable_release_source(): workflow = workflow_text() assert 'workflow_dispatch:' in workflow - assert 'pull_request_target:' not in workflow assert 'refs/heads/release/bind-rp/$series' in workflow assert 'refs/pull/$INPUT_PULL_NUMBER/head' in workflow assert 'gh api "repos/$GITHUB_REPOSITORY/pulls/$INPUT_PULL_NUMBER" --jq .base.ref' in workflow @@ -30,6 +29,22 @@ def test_workflow_selects_an_immutable_release_source(): assert 'git checkout "$SOURCE_COMMIT" -- .resolver-plugins/upstream.json Mk dns/bind' in workflow +def test_merged_release_source_pr_publishes_its_exact_merge_commit(): + workflow = workflow_text() + trigger = workflow.split(' pull_request_target:', 1)[1].split(' workflow_dispatch:', 1)[0] + select = workflow.split(' select:', 1)[1].split(' profile:', 1)[0] + + assert "pull_request_target:\n types: [closed]\n branches:\n - 'release/bind-rp/**'" in workflow + for path in ("'.resolver-plugins/**'", "'dns/bind/**'", "'Mk/**'"): + assert path in trigger + assert "if: github.event_name != 'pull_request_target' || github.event.pull_request.merged == true" in select + assert '[[ "$PR_MERGED" == true ]]' in select + assert '[[ "$PR_BASE_REF" =~ ^release/bind-rp/([0-9]+\\.[0-9]+)$ ]]' in select + assert 'source_ref="$PR_MERGE_COMMIT"' in select + assert 'control_ref="$GITHUB_WORKFLOW_SHA"' in select + assert 'github.event.pull_request.head.sha' not in workflow + + def test_package_affecting_master_pushes_publish_the_newest_release_series(): workflow = workflow_text() diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml index 3d0424dec5..b4262b2f6b 100644 --- a/.github/workflows/package-release.yml +++ b/.github/workflows/package-release.yml @@ -15,6 +15,14 @@ on: - 'docs/package-repository/resolver-plugins.pub' - 'dns/bind/**' - 'Mk/**' + pull_request_target: + types: [closed] + branches: + - 'release/bind-rp/**' + paths: + - '.resolver-plugins/**' + - 'dns/bind/**' + - 'Mk/**' workflow_dispatch: inputs: mode: @@ -56,6 +64,7 @@ jobs: run: python -m pytest -q .github/ci/ci-tests select: + if: github.event_name != 'pull_request_target' || github.event.pull_request.merged == true runs-on: ubuntu-24.04 outputs: mode: ${{ steps.select.outputs.mode }} @@ -70,7 +79,11 @@ jobs: env: GITHUB_REF: ${{ github.ref }} GITHUB_SHA: ${{ github.sha }} + GITHUB_WORKFLOW_SHA: ${{ github.workflow_sha }} EVENT_NAME: ${{ github.event_name }} + PR_BASE_REF: ${{ github.event.pull_request.base.ref }} + PR_MERGE_COMMIT: ${{ github.event.pull_request.merge_commit_sha }} + PR_MERGED: ${{ github.event.pull_request.merged }} INPUT_MODE: ${{ inputs.mode }} INPUT_SERIES: ${{ inputs.series }} INPUT_PULL_NUMBER: ${{ inputs.pull_number }} @@ -84,6 +97,11 @@ jobs: sed -nE 's#^refs/heads/release/bind-rp/([0-9]+\.[0-9]+)$#\1#p' | sort -V | tail -n 1) + elif [[ "$EVENT_NAME" == pull_request_target ]]; then + [[ "$PR_MERGED" == true ]] + [[ "$PR_BASE_REF" =~ ^release/bind-rp/([0-9]+\.[0-9]+)$ ]] + mode=production + series="${BASH_REMATCH[1]}" else mode="$INPUT_MODE" series="$INPUT_SERIES" @@ -105,11 +123,18 @@ jobs: prerelease_tag="pr-$INPUT_PULL_NUMBER-$series" control_ref=$GITHUB_SHA else - [[ "$GITHUB_REF" == refs/heads/master ]] pull_number="" - source_ref="refs/heads/release/bind-rp/$series" prerelease_tag="" - control_ref=$GITHUB_SHA + if [[ "$EVENT_NAME" == pull_request_target ]]; then + [[ "$PR_MERGE_COMMIT" =~ ^[0-9a-f]{40}$ ]] + [[ "$GITHUB_WORKFLOW_SHA" =~ ^[0-9a-f]{40}$ ]] + source_ref="$PR_MERGE_COMMIT" + control_ref="$GITHUB_WORKFLOW_SHA" + else + [[ "$GITHUB_REF" == refs/heads/master ]] + source_ref="refs/heads/release/bind-rp/$series" + control_ref=$GITHUB_SHA + fi fi { printf 'mode=%s\n' "$mode" diff --git a/docs/building.md b/docs/building.md index 62b663b37c..b9618dd1a9 100644 --- a/docs/building.md +++ b/docs/building.md @@ -41,9 +41,12 @@ scripts. In particular, the release `Mk` files prevent a development-branch marker from adding an unintended `-devel` package suffix. Package-affecting pushes to `master` automatically run production for the -newest numeric `release/bind-rp/` branch. Manual dispatch remains -available for an explicit series or development build. Release-source branches -provide immutable inputs and do not execute publication helpers themselves. +newest numeric `release/bind-rp/` branch. Merging a package-affecting +pull request into a release-source branch automatically runs production for +that series, pinned to the merge commit. The workflow and publication helpers +still come from the trusted `master` control plane. Closing a pull request +without merging does not build a release. Manual dispatch remains available +for an explicit series or development build. Reproduce that split in a disposable worktree when building locally. Start from `master`, fetch the selected release branch, and overlay only its release