jdaugherty commented on code in PR #16229: URL: https://github.com/apache/grails-core/pull/16229#discussion_r4326746255
########## .github/workflows/release-atr-announce.yml: ########## @@ -0,0 +1,137 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Experimental Apache Trusted Releases (ATR) announce step. +# Sends ONE announcement through ATR. The first successful announce promotes +# the candidate from preview to released, so this workflow must not be rerun +# for additional mailing lists. The recipient is restricted to [email protected]. +# ATR documentation and the official workflow example: +# https://tooling.apache.org/ +# https://github.com/apache/tooling-asf-example/blob/main/.github/workflows/announce-release-on-atr.yaml +# After it succeeds, send the remaining lists by hand from your @apache.org +# address: [email protected], [email protected], and +# [email protected]. +# +# Prerequisites (see RELEASE.md "Experimental: Apache Trusted Releases"): +# * This workflow listed under the project's ATR finish workflow paths +# * Vote already resolved as passed on ATR +name: "Release - ATR Announce (experimental)" +on: + workflow_dispatch: + inputs: + version: + description: 'Release version without the v prefix (e.g. 7.0.0 or 8.0.0-M1)' + required: true + type: string + previous_version: + description: 'Previous released version without the v prefix, used in the compare URL' + required: true + type: string + announce_email_to: Review Comment: This input can only ever hold `[email protected]`; any other value fails the first step. Drop the input and hardcode the recipient in the step. An input that exists only to be rejected invites someone to try the project lists through it. ########## build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/RepositoryConventionsTask.groovy: ########## @@ -51,8 +51,10 @@ abstract class RepositoryConventionsTask extends DefaultTask { private static final Pattern DOCKER_IMAGE_DIGEST = Pattern.compile(/^docker:\/\/[^@\s]+@sha256:[0-9a-f]{64}$/) private static final Pattern CONTAINER_IMAGE_DIGEST = Pattern.compile(/^[^@\s]+@sha256:[0-9a-f]{64}$/) // GitHub-official and first-party ASF actions track upstream ASF approvals, so they use version or - // branch references and are never pinned to a commit SHA. + // branch references and are never pinned to a commit SHA. apache/tooling-actions is the exception: Review Comment: AGENTS.md (CLAUDE.md links to it) still states the rule this relaxes: critical rule 12 says `apache/*` use "version or branch references, never SHAs", and the GitHub Actions section says "Never pin either by SHA". Please add the `apache/tooling-actions` exception there too, with the reason (untagged, full hash required by ATR Trusted Publishing), so the guide and the gate agree. ########## RELEASE.md: ########## @@ -433,6 +439,83 @@ Announcements should come from your apache email address (see https://infra.apac expected format. The announcement should be sent to `[email protected]`, `[email protected]`, `[email protected]`, & `[email protected]`. See the `close` job for a generated email. +### What GitHub Actions may automate + +The following boundaries preserve PMC authority and use only opt-in, protected workflows. Apache's release policy permits +automated release infrastructure to sign artifacts, while the vote remains a community email process. + +| Activity | GitHub Actions boundary and evidence | +| --- | --- | +| ATR compose, resolve, one announce, and distribution record | Opt-in workflows call [ASF Tooling actions](https://github.com/apache/tooling-actions) against [ATR Beta](https://releases.apache.org/docs/). Official examples: [compose](https://github.com/apache/tooling-asf-example/blob/main/.github/workflows/build-and-rsync-to-atr.yaml), [resolve](https://github.com/apache/tooling-asf-example/blob/main/.github/workflows/resolve-vote-on-atr.yaml), [announce](https://github.com/apache/tooling-asf-example/blob/main/.github/workflows/announce-release-on-atr.yaml), and [record](https://github.com/apache/tooling-asf-example/blob/main/.github/workflows/record-distribution-on-atr.yaml). | +| Signing in GitHub Actions | [Apache release policy](https://www.apache.org/legal/release-policy.html) requires release artifacts to be signed by the Release Manager or automated release infrastructure. ATR [Trusted Publishing](https://releases.apache.org/docs/trusted-publishing) accepts those signatures when the committee is eligible for CI builds. | +| Publish the voted distributions to `dist/release` | Beta ATR commits the approved artifacts to `svn:dist:release` itself. The workflow calls ATR. It does not write SVN. See [Promoting to release](https://releases.apache.org/docs/promoting-to-release). | +| Documentation and website content | [GitHub Actions policy](https://infra.apache.org/github-actions-policy.html) permits work on website content and other non-released data. Grails already deploys documentation from GitHub Actions. | +| Promote closed Nexus staging after a passed vote | `Release - Promote Nexus Staging` is `workflow_dispatch` plus the protected `release` environment. It follows the [Apache Polaris TLP promotion workflow](https://github.com/apache/polaris/blob/7866ce5c009d64e4c1454b47bca3df9873c6c0b2/.github/workflows/release-4-publish-release.yml) and uses the existing `NEXUS_STAGE_DEPLOYER_USER` / `NEXUS_STAGE_DEPLOYER_PW` secrets used to drop staging. | +| Skip `dist/dev` only when using ATR | ATR candidates may skip the traditional staging location as described in [Staging and voting](https://releases.apache.org/docs/staging-and-voting). The `dist/dev` plus Nexus path remains Grails' official default until the PMC opts in to ATR. | + +The following must remain manual: + +| Activity | Why it remains manual | +| --- | --- | +| Start the binding PMC vote and hold it for at least 72 hours | [Apache release policy](https://www.apache.org/legal/release-policy.html) says release votes SHOULD remain open for at least 72 hours. ATR can send and tally the vote email, but `apache/tooling-actions` has no action that starts a vote. | +| Move `dist/dev` distributions when ATR is not used | [GitHub Actions policy](https://infra.apache.org/github-actions-policy.html) prohibits automated services from pushing official release data without prior Infrastructure authorization. The default Grails path still uses `releaseDistributions.sh` as the release manager. | +| Rebuild and compare artifacts on trusted hardware | Trusted Publishing requires an independent rebuild outside GitHub Actions before publication. Grails already documents that comparison in this file. | +| Report the release to ASF Reporter | [ASF Reporter addrelease](https://reporter.apache.org/addrelease.html) has no documented public API. | +| Send lists beyond the one ATR announcement | ATR rejects a second announcement for the same release. Send `[email protected]`, `[email protected]`, and `[email protected]` manually after the single ATR announce. | +| Forge, SDKMAN!, the static website, and the blog | ATR records external distributions. It does not publish those Grails channels. | + +ATR Beta on `releases.apache.org` publishes finished releases directly to `svn:dist:release`. The PMC email that announces Beta to `pmcs@` is still tracked by [tooling-trusted-releases#1520](https://github.com/apache/tooling-trusted-releases/issues/1520). That open issue does not keep the platform on Alpha. + +## Apache Trusted Releases (ATR) + +[ASF Tooling](https://tooling.apache.org/) runs [Apache Trusted Releases](https://releases.apache.org/) to automate compose, vote, and finish. ATR is **Beta**. The existing `dist/dev` to `dist/release` and Nexus staging path remains the official Grails process until the PMC opts in. See the [ATR documentation](https://releases.apache.org/docs/) and [apache/tooling-actions](https://github.com/apache/tooling-actions). + +The workflows pin `apache/tooling-actions` to `dcba9f4ed2956f7a30113c3067e766eeda37d891` (`main` on 2026-10-08). [Trusted Publishing](https://releases.apache.org/docs/trusted-publishing) says these actions are not tagged and must be referenced by a full commit hash, not `@main`. Other `apache/*` actions stay on a branch. `validateRepositoryConventions` requires that commit hash for `apache/tooling-actions/*` and still rejects a commit hash for every other `apache/*` action. + +| Manual step today | Tooling action | Grails workflow | +| --- | --- | --- | +| Upload source, binary, wrapper, and docs zips | `upload-to-atr` | `Release - ATR Upload (experimental)`, or `atr_upload` in `release.yml` when `ATR_ENABLED=true` | +| Send the `[VOTE]` email | none (start the vote in the [ATR UI](https://releases.apache.org/) or with `atr vote start`) | — | +| Send the `[RESULT][VOTE]` email | `release-on-atr` with `resolve: true` | `Release - ATR Resolve Vote (experimental)` | +| Publish the voted zips to `dist/release` | ATR, when automatic publication was selected at vote start, or the Publish button | not a GitHub Actions SVN write | +| Promote Nexus staging to Maven Central | none | `Release - Promote Nexus Staging`, then `Release - ATR Record Distribution (experimental)` with `platform=MAVEN` | +| Send the `[ANNOUNCE]` email | `release-on-atr` with `announce: true` | `Release - ATR Announce (experimental)` once, to `[email protected]` | +| ASF Reporter, Forge, SDKMAN!, website, blog | none | unchanged | + +### Opt-in setup + +1. Log in at https://releases.apache.org/ with ASF credentials and confirm the Grails project. Discuss on [[email protected]](https://lists.apache.org/[email protected]) / [#apache-trusted-releases](https://the-asf.slack.com/archives/C049WADAAQG). +2. Set the project download path suffix to `core/{{VERSION}}`. Grails publishes under `dist/release/grails/core/<version>/`, not in the committee root next to `KEYS`. +3. Configure [Trusted Publishing](https://releases.apache.org/docs/trusted-publishing) for repository `grails-core`: + + * Compose: `.github/workflows/release.yml` and `.github/workflows/release-atr-upload.yml` + * Vote: `.github/workflows/release-atr-resolve.yml` + * Finish: `.github/workflows/release-atr-announce.yml` and `.github/workflows/release-atr-record.yml` + +4. The committee page must show CI builds enabled. That requires a signing key whose primary UID contains `Automated Release Signing` and whose email is `[email protected]`. The release workflow imports `GRAILS_GPG_KEY` and signs with `GPG_KEY_ID`. Confirm that selected key matches this UID before the workflows will be accepted. If it does not, ask Infrastructure for a key that does. Voters still compare an independent rebuild on trusted hardware with the uploaded artifacts. Review Comment: This prerequisite is already met, so the step should say so rather than hedge. The only key in KEYS is `Apache Grails Automated Release Signing <[email protected]>` (RSA 4096, fingerprint `08E2 CEC4 7E38 FE41 5F08 0AB6 2ADE CADC 1177 5306`, issued by Infra in May 2025), and the 7.0.6 and 8.0.0-RC2 signatures were made with it (key id `2ADECADC11775306`), so the release workflow already signs with the automated key. Please replace "Confirm that selected key matches this UID ... ask Infrastructure for a key that does" with a statement that the Infra-issued key in KEYS satisfies this, so the next release manager does not go looking for a key to compare. ########## .github/workflows/release-promote-jars.yml: ########## @@ -0,0 +1,83 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Apache Polaris, a TLP, promotes a closed staging repository after its vote: +# https://github.com/apache/polaris/blob/7866ce5c009d64e4c1454b47bca3df9873c6c0b2/.github/workflows/release-4-publish-release.yml +# Grails already uses the same NEXUS_STAGE_DEPLOYER_* secrets in +# release-drop-staging.yml. This workflow never writes dist.apache.org/release: +# https://infra.apache.org/github-actions-policy.html +name: "Release - Promote Nexus Staging" +on: + workflow_dispatch: + inputs: + version: + description: 'Release version without the v prefix (e.g. 8.0.0-M1)' + required: true + type: string + staging_description: + description: 'Nexus staging repository description (defaults to <repository>:<version>)' + required: false + type: string + default: '' + repository: + description: 'Repository name used only for the default staging description' + required: false + type: string + default: grails-core +permissions: + contents: read +jobs: + promote: + name: "Promote Nexus staging repository" + environment: release + # Keep the release environment restricted to trusted refs. + runs-on: ubuntu-24.04 + steps: + - name: "📥 Checkout the workflow ref" + uses: actions/[email protected] + with: + persist-credentials: false + - name: "📝 Establish staging description" + env: + VERSION: ${{ inputs.version }} + STAGING_DESCRIPTION_INPUT: ${{ inputs.staging_description }} + REPOSITORY: ${{ inputs.repository }} + run: | + set -euo pipefail + if [ -z "${VERSION}" ]; then + echo "::error::Version must not be empty." + exit 1 + fi + if [ -n "${STAGING_DESCRIPTION_INPUT}" ]; then + echo "STAGING_DESCRIPTION=${STAGING_DESCRIPTION_INPUT}" >> "$GITHUB_ENV" + else + echo "STAGING_DESCRIPTION=${REPOSITORY}:${VERSION}" >> "$GITHUB_ENV" + fi + - name: "🚀 Promote Nexus staging repository" + env: + NEXUS_USER: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }} Review Comment: I went looking for evidence either way and found none that this account can promote. Nothing on infra.apache.org says what the stage-deployer role may do beyond deploy, close and drop. The Polaris workflow this PR cites has no run on record that reached its Nexus release step: the real runs failed earlier, and the step logs of its two green runs have expired, so whether those were dry runs (the workflow's default) is unknowable. parquet-java has the same design with zero runs, and OpenDAL's Java artifacts on Central are not at the version its workflow reported released. So the precedent is a design, not a demonstration. Before this merges, please either dispatch the workflow against the closed staging repo of the next milestone or ask Infra in a ticket, and until one of those succeeds, drop the "prefer this workflow" wording in RELEASE.md and in the release job's echo so the documented path stays the one we know works. ########## RELEASE.md: ########## @@ -325,29 +326,34 @@ Confirm the Grails PMC votes passed with a +1 from at least 3 PMC members. The ` ### Release the Staged Jar files -The `release` job in the `Release` workflow has a step entitled `🚀 Release JAR files - MANUAL`. You can release the jar -files by one of 2 ways: +After the PMC vote has passed and the protected `release` environment is approved, prefer the opt-in +`Release - Promote Nexus Staging` workflow. Run it from Actions with the version without `v`; leave +`staging_description` empty to use `grails-core:<version>`. This is manually dispatched after the vote, following the +[Apache Polaris TLP precedent](https://github.com/apache/polaris/blob/7866ce5c009d64e4c1454b47bca3df9873c6c0b2/.github/workflows/release-4-publish-release.yml). -1. On https://repository.apache.org/#stagingRepositories, the staged artifacts must be released by opening the `grails-core` staging repository and - clicking the `Release` button. It took almost 2 hours for the initial ASF release to publish these jars to Maven - Central. -2. Alternatively, the `release` job in the `Release` workflow will output an example command line to release the staging - repository via the scripts checked into grails-core. Execute the script & set the placeholder values to release the - jar files. +The following remain fallbacks: + +1. On https://repository.apache.org/#stagingRepositories, release the staged artifacts by opening the `grails-core` staging repository and + clicking the `Release` button. It took almost 2 hours for the initial ASF release to publish these jars to Maven + Central. +2. Run `.github/scripts/releaseJarFiles.sh grails-core:<version> <ASF_USER>`. The script prompts for a password unless + `NEXUS_PASS` is already set, which is how the protected workflow supplies its secret. ### Move the distributions from `dev` to `release` -On dist.apache.org, the staged source distribution, binary distributions & documentation distribution must be moved from `https://dist.apache.org/repos/dist/dev/grails/` to `https://dist.apache.org/repos/dist/release/grails/`. Per ASF -infrastructure, this must be performed manually, and we are not allowed to automate it via a gated approval workflow. -Either move them via your SVN client or use the checked in script to perform these actions as your user. +If this candidate was staged on ATR, skip this `dist/dev` move. Beta ATR commits the voted artifacts directly to `svn:dist:release` when the release is published. Set the Grails project's download path suffix to `core/{{VERSION}}` so the tree is `dist/release/grails/core/<version>/`, which is where the source, binary, wrapper, and documentation distributions belong. Do not run `releaseDistributions.sh` for an ATR candidate, and do not move anything out of `dist/atr`. See [Apache Trusted Releases (ATR)](#apache-trusted-releases-atr). Review Comment: Two things `releaseDistributions.sh` does are lost on the ATR path and nothing here picks them up. The `upload` job still commits the candidate to `dist/dev/grails/core/<version>` whether or not `ATR_ENABLED` is set, and with the `svn mv` skipped that copy stays there for good (the abort workflow has the exact `svnmucc rm` for it). And the script's loop that offers to remove the prior release folder from `dist/release` never runs, so old releases accumulate until someone prunes them by hand; the auto-archive caveat in the ATR section only says not to let ATR do it. Please either gate the SVN steps of `upload` on `ATR_ENABLED` not being `true` (the job itself has to stay, `release` needs it) or add both the `svn rm` of the dev copy and the prior-release pruning to the ATR **Publish** step. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
