diff --git a/.github/workflows/promote_staging.yml b/.github/workflows/promote_staging.yml new file mode 100644 index 0000000..9f92234 --- /dev/null +++ b/.github/workflows/promote_staging.yml @@ -0,0 +1,75 @@ +name: Promote staging to main + +on: + workflow_dispatch: + inputs: + release_type: + description: "Release type for main (patch, minor, major)" + required: true + type: choice + options: + - patch + - minor + - major + +permissions: + contents: write + actions: read + +jobs: + promote: + runs-on: ubuntu-latest + steps: + - name: verify staging CI + uses: actions/github-script@v7 + with: + script: | + const owner = context.repo.owner; + const repo = context.repo.repo; + const workflowId = 'ci.yml'; + const runs = await github.rest.actions.listWorkflowRuns({ + owner, + repo, + workflow_id: workflowId, + branch: 'staging', + per_page: 1, + }); + if (!runs.data.workflow_runs.length) { + core.setFailed('No CI runs found for staging.'); + return; + } + const latest = runs.data.workflow_runs[0]; + if (latest.conclusion !== 'success') { + core.setFailed(`Latest staging CI is ${latest.conclusion}.`); + } + + - name: checkout main + uses: actions/checkout@v5 + with: + fetch-depth: 0 + ref: main + + - name: merge staging into main + run: | + git fetch origin staging + git merge --no-ff origin/staging -m "chore: promote staging to main" + git push origin HEAD:main + + - name: setup python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: semantic release (main) + uses: cycjimmy/semantic-release-action@v4 + with: + extra_plugins: | + @semantic-release/commit-analyzer@11 + @semantic-release/release-notes-generator@12 + @semantic-release/changelog@6 + @semantic-release/exec@6 + @semantic-release/git@10 + @semantic-release/github@10 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_TYPE: ${{ inputs.release_type }} diff --git a/.github/workflows/semantic_release.yml b/.github/workflows/semantic_release.yml new file mode 100644 index 0000000..a033234 --- /dev/null +++ b/.github/workflows/semantic_release.yml @@ -0,0 +1,37 @@ +name: semantic-release + +on: + push: + branches: [ staging ] + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: setup python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: semantic release + uses: cycjimmy/semantic-release-action@v4 + with: + extra_plugins: | + @semantic-release/commit-analyzer@11 + @semantic-release/release-notes-generator@12 + @semantic-release/changelog@6 + @semantic-release/exec@6 + @semantic-release/git@10 + @semantic-release/github@10 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.releaserc.json b/.releaserc.json index c5444d4..7363fca 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -47,6 +47,7 @@ [ "@semantic-release/exec", { + "analyzeCommitsCmd": "python scripts/release_type.py", "prepareCmd": "python scripts/bump_version.py ${nextRelease.version}" } ], diff --git a/plugin/README.md b/plugin/README.md index d084f80..744d4c2 100644 --- a/plugin/README.md +++ b/plugin/README.md @@ -145,6 +145,22 @@ Set the `CLIPABIT_ENVIRONMENT` environment variable: | **Windows** | `%APPDATA%\Blackmagic Design\DaVinci Resolve\Support\Fusion\Scripts\Utility\` | | **Linux** | `~/.local/share/DaVinci Resolve/Fusion/Scripts/Edit/` | +## Release Flow (Automated) + +### Staging prereleases +- Pushes to `staging` run semantic-release automatically. +- Tags are created as `vX.Y.Z-staging.N`. +- `plugin/CHANGELOG.md` and `plugin/pyproject.toml` are updated. + +### Promote to main (manual trigger) +- Use GitHub Actions workflow **Promote staging to main**. +- It asks for **release type** (`patch`, `minor`, `major`). +- It merges `staging` → `main`, then runs semantic-release on `main` with the chosen release type. + +### Permissions probe +- Run **Permissions Probe** workflow to verify whether `GITHUB_TOKEN` has write access. +- If it fails, org-level settings likely block write permissions. + ## Troubleshooting ### Scripts Menu Shows "No Scripts" diff --git a/scripts/release_type.py b/scripts/release_type.py new file mode 100644 index 0000000..8505a62 --- /dev/null +++ b/scripts/release_type.py @@ -0,0 +1,21 @@ +from __future__ import annotations + +import os +import sys + + +def main() -> int: + release_type = os.getenv("RELEASE_TYPE", "").strip().lower() + if not release_type: + return 0 + + if release_type not in {"patch", "minor", "major"}: + print(f"Invalid RELEASE_TYPE: {release_type}", file=sys.stderr) + return 1 + + print(release_type) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())