Skip to content

Release

Release #31

Workflow file for this run

# .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
# We skip committing changes to the repo. Use versions:set only in the build step ephemerally.
echo "Skipping persistent version bump in pom.xml to avoid branch protection issues."
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
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: Set project version for build (ephemeral)
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
- 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 }}