release-tag-created #27
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
| name: Release | ||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' | ||
| repository_dispatch: | ||
| types: [release-tag-created] | ||
| workflow_dispatch: | ||
| inputs: | ||
| tag: | ||
| description: 'Tag to release (e.g., v0.1.0)' | ||
| required: true | ||
| type: string | ||
| permissions: | ||
| contents: write | ||
| packages: write | ||
| actions: write | ||
| jobs: | ||
| prepare: | ||
| name: Determine tag and verify CI | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| tag: ${{ steps.tag.outputs.tag }} | ||
| require_ci: ${{ steps.verify_ci.outputs.require_ci }} | ||
| steps: | ||
| - name: Determine tag to release | ||
| id: tag | ||
| env: | ||
| INPUT_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || '' }} | ||
| DISPATCH_TAG: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.tag || '' }} | ||
| REF_NAME: ${{ github.ref_name }} | ||
| run: | | ||
| if [ -n "${INPUT_TAG}" ]; then | ||
| TAG="${INPUT_TAG}" | ||
| elif [ -n "${DISPATCH_TAG}" ]; then | ||
| TAG="${DISPATCH_TAG}" | ||
| else | ||
| TAG="${REF_NAME}" | ||
| fi | ||
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | ||
| echo "Releasing tag: $TAG" | ||
| - name: Ensure CI succeeded for tag commit | ||
| id: verify_ci | ||
| uses: actions/github-script@v8 | ||
| env: | ||
| RELEASE_TAG: ${{ steps.tag.outputs.tag }} | ||
| with: | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| script: | | ||
| const tag = process.env.RELEASE_TAG; | ||
| if (!tag) { | ||
| core.setFailed('No release tag determined.'); | ||
| return; | ||
| } | ||
| const { data: ref } = await github.rest.git.getRef({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| ref: `tags/${tag}`, | ||
| }); | ||
| const sha = ref.object.sha; | ||
| core.info(`Tag ${tag} points to commit ${sha}`); | ||
| const { data } = await github.rest.actions.listWorkflowRuns({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| workflow_id: 'ci.yml', | ||
| head_sha: sha, | ||
| per_page: 1, | ||
| }); | ||
| const run = data.workflow_runs[0]; | ||
| let requireCi = false; | ||
| if (!run) { | ||
| core.warning(`No CI workflow run found for commit ${sha}. Release workflow will rerun CI.`); | ||
| requireCi = true; | ||
| } else if (run.conclusion !== 'success') { | ||
| core.warning(`CI workflow run ${run.html_url} has conclusion ${run.conclusion}. Release workflow will rerun CI.`); | ||
| requireCi = true; | ||
| } else { | ||
| core.info(`CI workflow run ${run.html_url} succeeded at ${run.updated_at}.`); | ||
| } | ||
| core.setOutput('require_ci', requireCi ? 'true' : 'false'); | ||
| ci: | ||
|
Check failure on line 91 in .github/workflows/release.yml
|
||
| name: Rerun CI if required | ||
| needs: prepare | ||
| if: needs.prepare.outputs.require_ci == 'true' | ||
| uses: ./.github/workflows/ci.yml | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| publish: | ||
| name: Publish to Maven Central | ||
| needs: [prepare, ci] | ||
| if: | | ||
| needs.prepare.outputs.require_ci != 'true' || | ||
| (needs.prepare.outputs.require_ci == 'true' && needs.ci.result == 'success') | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| env: | ||
| RELEASE_TAG: ${{ needs.prepare.outputs.tag }} | ||
| steps: | ||
| - name: Checkout tag | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: refs/tags/${{ env.RELEASE_TAG }} | ||
| fetch-depth: 0 | ||
| - name: Setup Java | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| distribution: temurin | ||
| java-version: 17 | ||
| cache: sbt | ||
| - name: Setup sbt | ||
| uses: sbt/setup-sbt@v1 | ||
| - name: Import and publish GPG key | ||
| id: gpg | ||
| env: | ||
| PGP_SECRET: ${{ secrets.PGP_SECRET }} | ||
| run: | | ||
| set -euo pipefail | ||
| if [ -z "${PGP_SECRET:-}" ]; then | ||
| echo "PGP_SECRET is not configured" | ||
| exit 1 | ||
| fi | ||
| echo "$PGP_SECRET" | base64 --decode | gpg --batch --import | ||
| KEY_FPR=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr:/ { print $10; exit }') | ||
| if [ -z "$KEY_FPR" ]; then | ||
| echo "Could not determine GPG key fingerprint" | ||
| exit 1 | ||
| fi | ||
| echo "fingerprint=$KEY_FPR" >> "$GITHUB_OUTPUT" | ||
| echo "Using GPG fingerprint: $KEY_FPR" | ||
| KEYSERVER="hkps://keyserver.ubuntu.com" | ||
| if gpg --batch --keyserver "$KEYSERVER" --send-keys "$KEY_FPR"; then | ||
| echo "Uploaded public key to $KEYSERVER" | ||
| else | ||
| echo "::warning::Failed to upload key to $KEYSERVER. Ensure the fingerprint $KEY_FPR is published manually." | ||
| fi | ||
| - name: Get version | ||
| id: version | ||
| run: | | ||
| VERSION=$(sbt --batch --no-colors 'print version' | tail -1 | xargs) | ||
| echo "Version: $VERSION" | ||
| echo "version=$VERSION" >> $GITHUB_OUTPUT | ||
| TAG="${RELEASE_TAG}" | ||
| EXPECTED_VERSION="${TAG#v}" | ||
| if [ "$VERSION" != "$EXPECTED_VERSION" ]; then | ||
| echo "ERROR: Version mismatch!" | ||
| echo " Tag: $TAG" | ||
| echo " Expected version: $EXPECTED_VERSION" | ||
| echo " Actual version: $VERSION" | ||
| exit 1 | ||
| fi | ||
| if [[ "$VERSION" =~ SNAPSHOT ]]; then | ||
| echo "ERROR: Tag release cannot have SNAPSHOT version!" | ||
| echo " Tag: $TAG" | ||
| echo " Version: $VERSION" | ||
| exit 1 | ||
| fi | ||
| - name: Publish to Maven Central | ||
| run: sbt --batch --no-colors ci-release | ||
| env: | ||
| PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} | ||
| PGP_SECRET: ${{ secrets.PGP_SECRET }} | ||
| SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} | ||
| SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} | ||
| CI_RELEASE: +publishSigned | ||
| CI_COMMIT_TAG: ${{ env.RELEASE_TAG }} | ||
| BUILD_SOURCEBRANCH: refs/tags/${{ env.RELEASE_TAG }} | ||
| GITHUB_REF: refs/tags/${{ env.RELEASE_TAG }} | ||
| - name: Package artifacts | ||
| run: sbt --batch --no-colors package | ||
| - name: Create GitHub Release | ||
| uses: ncipollo/release-action@v1 | ||
| with: | ||
| tag: ${{ env.RELEASE_TAG }} | ||
| name: flowforge ${{ steps.version.outputs.version }} | ||
| body: | | ||
| ## flowforge ${{ steps.version.outputs.version }} | ||
| Type-safe-first data engineering framework for compile-time contract enforcement. | ||
| ### What's changed | ||
| - [Changelog](https://github.com/${{github.repository}}/blob/main/CHANGELOG.md) | ||
| ### Installation | ||
| ```scala | ||
| libraryDependencies += "com.flowforge" %% "flowforge-core" % "${{steps.version.outputs.version}}" | ||
| ``` | ||
| artifacts: "modules/**/target/scala-*/flowforge-*.jar" | ||
| draft: false | ||
| prerelease: false | ||
| makeLatest: true | ||
| allowUpdates: true | ||
| updateOnlyUnreleased: false | ||
| - name: Trigger Changelog update | ||
| uses: actions/github-script@v8 | ||
| with: | ||
| script: | | ||
| await github.rest.repos.createDispatchEvent({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| event_type: 'release-completed', | ||
| client_payload: { | ||
| tag: process.env.RELEASE_TAG | ||
| } | ||
| }); | ||