Release #29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # .github/workflows/release.yml | |
| name: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: "DRY RUN: Do not push/tag or create a GitHub Release" | |
| type: boolean | |
| default: false | |
| base_ref: | |
| description: "Branch to release from (for testing)" | |
| type: string | |
| default: "main" | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: release-${{ github.event.inputs.base_ref || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| tag_name: ${{ steps.set_tag.outputs.tag_name }} | |
| dsl_version: ${{ steps.get_dsl_version.outputs.dsl_version }} | |
| artifact_id: ${{ steps.get_artifact_id.outputs.artifact_id }} | |
| steps: | |
| - name: Checkout base branch | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.inputs.base_ref || 'main' }} | |
| persist-credentials: true | |
| - name: Set up Java | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| cache: maven | |
| - name: Get DSL version from pom.xml | |
| id: get_dsl_version | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| DSL_VERSION=$(mvn -q help:evaluate -Dexpression=rosetta.dsl.version -DforceStdout) | |
| if [ -z "${DSL_VERSION:-}" ]; then | |
| echo "Failed to resolve rosetta.dsl.version from pom.xml" | |
| exit 1 | |
| fi | |
| echo "dsl_version=$DSL_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Get artifactId from pom.xml | |
| id: get_artifact_id | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ARTIFACT_ID=$(mvn -q help:evaluate -Dexpression=project.artifactId -DforceStdout) | |
| if [ -z "${ARTIFACT_ID:-}" ]; then | |
| echo "Failed to resolve project.artifactId from pom.xml" | |
| exit 1 | |
| fi | |
| echo "artifact_id=$ARTIFACT_ID" >> "$GITHUB_OUTPUT" | |
| - name: Ensure up-to-date and fetch tags | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| git config --global pull.ff only | |
| git fetch --prune --tags origin | |
| git pull --ff-only origin "${{ github.event.inputs.base_ref || 'main' }}" | |
| - name: Determine next tag | |
| id: set_tag | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| DSL_VERSION="${{ steps.get_dsl_version.outputs.dsl_version }}" | |
| DSL_ESCAPED=$(printf '%s\n' "$DSL_VERSION" | sed -e 's/[]\/$*.^|[]/\\&/g') | |
| EXISTING=$(git tag -l "${DSL_VERSION}.*" | grep -E "^${DSL_ESCAPED}\.[0-9]+$" || true) | |
| if [ -z "$EXISTING" ]; then | |
| NEXT_TAG="${DSL_VERSION}.0" | |
| else | |
| MAX_N=$(echo "$EXISTING" | sed -E "s/^${DSL_ESCAPED}\.//" | sort -n | tail -1) | |
| NEXT_TAG="${DSL_VERSION}.$((MAX_N + 1))" | |
| fi | |
| echo "Next tag computed: $NEXT_TAG" | |
| echo "tag_name=$NEXT_TAG" >> "$GITHUB_OUTPUT" | |
| - name: Guard only allow real release from main | |
| if: ${{ github.event.inputs.dry_run != 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ github.event.inputs.base_ref || 'main' }}" != "main" ]; then | |
| echo "Unable to perform a release from '${{ github.event.inputs.base_ref }}'. Use main or set dry_run=true." | |
| exit 1 | |
| fi | |
| - name: Bump version, tag, and push (skipped in dry run) | |
| env: | |
| TAG_NAME: ${{ steps.set_tag.outputs.tag_name }} | |
| DRY_RUN: ${{ github.event.inputs.dry_run }} | |
| BASE_REF: ${{ github.event.inputs.base_ref || 'main' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ "${DRY_RUN}" = "true" ]; then | |
| echo "[DRY RUN] Would set project version to ${TAG_NAME}, commit, tag, and push atomically to ${BASE_REF}." | |
| exit 0 | |
| fi | |
| mvn -q -B versions:set -DnewVersion="${TAG_NAME}" -DgenerateBackupPoms=false | |
| if ! git diff --quiet; then | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add -A | |
| git commit -m "Release ${TAG_NAME}: set project version to ${TAG_NAME}" | |
| else | |
| echo "No changes to commit (version already ${TAG_NAME})." | |
| fi | |
| git fetch --prune --tags origin | |
| if git rev-parse "${TAG_NAME}" >/dev/null 2>&1; then | |
| echo "Tag ${TAG_NAME} already exists. Exiting." | |
| exit 1 | |
| fi | |
| git tag -a "${TAG_NAME}" -m "Release ${TAG_NAME}" | |
| git push --atomic origin HEAD:"${BASE_REF}" "${TAG_NAME}" | |
| build-and-verify-release: | |
| needs: prepare-release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout the tag (real release) | |
| if: ${{ github.event.inputs.dry_run != 'true' }} | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ needs.prepare-release.outputs.tag_name }} | |
| - name: Checkout the base branch (dry run) | |
| if: ${{ github.event.inputs.dry_run == 'true' }} | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.inputs.base_ref || 'main' }} | |
| - name: Set up Java | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| cache: maven | |
| - name: In dry run - set project version to computed tag (no commit) | |
| if: ${{ github.event.inputs.dry_run == 'true' }} | |
| env: | |
| TAG_NAME: ${{ needs.prepare-release.outputs.tag_name }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mvn -q -B versions:set -DnewVersion="${TAG_NAME}" -DgenerateBackupPoms=false | |
| # No commit; only adjust the working tree so the built artifact names match | |
| - name: Build JARs | |
| shell: bash | |
| run: mvn -B clean package | |
| - name: Collect artifact paths | |
| id: archive | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ARTIFACT_ID="${{ needs.prepare-release.outputs.artifact_id }}" | |
| TAG_NAME="${{ needs.prepare-release.outputs.tag_name }}" | |
| JAR="target/${ARTIFACT_ID}-${TAG_NAME}.jar" | |
| JDOC="target/${ARTIFACT_ID}-${TAG_NAME}-javadoc.jar" | |
| if [ ! -f "$JAR" ]; then echo "Missing $JAR"; ls -l target || true; exit 1; fi | |
| if [ ! -f "$JDOC" ]; then echo "Missing $JDOC"; ls -l target || true; exit 1; fi | |
| echo "jar_path=$JAR" >> "$GITHUB_OUTPUT" | |
| echo "javadoc_jar_path=$JDOC" >> "$GITHUB_OUTPUT" | |
| - name: In dry run - upload build outputs as workflow artifacts | |
| if: ${{ github.event.inputs.dry_run == 'true' }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: dry-run-${{ needs.prepare-release.outputs.tag_name }} | |
| path: | | |
| ${{ steps.archive.outputs.jar_path }} | |
| ${{ steps.archive.outputs.javadoc_jar_path }} | |
| retention-days: 3 | |
| - name: Create GitHub Release (real release) | |
| if: ${{ github.event.inputs.dry_run != 'true' }} | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.prepare-release.outputs.tag_name }} | |
| name: ${{ needs.prepare-release.outputs.tag_name }} | |
| body: | | |
| Automated release for DSL version ${{ needs.prepare-release.outputs.dsl_version }} | |
| files: | | |
| ${{ steps.archive.outputs.jar_path }} | |
| ${{ steps.archive.outputs.javadoc_jar_path }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |