blob: e758346cbad2494b4fcf366bb5d962c8aa013c81 [file]
# 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.
name: "Release"
on:
release:
types: [published]
permissions:
contents: write
packages: read
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
publish:
name: "Stage Jar Files"
permissions:
packages: read # pre-release workflow
contents: write # to create release
issues: write # to modify milestones
runs-on: ubuntu-24.04
outputs:
release_version: ${{ steps.release_version.outputs.value }}
commit_hash: ${{ steps.commit_hash.outputs.value }}
extract_repository_name: ${{ steps.extract_repository_name.outputs.repository_name }}
steps:
- name: "📝 Store the current release version"
id: release_version
run: |
export RELEASE_VERSION="${GITHUB_REF:11}"
echo "Found Release Version: ${RELEASE_VERSION}"
echo "value=${RELEASE_VERSION}" >> $GITHUB_OUTPUT
- name: "Output Agent IP" # in the event RAO blocks this agent, this can be used to debug it
run: curl -s https://api.ipify.org
- name: "Extract repository name"
id: extract_repository_name
run: |
echo "repository_name=${GITHUB_REPOSITORY##*/}" >> $GITHUB_OUTPUT
- name: "📥 Checkout repository"
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: v${{ steps.release_version.outputs.value }}
- name: 'Ensure Common Build Date' # to ensure a reproducible build
run: echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> "$GITHUB_ENV"
- name: "Ensure source files use common date"
run: |
find . -depth \( -type f -o -type d \) -exec touch -d "@${SOURCE_DATE_EPOCH}" {} +
- name: '🔐 Set up GPG'
run: |
echo "${{ secrets.GRAILS_GPG_KEY }}" | gpg --batch --import
gpg --list-keys
env:
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
- name: "☕️ Setup JDK"
uses: actions/setup-java@v4
with:
distribution: liberica
java-version: '17.0.15' # this must be a specific version for reproducible builds
- name: "🐘 Setup Gradle"
uses: gradle/actions/setup-gradle@v4
with:
develocity-access-key: ${{ secrets.GRAILS_DEVELOCITY_ACCESS_KEY }}
- name: "⚙️ Run pre-release"
uses: apache/grails-github-actions/pre-release@asf
env:
RELEASE_VERSION: ${{ steps.release_version.outputs.value }}
- name: 'Fetch release Commit Hash'
id: commit_hash
env:
OWNER: ${{ github.repository_owner }}
REPO: ${{ steps.extract_repository_name.outputs.repository_name }}
TAG: 'v${{ steps.release_version.outputs.value }}'
run: |
ref_json=$(gh api "repos/$OWNER/$REPO/git/ref/tags/$TAG")
type=$(jq -r '.object.type' <<<"$ref_json")
sha=$(jq -r '.object.sha' <<<"$ref_json")
if [ "$type" = "tag" ]; then
sha=$(gh api "repos/$OWNER/$REPO/git/tags/$sha" --jq '.object.sha')
fi
echo "Found Commit Sha: $sha"
echo "value=$sha" >>"$GITHUB_OUTPUT"
- name: "📤 Publish to staging repository"
env:
GRAILS_PUBLISH_RELEASE: 'true'
NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
NEXUS_PUBLISH_PASSWORD: ${{ secrets.NEXUS_STAGE_DEPLOYER_PW }}
NEXUS_PUBLISH_URL: 'https://repository.apache.org/service/local/'
NEXUS_PUBLISH_STAGING_PROFILE_ID: ${{ secrets.STAGING_PROFILE_ID }}
NEXUS_PUBLISH_DESCRIPTION: '${{ steps.extract_repository_name.outputs.repository_name }}:${{ steps.release_version.outputs.value }}'
SIGNING_KEY: ${{ secrets.GPG_KEY_ID }}
run: >
./gradlew
publishToSonatype
closeSonatypeStagingRepository
aggregateChecksums
aggregatePublishedArtifacts
- name: "Upload checksums"
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
with:
files: build/CHECKSUMS.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Upload published artifacts"
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
with:
files: build/PUBLISHED_ARTIFACTS.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Generate Build Date file"
run: echo "$SOURCE_DATE_EPOCH" >> build/BUILD_DATE.txt
- name: "Upload Build Date file"
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
with:
files: build/BUILD_DATE.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
source:
# to ensure we never publish any build artifacts, run the source distribution as a separate build workflow
name: "Create Source Distribution"
needs: publish
permissions:
contents: write
runs-on: ubuntu-24.04
steps:
- name: "📥 Checkout repository"
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: v${{ needs.publish.outputs.release_version }}
path: ${{ needs.publish.outputs.extract_repository_name }}
- name: "🗑️ Remove unnecessary files"
run: |
rm -f ${{ needs.publish.outputs.extract_repository_name }}/gradle/wrapper/gradle-wrapper.jar
rm -f ${{ needs.publish.outputs.extract_repository_name }}/gradle/wrapper/gradle-wrapper.properties
rm -f ${{ needs.publish.outputs.extract_repository_name }}/gradlew
rm -f ${{ needs.publish.outputs.extract_repository_name }}/gradlew.bat
rm -f ${{ needs.publish.outputs.extract_repository_name }}/.asf.yaml
- name: "📥 Download CHECKSUMS.txt and rename to CHECKSUMS"
working-directory: '${{ needs.publish.outputs.extract_repository_name }}'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
release_url=$(gh release view v${{ needs.publish.outputs.release_version }} --json assets --repo ${{ github.repository }} --jq '.assets[] | select(.name == "CHECKSUMS.txt") | .url')
curl -f -L -H "Authorization: token $GH_TOKEN" -o CHECKSUMS "$release_url"
- name: "📥 Download PUBLISHED_ARTIFACTS.txt and rename to PUBLISHED_ARTIFACTS"
working-directory: '${{ needs.publish.outputs.extract_repository_name }}'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
release_url=$(gh release view v${{ needs.publish.outputs.release_version }} --json assets --repo ${{ github.repository }} --jq '.assets[] | select(.name == "PUBLISHED_ARTIFACTS.txt") | .url')
curl -f -L -H "Authorization: token $GH_TOKEN" -o PUBLISHED_ARTIFACTS "$release_url"
- name: "📥 Download BUILD_DATE.txt and rename to BUILD_DATE"
working-directory: '${{ needs.publish.outputs.extract_repository_name }}'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
release_url=$(gh release view v${{ needs.publish.outputs.release_version }} --json assets --repo ${{ github.repository }} --jq '.assets[] | select(.name == "BUILD_DATE.txt") | .url')
curl -f -L -H "Authorization: token $GH_TOKEN" -o BUILD_DATE "$release_url"
- name: "📅 Ensure source files use common date"
run: |
SOURCE_DATE_EPOCH=$(cat ${{ needs.publish.outputs.extract_repository_name }}/BUILD_DATE)
find . -depth \( -type f -o -type d \) -exec touch -d "@${SOURCE_DATE_EPOCH}" {} +
- name: "📦 Create source distribution ZIP"
run: |
zip -r "apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip" ${{ needs.publish.outputs.extract_repository_name }} -x '${{ needs.publish.outputs.extract_repository_name }}/.git/*' -x '${{ needs.publish.outputs.extract_repository_name }}/.github/*'
- name: '🔐 Set up GPG'
run: |
echo "${{ secrets.GRAILS_GPG_KEY }}" | gpg --batch --import
gpg --list-keys
env:
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
- name: "🔏 Sign source distribution ZIP"
env:
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
run: |
gpg --default-key "${GPG_KEY_ID}" --batch --yes --pinentry-mode loopback --armor --detach-sign ./apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip
- name: "📦 Create source distribution checksum"
run: |
sha512sum ./apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip > "apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip.sha512"
cat ./apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip.sha512
- name: "🚀 Upload ZIP and Signature to GitHub Release"
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
with:
tag_name: v${{ needs.publish.outputs.release_version }}
files: |
apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip
apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip.sha512
apache-${{ needs.publish.outputs.extract_repository_name }}-${{ needs.publish.outputs.release_version }}-incubating-src.zip.asc
- name: "🗑️ Remove CHECKSUMS.txt asset from release"
working-directory: '${{ needs.publish.outputs.extract_repository_name }}'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -e
gh release delete-asset \
v${{ needs.publish.outputs.release_version }} \
CHECKSUMS.txt \
--repo ${{ github.repository }} \
--yes
- name: "🗑️ Remove BUILD_DATE.txt asset from release"
working-directory: '${{ needs.publish.outputs.extract_repository_name }}'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -e
gh release delete-asset \
v${{ needs.publish.outputs.release_version }} \
BUILD_DATE.txt \
--repo ${{ github.repository }} \
--yes
- name: "🗑️ Remove PUBLISHED_ARTIFACTS.txt asset from release"
working-directory: '${{ needs.publish.outputs.extract_repository_name }}'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -e
gh release delete-asset \
v${{ needs.publish.outputs.release_version }} \
PUBLISHED_ARTIFACTS.txt \
--repo ${{ github.repository }} \
--yes
upload:
name: "Upload Source Distribution"
needs: [ publish, source ]
runs-on: ubuntu-24.04
permissions:
contents: write
env:
SVN_USERNAME: ${{ secrets.SVC_DIST_GRAILS_USERNAME }}
SVN_PASSWORD: ${{ secrets.SVC_DIST_GRAILS_PASSWORD }}
steps:
- name: "🌐 Output Agent IP" # in the event RAO blocks this agent, this can be used to debug it
run: curl -s https://api.ipify.org
- name: "⚙️ Setup SVN and Tools"
run: sudo apt-get install -y subversion subversion-tools tree gettext-base
- name: "👀 Ensure grails dev folder exists"
run: |
set -e
if svn ls https://dist.apache.org/repos/dist/dev/incubator/grails --username "$SVN_USERNAME" --password "$SVN_PASSWORD" --non-interactive; then
echo "Dev Folder 'grails' already exists — skipping creation"
else
echo "Dev Folder 'grails' does not exist, creating"
svnmucc --username "$SVN_USERNAME" --password "$SVN_PASSWORD" --non-interactive \
mkdir https://dist.apache.org/repos/dist/dev/incubator/grails \
-m "Create 'grails' dev folder"
fi
- name: "👀 Ensure grails spring-security folder exists"
run: |
set -e
if svn ls https://dist.apache.org/repos/dist/dev/incubator/grails/spring-security --username "$SVN_USERNAME" --password "$SVN_PASSWORD" --non-interactive; then
echo "Dev Folder 'grails/spring-security' already exists — skipping creation"
else
echo "Dev Folder 'grails/spring-security' does not exist, creating"
svnmucc --username "$SVN_USERNAME" --password "$SVN_PASSWORD" --non-interactive \
mkdir https://dist.apache.org/repos/dist/dev/incubator/grails/spring-security \
-m "Create 'grails spring-security' dev folder"
fi
- name: "📥 Checkout dev repo"
run: |
svn checkout --username "$SVN_USERNAME" --password "$SVN_PASSWORD" --non-interactive https://dist.apache.org/repos/dist/dev/incubator/grails/spring-security dev-repo
- name: "🗑️ Remove existing dev version"
run: |
export VERSION="${{ needs.publish.outputs.release_version }}"
cd dev-repo
if [ -d "$VERSION" ]; then
svn delete "$VERSION"
svn commit -m "Remove grails spring-security dev version $VERSION" --username "$SVN_USERNAME" --password "$SVN_PASSWORD" --non-interactive
else
echo "No existing dev version $VERSION to remove"
fi
- name: "📥 Fetch source distributions"
run: |
export TAG="v${{ needs.publish.outputs.release_version }}"
export VERSION="${{ needs.publish.outputs.release_version }}"
cd dev-repo
mkdir -p $VERSION/sources
cd $VERSION/sources
curl -f -LO https://github.com/apache/${{ needs.publish.outputs.extract_repository_name }}/releases/download/$TAG/apache-${{ needs.publish.outputs.extract_repository_name }}-$VERSION-incubating-src.zip
curl -f -LO https://github.com/apache/${{ needs.publish.outputs.extract_repository_name }}/releases/download/$TAG/apache-${{ needs.publish.outputs.extract_repository_name }}-$VERSION-incubating-src.zip.sha512
curl -f -LO https://github.com/apache/${{ needs.publish.outputs.extract_repository_name }}/releases/download/$TAG/apache-${{ needs.publish.outputs.extract_repository_name }}-$VERSION-incubating-src.zip.asc
echo "Downloaded the following files:"
ls -l
- name: "Upload distributions"
run: |
export TAG="v${{ needs.publish.outputs.release_version }}"
export VERSION="${{ needs.publish.outputs.release_version }}"
cd dev-repo
echo "Adding the following files to SVN:"
tree
svn add $VERSION --force
svn commit -m "Upload grails distribution files for $VERSION" --username "$SVN_USERNAME" --password "$SVN_PASSWORD" --non-interactive
pwd
- name: "💾 Store Distribution SVN revision in a file"
run: |
export VERSION="${{ needs.publish.outputs.release_version }}"
cd dev-repo
svn info $VERSION > "DIST_SVN_REVISION.txt"
- name: "📤 Upload the Distribution SVN revision file"
uses: softprops/action-gh-release@v2
with:
files: dev-repo/DIST_SVN_REVISION.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "📥 Checkout repository"
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: v${{ needs.publish.outputs.release_version }}
path: ${{ needs.publish.outputs.extract_repository_name }}
- name: "📧 Print Grails Vote Email"
env:
VERSION: ${{ needs.publish.outputs.release_version }}
VERSION_COMMIT_ID: ${{ needs.publish.outputs.commit_hash }}
run: |
export DIST_SVN_REVISION=$(awk '/Last Changed Rev:/ {print $4}' dev-repo/DIST_SVN_REVISION.txt)
echo "::group::Grails PPMC Vote Email"
echo "*************************************************"
echo "Subject: [VOTE] Release Apache Grails (incubating) Spring Security Plugin ${VERSION}"
echo "*************************************************"
echo "Body:"
echo "*************************************************"
cat ${{ needs.publish.outputs.extract_repository_name }}/.github/vote_templates/staged.txt | envsubst
echo "*************************************************"
echo "::endgroup::"
- name: '📧 Print Groovy Vote Email'
env:
VERSION: ${{ needs.publish.outputs.release_version }}
VERSION_COMMIT_ID: ${{ needs.publish.outputs.commit_hash }}
run: |
export DIST_SVN_REVISION=$(awk '/Last Changed Rev:/ {print $4}' dev-repo/DIST_SVN_REVISION.txt)
echo "::group::Grails PPMC Vote Email"
echo "*************************************************"
echo "Subject: [VOTE] Approval of Apache Grails (incubating) Spring Security Plugin ${VERSION} release by Groovy PMC"
echo "*************************************************"
echo "Body:"
echo "*************************************************"
cat ${{ needs.publish.outputs.extract_repository_name }}/.github/vote_templates/groovy_pmc.txt | envsubst
echo "*************************************************"
echo "::endgroup::"
release:
environment: release
name: 'VOTE SUCCEEDED - Release Artifacts'
needs: [ publish, source, upload ]
runs-on: ubuntu-24.04
steps:
- name: "Output Agent IP" # in the event RAO blocks this agent, this can be used to debug it
run: curl -s https://api.ipify.org
- name: "Setup SVN and Tools"
run: sudo apt-get install -y subversion subversion-tools tree gettext-base
- name: "🗳 Grails PPMC Vote Confirmation - MANUAL"
run: |
echo "::group::Manual Confirmation"
echo "🔎 This step is a placeholder that the vote confirmation on dev@grails.apache.org completed successfully."
echo "::endgroup::"
- name: "🗳 Groovy PMC Vote Confirmation - MANUAL"
run: |
echo "::group::Manual Confirmation"
echo "🔎 This step is a placeholder that the vote confirmation on dev@grails.apache.org completed successfully."
echo "::endgroup::"
- name: "🚀 Release JAR files - MANUAL"
run: |
echo "::group::Manual Jar Promotion"
echo "Run .github/scripts/releaseJarFiles.sh 'v${{ needs.publish.outputs.release_version }}' '${{ needs.publish.outputs.extract_repository_name }}:${{ needs.publish.outputs.release_version }}' ASF_USER ASF_PASS"
echo "::endgroup::"
- name: "🚀 Release distribution artifacts - MANUAL"
run: |
echo "::group::Manual ASF Artifact Promotion"
echo "Run github/scripts/releaseDistributions.sh 'v${{ needs.publish.outputs.release_version }}' ASF_USER ASF_PASS"
echo "::endgroup::"
- name: "✅ Update ASF Reporter - MANUAL"
run: |
echo "::group::Manual ASF Reporter Update"
TODAY=$(date +"%Y-%m-%d")
echo "Check email & update https://reporter.apache.org to mark the release ${{ needs.publish.outputs.release_version }} as complete as of ${TODAY}"
echo "Note: this is a place holder; currently this is not possible since Groovy sponsors us instead of the incubator PMC"
echo "::endgroup::"
docs:
environment: docs
name: "VOTE SUCCEEDED - Publish Documentation"
needs: [ publish, source, upload ] # TODO Once we have confirmed `release` won't fail, add it as a dependency here
runs-on: ubuntu-24.04
permissions:
contents: write # required for gradle.properties revert
issues: write # required for milestone closing
steps:
- name: "📥 Checkout repository"
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: v${{ needs.publish.outputs.release_version }}
fetch-depth: 1
fetch-tags: true
- name: "☕️ Setup JDK"
uses: actions/setup-java@v4
with:
java-version: '17.0.15'
distribution: liberica
- name: "🐘 Setup Gradle"
uses: gradle/actions/setup-gradle@v4
with:
develocity-access-key: ${{ secrets.GRAILS_DEVELOCITY_ACCESS_KEY }}
- name: "🔨 Build Documentation"
run: ./gradlew aggregateDocs
env:
GRAILS_PUBLISH_RELEASE: 'true'
- name: "🚀 Publish to Github Pages"
uses: apache/grails-github-actions/deploy-github-pages@asf
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GRADLE_PUBLISH_RELEASE: 'true'
SOURCE_FOLDER: build/docs
VERSION: ${{ needs.publish.outputs.release_version }}
close:
name: "VOTE SUCCEEDED - Close Release"
environment: release
needs: [ publish, source, upload, docs ] # TODO Once we have confirmed `release` won't fail, add it as a dependency here
runs-on: ubuntu-24.04
permissions:
contents: write # required for gradle.properties revert
issues: write # required for milestone closing
pull-requests: write # to open PR
actions: write
steps:
- name: "📥 Checkout repository"
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: v${{ needs.publish.outputs.release_version }}
- name: "☕️ Setup JDK"
uses: actions/setup-java@v4
with:
distribution: liberica
java-version: '17.0.15'
- name: "🐘 Setup Gradle"
uses: gradle/actions/setup-gradle@v4
with:
develocity-access-key: ${{ secrets.GRAILS_DEVELOCITY_ACCESS_KEY }}
- name: "⚙️ Run post-release"
uses: apache/grails-github-actions/post-release@asf
- name: '🌎 Create Blog Post - MANUAL'
run: |
echo "::group::Blog Post Creation - MANUAL"
echo "Publish a blog post on https://grails.apache.org/blog/ about the new release ${{ needs.publish.outputs.release_version }} using the repo https://github.com/apache/grails-static-website"
echo "::endgroup::"
- name: 'Announcement Email'
env:
VERSION: ${{ needs.publish.outputs.release_version }}
VERSION_COMMIT_ID: ${{ needs.publish.outputs.commit_hash }}
PREVIOUS_VERSION: 'TODO_PREVIOUS_VERSION'
run: |
export DIST_SVN_REVISION=$(awk '/Last Changed Rev:/ {print $4}' dev-repo/DIST_SVN_REVISION.txt)
echo "::group::Announcement Email"
echo "*************************************************"
echo "Subject: [ANNOUNCE] Apache Grails (incubating) Spring Security Plugin ${VERSION}"
echo "*************************************************"
echo "Body:"
echo "*************************************************"
cat ${{ needs.publish.outputs.extract_repository_name }}/.github/vote_templates/announce.txt | envsubst
echo "*************************************************"
echo "::endgroup::"