Release Automation
In release mode, the action consumes changesets and opens a “Version Contracts” PR on the main branch.
What happens on each push to main
Section titled “What happens on each push to main”- The Action checks for changeset files in
.contractual/changesets/ - If none exist, the job exits with no changes
- If changesets exist,
contractual versionconsumes them - A pull request titled “Version Contracts” is opened or updated
- Merge that PR to complete the release
Workflow
Section titled “Workflow”name: Contractual Release
on: push: branches: [main] paths: - '.contractual/changesets/**'
permissions: contents: write pull-requests: write
jobs: contractual-release: name: Version contracts runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0
- name: Run Contractual id: release uses: contractual-dev/action@v1 with: mode: release github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Log version PR URL if: steps.release.outputs.version-pr-url != '' run: echo "Version PR: ${{ steps.release.outputs.version-pr-url }}"Inputs
Section titled “Inputs”| Input | Description | Default |
|---|---|---|
mode | Must be release | |
github-token | Token for PR creation and commits | ${{ github.token }} |
config-path | Path to contractual.yaml | ./contractual.yaml |
version-pr-title | Title for the Version Contracts PR | Version Contracts |
version-pr-branch | Branch for the Version Contracts PR | contractual/version-contracts |
pre-release-tag | Pre-release tag (e.g., beta, rc) | |
create-releases | Create GitHub Releases when Version PR merges | true |
tag-prefix | Tag format: contract, v, or none | contract |
attach-specs | Attach spec files to GitHub Releases | true |
Outputs
Section titled “Outputs”| Output | Description |
|---|---|
version-pr-url | URL of the Version Contracts PR |
bumped-versions | JSON of bumped versions, e.g. {"orders-api": "2.0.0"} |
release-urls | JSON array of created GitHub Release URLs |
created-tags | JSON array of created git tags |
Customization
Section titled “Customization”Custom Version PR title and branch
Section titled “Custom Version PR title and branch”- uses: contractual-dev/action@v1 with: mode: release version-pr-title: "chore: release contract versions" version-pr-branch: "release/contractual"Use a personal access token
Section titled “Use a personal access token”Use a PAT when the Version PR needs to trigger other workflows:
- uses: contractual-dev/action@v1 with: mode: release github-token: ${{ secrets.CONTRACTUAL_PAT }}Notify on PR creation
Section titled “Notify on PR creation”- uses: contractual-dev/action@v1 id: release with: mode: release github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Notify Slack if: steps.release.outputs.version-pr-url != '' run: | curl -X POST ${{ secrets.SLACK_WEBHOOK }} \ -d '{"text": "Version PR ready: ${{ steps.release.outputs.version-pr-url }}"}'How multiple changesets are handled
Section titled “How multiple changesets are handled”When multiple PRs merge before a release, each contributes a changeset. At release time:
- For each contract, the highest bump level wins (
major>minor>patch) - All changeset bodies are concatenated into the changelog
fuzzy-lion-dances.md: orders-api: minorsilver-hawk-runs.md: orders-api: majorbrave-wolf-leaps.md: orders-api: patchResult: orders-api gets a major bump.
Triggering downstream workflows
Section titled “Triggering downstream workflows”By default, GitHub Actions created PRs don’t trigger other workflows. Options:
- Use a PAT: PRs created with a PAT trigger workflows
- Use a GitHub App: Same effect without storing a PAT
- Manually trigger: Merge the Version PR to trigger downstream
Path filtering
Section titled “Path filtering”The release workflow only triggers when changesets are pushed:
on: push: branches: [main] paths: - '.contractual/changesets/**'This prevents unnecessary runs when other files change.
Post-merge release
Section titled “Post-merge release”When the Version Contracts PR merges, the action automatically:
- Creates a git tag for each bumped contract
- Creates a GitHub Release with release notes
- Attaches the spec file as a release asset
To trigger on Version PR merge, add versions.json to the paths filter:
on: push: branches: [main] paths: - '.contractual/changesets/**' - '.contractual/versions.json'Tag formats
Section titled “Tag formats”tag-prefix | Example tag |
|---|---|
contract (default) | orders-api@2.0.0 |
v | v2.0.0 |
none | 2.0.0 |
Using release outputs
Section titled “Using release outputs”- uses: contractual-dev/action@v1 id: release with: mode: release
- name: Notify Slack on release if: steps.release.outputs.created-tags != '[]' run: | curl -X POST ${{ secrets.SLACK_WEBHOOK }} \ -d '{"text": "Released: ${{ steps.release.outputs.created-tags }}"}'Disable GitHub Releases
Section titled “Disable GitHub Releases”To create only git tags without GitHub Releases:
- uses: contractual-dev/action@v1 with: mode: release create-releases: falseDisable spec attachments
Section titled “Disable spec attachments”- uses: contractual-dev/action@v1 with: mode: release attach-specs: falsePre-release versions
Section titled “Pre-release versions”Create pre-release versions (e.g., 2.0.0-beta.0) with the pre-release-tag input:
- uses: contractual-dev/action@v1 with: mode: release pre-release-tag: betaPre-release versions:
- Are marked as pre-release in GitHub Releases
- Follow semver pre-release conventions (
2.0.0-beta.0,2.0.0-beta.1) - Increment the pre-release number on subsequent releases with the same tag
Next steps
Section titled “Next steps”- Setup: Initial workflow setup
- PR Checks: Configure pr-check mode
- Versioning: Understand the changeset model