-
Notifications
You must be signed in to change notification settings - Fork 0
MT-23496: Add in-repo release workflow #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| # Publishes the release drafted by draft-release.yml: builds and GPG-signs the provider | ||
| # with GoReleaser, attaches the artifacts to the pending draft release, and un-drafts it. | ||
| # Un-drafting is what creates the git tag, which the Terraform Registry then ingests. | ||
| # | ||
| # The signing key must be the one registered with the Terraform Registry — the Registry | ||
| # verifies SHA256SUMS.sig against it and rejects the version otherwise. | ||
| # | ||
| # SECRETS (environment `release`): | ||
| # GPG_PRIVATE_KEY - ASCII-armored GPG private key registered with the Terraform Registry | ||
| # GPG_PASSPHRASE - passphrase for that key | ||
| name: Release | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| dry_run: | ||
| description: "Dry run: build and sign, but do not upload or publish" | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }} | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| release: | ||
| name: Release terraform-provider-mailtrap | ||
| runs-on: ubuntu-latest | ||
| # GPG_PRIVATE_KEY / GPG_PASSPHRASE are environment secrets, not repo secrets: | ||
| # the signing key is only reachable through this environment's protection rules. | ||
| environment: release | ||
| steps: | ||
| # The provider has no version file: the version lives in the git tag, which GitHub | ||
| # creates when the pending draft release is un-drafted at the end of this job. Until | ||
| # then the version is resolved from the draft and handed to GoReleaser via a local, | ||
| # never-pushed tag. | ||
| # | ||
| # The draft is always created against the default branch, so releasing from anywhere | ||
| # else would tag a tree the release notes were never generated from. | ||
| - name: Refuse to release from a non-default branch | ||
| env: | ||
| REF: ${{ github.ref_name }} | ||
| DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} | ||
| run: | | ||
| if [ "$REF" != "$DEFAULT_BRANCH" ]; then | ||
| echo "::error::Releases must be dispatched from $DEFAULT_BRANCH, got $REF" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Resolve pending draft release | ||
| id: version | ||
| uses: actions/github-script@v9 | ||
| with: | ||
| script: | | ||
| const releases = await github.paginate(github.rest.repos.listReleases, { | ||
| ...context.repo, | ||
| per_page: 100 | ||
| }); | ||
| const drafts = releases.filter((release) => release.draft); | ||
|
|
||
| if (drafts.length === 0) { | ||
| core.setFailed('No draft GitHub Release found to publish; run the Draft Release workflow first'); | ||
| return; | ||
| } | ||
|
|
||
| // Publishing to the Registry is irreversible, so never guess between drafts. | ||
| if (drafts.length > 1) { | ||
| const tags = drafts.map((draft) => draft.tag_name).join(', '); | ||
| core.setFailed(`Found ${drafts.length} draft releases (${tags}); leave exactly one`); | ||
| return; | ||
| } | ||
|
|
||
| const tag = drafts[0].tag_name; | ||
|
|
||
| core.info(`Draft GitHub Release ${tag} found`); | ||
| core.setOutput('tag', tag); | ||
| core.setOutput('version', tag.replace(/^v/, '')); | ||
|
|
||
| - uses: actions/checkout@v7 | ||
| with: | ||
| # GoReleaser resolves the version from git tags and history. | ||
| fetch-depth: 0 | ||
|
Rabsztok marked this conversation as resolved.
|
||
| persist-credentials: false | ||
|
|
||
| # The draft's target_commitish is a branch name, so un-drafting would tag whatever | ||
| # the default branch points at *then* — not what was built here. Record the exact | ||
| # commit and pin the release to it before publishing, so the signed checksums always | ||
| # describe the tag's tree. | ||
| - name: Record built commit | ||
| id: commit | ||
| run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Create local tag for GoReleaser | ||
| env: | ||
| TAG: ${{ steps.version.outputs.tag }} | ||
| run: git tag "$TAG" | ||
|
|
||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-version-file: go.mod | ||
| cache: false | ||
|
|
||
| # Mirrors ci.yml: the acceptance tests need the terraform binary. | ||
| - uses: hashicorp/setup-terraform@v3 | ||
| with: | ||
| terraform_wrapper: false | ||
|
|
||
| - name: Vet | ||
| run: go vet ./... | ||
|
|
||
| - name: Test | ||
| run: go test -race ./... | ||
|
|
||
| # Third-party actions are pinned to a commit: this one receives the release signing | ||
| # key, and GoReleaser's archive naming is load-bearing for Registry ingestion. | ||
| - name: Import GPG key | ||
| id: import_gpg | ||
| uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0 | ||
| with: | ||
| gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} | ||
| passphrase: ${{ secrets.GPG_PASSPHRASE }} | ||
|
|
||
| # Build, archive, checksum and GPG-sign only — publishing means uploading to the | ||
| # pending draft release below, not letting GoReleaser create its own release. | ||
| - name: Build and sign with GoReleaser | ||
| uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 | ||
| with: | ||
| distribution: goreleaser | ||
| version: "2.17.1" | ||
| args: release --clean --skip=publish,announce | ||
| env: | ||
| GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} | ||
|
|
||
| # GoReleaser attaches the Registry protocol manifest only at publish time, which is | ||
| # skipped here — copy it into dist under its release asset name instead (same content | ||
| # its SHA256SUMS entry was computed from). Not guarded by dry_run: GoReleaser records | ||
| # this file's hash in SHA256SUMS under the asset name below, so a dry run must fail | ||
| # here if the two ever drift apart. | ||
| - name: Stage the Registry protocol manifest | ||
| env: | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| run: cp terraform-registry-manifest.json "dist/terraform-provider-mailtrap_${VERSION}_manifest.json" | ||
|
|
||
| - name: Attach artifacts to GitHub Release | ||
| if: ${{ !inputs.dry_run }} | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| TAG: ${{ steps.version.outputs.tag }} | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| # --clobber so a re-run after a partial upload replaces assets instead of failing. | ||
| run: | | ||
| gh release upload "$TAG" \ | ||
| dist/*.zip \ | ||
| "dist/terraform-provider-mailtrap_${VERSION}_SHA256SUMS" \ | ||
| "dist/terraform-provider-mailtrap_${VERSION}_SHA256SUMS.sig" \ | ||
| "dist/terraform-provider-mailtrap_${VERSION}_manifest.json" \ | ||
| --clobber \ | ||
| --repo "$GITHUB_REPOSITORY" | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| - name: Pin release to the built commit | ||
| if: ${{ !inputs.dry_run }} | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| TAG: ${{ steps.version.outputs.tag }} | ||
| SHA: ${{ steps.commit.outputs.sha }} | ||
| run: gh release edit "$TAG" --target "$SHA" --repo "$GITHUB_REPOSITORY" | ||
|
|
||
| # Un-drafting creates the git tag; the Terraform Registry then ingests the release. | ||
| - name: Publish GitHub Release | ||
| if: ${{ !inputs.dry_run }} | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| TAG: ${{ steps.version.outputs.tag }} | ||
| run: gh release edit "$TAG" --repo "$GITHUB_REPOSITORY" --draft=false | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.