| # |
| # 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 |
| # |
| # http://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: deploy-release-reusable |
| |
| on: |
| workflow_call: |
| inputs: |
| java-version: |
| description: The Java compiler version |
| default: 17 |
| type: string |
| project-id: |
| description: Identifier used in the distribution artifact and Subversion repository folder filenames (e.g., `logging-parent`) |
| required: true |
| type: string |
| secrets: |
| GPG_SECRET_KEY: |
| description: GPG secret key for signing artifacts |
| required: true |
| NEXUS_USERNAME: |
| description: Nexus staging repository username for deploying artifacts |
| required: true |
| NEXUS_PASSWORD: |
| description: Nexus staging repository password for deploying artifacts |
| required: true |
| SVN_USERNAME: |
| description: Subversion username for uploading the release distribution |
| required: true |
| SVN_PASSWORD: |
| description: Subversion password for uploading the release distribution |
| required: true |
| |
| jobs: |
| deploy: |
| runs-on: ubuntu-latest |
| steps: |
| |
| - name: Checkout repository |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 |
| |
| - name: Set up Java & GPG |
| uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # 3.7.0 |
| with: |
| distribution: zulu |
| java-version: ${{ inputs.java-version }} |
| cache: maven |
| server-id: apache.releases.https |
| server-username: NEXUS_USERNAME |
| server-password: NEXUS_PASSWORD |
| gpg-private-key: ${{ secrets.GPG_SECRET_KEY }} |
| |
| - name: Set up Git user |
| shell: bash |
| run: | |
| # Set up user name and email required for `git commit` |
| git config user.name "ASF Logging Services RM" |
| git config user.email private@logging.apache.org |
| |
| - name: Export version |
| shell: bash |
| env: |
| GIT_BRANCH_NAME: ${{ github.ref_name }} |
| run: | |
| [[ "$GIT_BRANCH_NAME" =~ ^release/.+$ ]] || { |
| echo "was expecting a \`release/\`-prefixed Git branch name, found: \`$GIT_BRANCH_NAME\`" |
| exit 1 |
| } |
| export PROJECT_VERSION=$(echo "$GIT_BRANCH_NAME" | sed 's/^release\///') |
| echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV |
| |
| - name: Set the Maven `revision` property |
| shell: bash |
| run: | |
| export REVISION=$(./mvnw \ |
| --non-recursive --quiet --batch-mode \ |
| -DforceStdout=true \ |
| -Dexpression=revision \ |
| help:evaluate \ |
| | tail -n 1) |
| if [ "$REVISION" != "$PROJECT_VERSION" ]; then |
| echo "Maven \`revision\` property \`$REVISION\` doesn't match with the project version \`$PROJECT_VERSION\`, updating \`pom.xml\`..." |
| ./mvnw \ |
| --non-recursive --batch-mode --errors --no-transfer-progress \ |
| -Dproperty=revision \ |
| -DnewVersion="$PROJECT_VERSION" \ |
| -DgenerateBackupPoms=false \ |
| versions:set-property |
| git commit -S pom.xml -m "Set version to \`$PROJECT_VERSION\`" |
| git push -f origin |
| fi |
| |
| - name: Set the Maven `project.build.outputTimestamp` property |
| shell: bash |
| run: | |
| export PROPERTY="project.build.outputTimestamp" |
| grep -qE '^[\t ]+<'$PROPERTY'>' pom.xml || { |
| echo "Failed to find the \`$PROPERTY\` Maven property!" |
| exit 1 |
| } |
| export TIMESTAMP=$(TZ=UTC0 git show --quiet --date="format-local:%Y-%m-%dT%H:%M:%SZ" --format="%cd") |
| sed -r 's|^([\t ]+<'$PROPERTY'>).+(</'$PROPERTY'>)$|\1'$TIMESTAMP'\2|g' -i pom.xml |
| if [ -n "$(git status --porcelain)" ]; then |
| git commit -S pom.xml -m "Update the \`$PROPERTY\` property" |
| git push -f origin |
| fi |
| |
| - name: Release changelog |
| shell: bash |
| run: | |
| ./mvnw \ |
| --non-recursive --batch-mode --errors --no-transfer-progress \ |
| -P changelog-release |
| git add src |
| if [ -n "$(git status --porcelain)" ]; then |
| git commit -S src -m "Release changelog for version \`$PROJECT_VERSION\`" |
| git push -f origin |
| fi |
| |
| - name: Upload to Nexus |
| shell: bash |
| env: |
| # `NEXUS_USERNAME` and `NEXUS_PASSWORD` are used in `~/.m2/settings.xml` created by `setup-java` action |
| NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }} |
| NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} |
| # `SIGN_KEY` is used by `sign-maven-plugin` |
| SIGN_KEY: ${{ secrets.GPG_SECRET_KEY }} |
| run: | |
| ./mvnw \ |
| --show-version --batch-mode --errors --no-transfer-progress \ |
| -P deploy,release |
| export NEXUS_URL=$(awk '/^(stagingRepository.url)/ { gsub(/(^.+=|\\)/, ""); print $1 }' target/nexus-staging/staging/*.properties) |
| echo "NEXUS_URL=$NEXUS_URL" >> $GITHUB_ENV |
| |
| # Node.js cache is needed for Antora |
| - name: Set up Node.js cache |
| id: nodejs-cache |
| uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # 4.1.1 |
| with: |
| # We should be calculating the cache key using `package-lock.json` instead! |
| # See https://stackoverflow.com/a/48524475/1278899 |
| # For that, `package-lock.json` needs to be committed into the repository – right now it is `.gitignore`d. |
| # Once it is there, we should ideally switch from `npm i` to `npm ci`. |
| # For that, we need to configure `dependabot` to update hundreds of dependencies listed in `package-lock.json`. |
| # That translates to a never ending rain of `dependabot` PRs. |
| # I doubt if the wasted CPU cycles worth the gain. |
| key: ${{ runner.os }}-nodejs-cache-${{ hashFiles('node', 'node_modules') }} |
| # `actions/cache` doesn't recommend caching `node_modules`. |
| # Though none of its recipes fit our bill, since we install Node.js using `frontend-maven-plugin`. |
| # See https://github.com/actions/cache/blob/main/examples.md#node---npm |
| # We settle for this quick-n-dirty solution for the time being. |
| path: | |
| node |
| node_modules |
| |
| # Website build is needed to generate the release notes |
| - name: Build the website |
| shell: bash |
| env: |
| # Making Node.js cache hit visible for debugging purposes |
| NODEJS_CACHE_HIT: ${{ steps.nodejs-cache.outputs.cache-hit }} |
| run: | |
| export TIMESTAMP=$(./mvnw \ |
| --non-recursive --quiet --batch-mode \ |
| -DforceStdout=true \ |
| -Dexpression=project.build.outputTimestamp \ |
| help:evaluate \ |
| | tail -n 1) |
| ./mvnw \ |
| --show-version --batch-mode --errors --no-transfer-progress \ |
| site |
| |
| - name: Stage distribution attachments |
| shell: bash |
| run: | |
| # Dump deployed artifacts to a local folder |
| export ALT_DEPLOYMENT_REPO_FILEPATH="target/alt-deployment-repo" |
| mkdir "$ALT_DEPLOYMENT_REPO_FILEPATH" |
| ./mvnw \ |
| --show-version --batch-mode --errors --no-transfer-progress \ |
| -DaltDeploymentRepository=apache.releases.https::file:"$ALT_DEPLOYMENT_REPO_FILEPATH" \ |
| -Dsign.skip \ |
| -P deploy |
| |
| # This regex needs to work for both Java (`distribution` profile) and `find` (while counting attachments)! |
| # Hence, we don't escape dots, etc. with backslashes, which is problematic to get working in both worlds. |
| export DIST_ATTACHMENT_FILEPATH_PATTERN="^$ALT_DEPLOYMENT_REPO_FILEPATH/.+-$PROJECT_VERSION"'((-tests)?.jar|-cyclonedx.xml)$' |
| export DIST_ATTACHMENT_COUNT=$(find "$ALT_DEPLOYMENT_REPO_FILEPATH" -type f -regextype posix-extended -regex "$DIST_ATTACHMENT_FILEPATH_PATTERN" | wc -l) |
| |
| # Pass the necessary environment variables |
| cat >> $GITHUB_ENV << EOF |
| DIST_ATTACHMENT_FILEPATH_PATTERN=$DIST_ATTACHMENT_FILEPATH_PATTERN |
| DIST_ATTACHMENT_COUNT=$DIST_ATTACHMENT_COUNT |
| EOF |
| |
| - name: Create the distribution |
| shell: bash |
| run: | |
| |
| # Generate the distribution (i.e., `src.zip` and optional `bin.zip`) |
| ./mvnw \ |
| --show-version --batch-mode --errors --no-transfer-progress \ |
| --non-recursive \ |
| -P distribution \ |
| -DattachmentFilepathPattern="$DIST_ATTACHMENT_FILEPATH_PATTERN" \ |
| -DattachmentCount="$DIST_ATTACHMENT_COUNT" |
| |
| # Rename distribution files |
| export DIST_FILENAME_PREFIX="apache-${{ inputs.project-id }}" |
| export DIST_FILENAME_VERSIONED_PREFIX="${DIST_FILENAME_PREFIX}-${PROJECT_VERSION}" |
| export DIST_FILEPATH_PREFIX="/tmp/${DIST_FILENAME_VERSIONED_PREFIX}" |
| export DIST_FILEPATH_SRC="${DIST_FILEPATH_PREFIX}-src.zip" |
| export DIST_FILEPATH_BIN="${DIST_FILEPATH_PREFIX}-bin.zip" |
| mv "target/src.zip" "$DIST_FILEPATH_SRC" |
| test -f "target/bin.zip" && mv "$_" "$DIST_FILEPATH_BIN" |
| |
| # Create signature and checksum files |
| for DIST_FILEPATH in "$DIST_FILEPATH_SRC" "$DIST_FILEPATH_BIN"; do |
| if [ -f "$DIST_FILEPATH" ]; then |
| gpg --armor --detach-sign --yes --pinentry-mode error "$DIST_FILEPATH" |
| sha512sum "$DIST_FILEPATH" \ |
| | ( read CHECKSUM FILEPATH; echo $CHECKSUM" "$(basename "$FILEPATH") ) \ |
| > "$DIST_FILEPATH.sha512" |
| fi |
| done |
| |
| # Pass the necessary environment variables |
| cat >> $GITHUB_ENV << EOF |
| DIST_FILENAME_PREFIX=$DIST_FILENAME_PREFIX |
| DIST_FILENAME_VERSIONED_PREFIX=$DIST_FILENAME_VERSIONED_PREFIX |
| DIST_FILEPATH_PREFIX=$DIST_FILEPATH_PREFIX |
| EOF |
| |
| - name: Upload to Subversion |
| shell: bash |
| env: |
| PROJECT_ID: ${{ inputs.project-id }} |
| SVN_USERNAME: ${{ secrets.SVN_USERNAME }} |
| SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} |
| run: | |
| |
| # Find the effective Git commit ID |
| export COMMIT_ID=$(git rev-parse HEAD) |
| |
| # Checkout the SVN repository |
| export SVN_DIR="/tmp/svn-repo" |
| svn co \ |
| "https://dist.apache.org/repos/dist/dev/logging/$PROJECT_ID" \ |
| "$SVN_DIR" |
| cd "$SVN_DIR" |
| |
| # Switch to the distribution folder |
| [ -d "$PROJECT_VERSION" ] || { |
| mkdir "$PROJECT_VERSION" |
| svn add "$PROJECT_VERSION" |
| } |
| cd "$PROJECT_VERSION" |
| |
| # Clean up old files |
| find . -name "${DIST_FILENAME_PREFIX}*" -type f -print0 | xargs -0 -r svn delete |
| |
| # Generate emails |
| for EMAIL_TYPE in vote announce; do |
| "$GITHUB_WORKSPACE/.github/generate-email.sh" \ |
| "$EMAIL_TYPE" "$PROJECT_VERSION" "$COMMIT_ID" "$NEXUS_URL" \ |
| > "${DIST_FILENAME_VERSIONED_PREFIX}-email-${EMAIL_TYPE}.txt" |
| done |
| |
| # Copy the distribution |
| cp "$DIST_FILEPATH_PREFIX"* . |
| |
| # Add & commit changes |
| svn add "$DIST_FILENAME_PREFIX"* |
| svn commit \ |
| --username "$SVN_USERNAME" \ |
| --password "$SVN_PASSWORD" \ |
| -m "Added \`${DIST_FILENAME_PREFIX}\` artifacts for release \`${PROJECT_VERSION}\`" |