diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a5aff6aa..41721262b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,11 +3,11 @@ name: Release run-name: Release ${{ inputs.tag || github.ref_name }} at ${{ inputs.release_commit || github.sha }} on: - # PHP Server releases are 2.x and earlier; plain tags from 3.0 are native - # releases (native-release.yml). - push: - tags: - - '[0-2].[0-9]+.[0-9]+*' + # Retired: PHP Server 2.11.8 is the final PHP release (server#1002). No tag + # starts this workflow, and its publish job never runs (`if: false`), so it + # never loads the registry logins or holds contents: write. It stays as the + # reviewed record of how 2.x images were published, for its contract tests. + # Native releases are native-release.yml. workflow_dispatch: inputs: tag: @@ -46,10 +46,9 @@ jobs: concurrency: group: durable-workflow-server-rolling-aliases cancel-in-progress: false - if: >- - (github.event_name == 'workflow_dispatch' && - github.ref == 'refs/heads/main') || - (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) + # Retired (server#1002): a skipped job starts no runner, so none of its + # secrets or write permissions are ever loaded. + if: false permissions: contents: write packages: write diff --git a/scripts/ci/check-native-release-tags.sh b/scripts/ci/check-native-release-tags.sh index bb21b521c..fd4ec8879 100755 --- a/scripts/ci/check-native-release-tags.sh +++ b/scripts/ci/check-native-release-tags.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash # Native release-candidate tags are their own Git tags, native- # (Server #325). Check that: -# - the PHP Release workflow's push-tag filter matches no native- tag, so a -# native tag starts no PHP release, and still matches plain versions; +# - the retired PHP Release workflow (server#1002) has no push trigger, so +# no tag starts it, and its publish job never runs; # - the tag verifier accepts native- only when asked for it; # - the native publisher accepts only native- tags, and lets only a release # candidate (-rc.N) skip Docker Hub. @@ -10,35 +10,18 @@ set -euo pipefail fail() { printf 'Native release tag check failed: %s\n' "$1" >&2; exit 1; } -# The tag patterns under release.yml's push trigger. -mapfile -t patterns < <(awk ' - /^ push:/ { push = 1; next } - push && /^ [a-z_]+:/ { push = 0 } - push && /^ tags:/ { tags = 1; next } - tags && /^ - / { sub(/^ - /, ""); gsub(/\x27|"/, ""); print; next } - tags { tags = 0 } +# The retired PHP Release workflow (server#1002): no push trigger at all, so +# no tag of any kind starts it, and its publish job is `if: false`, so it never +# loads the registry logins or contents: write. +release_triggers=$(awk ' + /^on:/ { on = 1; next } + on && /^[^ #]/ { on = 0 } + on && /^ [a-z_]+:/ { sub(/^ /, ""); sub(/:.*/, ""); print } ' .github/workflows/release.yml) -test "${#patterns[@]}" -ge 1 || fail "release.yml has no push tag patterns." - -# A GitHub filter pattern as an anchored extended regular expression: -# [..] and + keep their meaning, * matches anything but /, the rest is literal. -matches() { - local pattern=$1 tag=$2 regex - regex=$(printf '%s' "$pattern" | sed -e 's/[.]/\\./g' -e 's#[*]#[^/]*#g') - [[ $tag =~ ^${regex}$ ]] -} -for pattern in "${patterns[@]}"; do - for tag in native-2.12.0-rc.1 native-2.11.4 native-3.0.0 3.0.2 3.1.0-rc.1 10.0.0; do - if matches "$pattern" "$tag"; then fail "release.yml tag pattern $pattern matches $tag."; fi - done -done -for tag in 2.11.4 2.12.0-rc.1; do - matched=0 - for pattern in "${patterns[@]}"; do - if matches "$pattern" "$tag"; then matched=1; fi - done - test "$matched" = 1 || fail "no release.yml tag pattern matches the plain version $tag." -done +test "$release_triggers" = workflow_dispatch \ + || fail "the retired release.yml must have only workflow_dispatch, not: $(echo $release_triggers)." +grep -qx ' if: false' <(sed -n '/^ publish:$/,/^ [a-z-]*:$/p' .github/workflows/release.yml) \ + || fail "the retired release.yml publish job must be if: false." expect() { local message=$1; shift @@ -480,4 +463,4 @@ grep -q 'run: scripts/ci/verify-native-release-dispatch.sh' .github/workflows/na # the native Release job may write releases. grep -q 'name: Refuse a native release tag' .github/workflows/release.yml \ || fail "release.yml must refuse a 3.x or native- tag." -printf 'Native release tags: %d release.yml pattern(s) checked; verifier, publisher and rolling tags behave as intended.\n' "${#patterns[@]}" +printf 'Native release tags: retired release.yml cannot start or publish; verifier, publisher and rolling tags behave as intended.\n' diff --git a/tests/Unit/ReleaseImagePublishWorkflowContractTest.php b/tests/Unit/ReleaseImagePublishWorkflowContractTest.php index 48c3cb037..b75065011 100644 --- a/tests/Unit/ReleaseImagePublishWorkflowContractTest.php +++ b/tests/Unit/ReleaseImagePublishWorkflowContractTest.php @@ -53,13 +53,13 @@ public function test_release_publish_job_is_guarded_before_registry_login(): voi $parsedWorkflow = Yaml::parse($workflow); $this->assertIsArray($parsedWorkflow); - $publishCondition = $parsedWorkflow['jobs']['publish']['if'] ?? null; - $this->assertIsString($publishCondition); - $this->assertSame( - "(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') " - ."|| (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))", - preg_replace('/\s+/', ' ', trim($publishCondition)), - ); + // Retired (server#1002): PHP Server 2.11.8 is final. No tag starts the + // workflow, and its publish job never runs, so it never loads the + // registry logins or contents: write. + $this->assertSame(false, $parsedWorkflow['jobs']['publish']['if'] ?? null); + $triggers = $parsedWorkflow['on'] ?? $parsedWorkflow[true] ?? null; + $this->assertIsArray($triggers); + $this->assertSame(['workflow_dispatch'], array_keys($triggers)); $guardOffset = strpos($workflow, 'Validate release publish context and credentials'); $dockerHubLoginOffset = strpos($workflow, 'Log in to Docker Hub');