Parent directory

SKILL.md

10014 bytes

name: deploying-production description: "Converts the current repository to Dune's GitHub Actions production-release pipeline: protected semantic tags, manual forward releases, approved rollbacks, environments, and bot-only tag rulesets. Use when manually invoked to migrate a repository." disable-model-invocation: true

Convert this repository to tag-based production releases

Migrate the current repository to the new production-release pipeline. The result is two manual helper workflows that create protected release tags, plus a tag-triggered production deployment workflow. Do not dispatch a helper workflow as a test: it creates a production tag.

Release model

  • tag-release@main creates tags; deploy-prod@main deploys them.
  • Forward release: tags main head or a newer reviewed commit on main.
  • Rollback: creates a new patch tag at an older reviewed commit on main; it needs a reason and approval.
  • Do not create, move, or delete a release tag by hand.
  • Tags must be strict semantic versions. Default prefix: v.

| Operation | First tag / example | | --------------- | ---------------------------------------------------------- | | Forward release | <prefix>1.0.0; then increment minor: v1.2.3 → v1.3.0 | | Rollback | Increment patch: v1.2.3 → v1.2.4 |

Malformed and prerelease tags are ignored. The newest strict release tag is considered current production even if its deployment fails or is cancelled.

Inspect the current repository

Before editing, verify and record:

  1. main requires PR review and checks; normal users cannot push directly.
  2. The tag-triggered production workflow exists or can be added. It uses duneanalytics/actions/library/deploy-prod@main; note its tag pattern and production environment.
  3. GitHub App dune-semver-tag-bot (ID 4183494) is installed on the repository. Install it before creating the tag ruleset.
  4. The repository can access organization secrets DUNE_SEMVER_TAG_BOT_CLIENT_ID and DUNE_SEMVER_TAG_BOT_PRIVATE_KEY. For selected-repository secrets, grant this repository access. Never read or expose their values.
  5. Workflow authors and dispatchers are within the trusted release boundary.
  6. The current production environment will either be retained without reviewers or removed only after every merged workflow reference is gone.

Choose one tag family and use it everywhere:

| Family | tag-prefix | Tag trigger | | -------- | -------------- | ------------ | | Standard | v or omitted | v*.*.* | | Custom | <prefix>- | <prefix>-* |

target-commit is a full 40-character SHA. It is optional for releases and required for rollbacks. The shared action verifies that the SHA is on main, that releases move forward, and that rollbacks move backward.

Add the release helpers

Create both files in this repository's .github/workflows/. Substitute service, approved runner, environments, and tag prefix. Both must use the same concurrency group.

Forward release

---
name: "Deploy <service> to prod"

on:
  workflow_dispatch:
    inputs:
      commit:
        description: "Commit SHA to deploy (head of main if empty)"
        required: false
        type: string

concurrency:
  group: prod-tag
  cancel-in-progress: false

jobs:
  deploy-prod:
    runs-on: <approved-runner>
    permissions:
      contents: read
    environment:
      name: <release-helper-environment>
    steps:
      - uses: duneanalytics/actions/library/tag-release@main
        with:
          mode: release
          target-commit: ${{ inputs.commit }}
          tag-prefix: <tag-prefix>
          app-token-client-id: ${{ secrets.DUNE_SEMVER_TAG_BOT_CLIENT_ID }}
          app-token-private-key: ${{ secrets.DUNE_SEMVER_TAG_BOT_PRIVATE_KEY }}

Rollback

---
name: "Roll back <service> in prod"

on:
  workflow_dispatch:
    inputs:
      commit:
        description: "Commit SHA on main to roll back to"
        required: true
        type: string
      reason:
        description: "Reason for the production rollback"
        required: true
        type: string

concurrency:
  group: prod-tag
  cancel-in-progress: false

jobs:
  rollback-prod:
    runs-on: <approved-runner>
    permissions:
      contents: read
    environment:
      name: <rollback-helper-environment>
    steps:
      - uses: duneanalytics/actions/library/tag-release@main
        with:
          mode: rollback
          target-commit: ${{ inputs.commit }}
          tag-prefix: <tag-prefix>
          rollback-reason: ${{ inputs.reason }}
          app-token-client-id: ${{ secrets.DUNE_SEMVER_TAG_BOT_CLIENT_ID }}
          app-token-private-key: ${{ secrets.DUNE_SEMVER_TAG_BOT_PRIVATE_KEY }}

prod-tag allows one running and one pending workflow per repository; a newer pending request replaces the older one. Keep the deployment workflow tag-triggered only—do not add workflow_dispatch to it.

Add or update the tag-triggered deployment

Ensure this repository's production workflow uses duneanalytics/actions/library/deploy-prod@main. It verifies the tagged commit is on main before deploying the Flux OCI artifact.

on:
  push:
    tags:
      - "<tag-prefix>*.*.*"

jobs:
  deploy-prod:
    runs-on: <approved-runner>
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Deploy to prod
        uses: duneanalytics/actions/library/deploy-prod@main
        with:
          role-to-assume: <optional-aws-role-arn>
          manifests-ecr-repository: <optional-ecr-repository>
          manifests-directory: <optional-manifest-directory>

Omit optional inputs when defaults apply. By default the action packages the checkout's manifests-directory with flux push; use that only when it contains every production manifest.

If CI already generated and pushed the OCI artifact, promote its immutable build artifact instead. The artifact must exist in the configured ECR repository before the release tag is created.

with:
  source-artifact-tag: ${{ github.sha }}

Normally this is the full SHA for the tagged commit.

Configure this repository in GitHub

Create the repository environments before merging the helper workflows. Both select branch main only.

| Environment | Required reviewers | Self-review | | ------------------------------- | ------------------ | ----------- | | <release-helper-environment> | None | N/A | | <rollback-helper-environment> | Release-owner team | Disabled |

Keep administrator bypass enabled for rollback only; it is for urgent incidents and GitHub records its comment. The action records the rollback reason in the job summary.

Create an active repository tag ruleset before removing reviewers from the legacy production environment:

| Setting | Value | | ----------------- | ------------------------------------------------------------------ | | Target | Tags | | Name | <service> release tags | | Include pattern | refs/tags/<tag-prefix>*.*.* | | Rules | Restrict creation, update, deletion | | Only bypass actor | Integration App dune-semver-tag-bot, ID 4183494, mode always |

Never add user, team, administrator, or deploy-key bypasses. The ruleset blocks direct release tags, so merge and configure helpers first or plan a release freeze.

For the legacy production environment, either retain it in the tag workflow and remove only reviewers after the ruleset is active, or remove all merged references before deleting it. A workflow reference recreates a deleted environment.

Roll out this repository conversion

  1. Add helpers, documentation, and any legacy-environment change on a branch.
  2. Configure App installation, secret visibility, and helper environments.
  3. Merge the helper PR.
  4. Activate the bot-only tag ruleset.
  5. Retire reviewers or delete the legacy environment as chosen.
  6. Without dispatching a helper, verify both environments select main; rollback has reviewers and no self-review; the ruleset is active with only App ID 4183494; helpers use tag-release@main and the intended prefix.

Required manual actions after the helper PR merges

Always include this callout in the completion response. Do not say the conversion is complete until these actions are confirmed:

  1. Activate the active bot-only tag ruleset for refs/tags/<tag-prefix>*.*.*, allowing only App ID 4183494 to create, update, or delete matching tags.
  2. Only after the ruleset is active, remove required reviewers from the retained legacy production environment, or delete it if every merged workflow reference is gone.
  3. Verify both helper environments still select main; rollback requires a reviewer other than the initiator; the ruleset has no user, team, administrator, or deploy-key bypasses; and the helpers use the intended prefix.
  4. Do not dispatch either helper as a test. It creates a production tag.

After conversion: operating releases

Forward: merge and validate in dev; dispatch the forward helper from main; leave commit empty for current main, or provide a newer reviewed full SHA; confirm the tag starts deployment.

Rollback: choose an older full main SHA; dispatch with a clear reason; obtain approval from a configured reviewer other than the initiator; confirm the patch tag starts deployment.

Keep main-triggered production-spec deployment separate from tag-triggered code deployment. A rollback pauses spec deployments because parity with the newest release tag fails. Revert the rolled-back code on main, validate in dev, then forward-release that revert to resume them.