From d62626f4c28d1ee2b99bab3a5af73df347474af7 Mon Sep 17 00:00:00 2001 From: EthanMcManus Date: Thu, 29 Jan 2026 17:26:42 -0500 Subject: [PATCH 1/2] Commit my files!?!?!?! --- .github/workflows/permissions_probe.yml | 49 ++++++++++++++++ .github/workflows/promote_staging.yml | 75 +++++++++++++++++++++++++ .github/workflows/semantic_release.yml | 37 ++++++++++++ .releaserc.json | 1 + plugin/README.md | 16 ++++++ scripts/release_type.py | 21 +++++++ 6 files changed, 199 insertions(+) create mode 100644 .github/workflows/permissions_probe.yml create mode 100644 .github/workflows/promote_staging.yml create mode 100644 .github/workflows/semantic_release.yml create mode 100644 scripts/release_type.py diff --git a/.github/workflows/permissions_probe.yml b/.github/workflows/permissions_probe.yml new file mode 100644 index 0000000..f634a6a --- /dev/null +++ b/.github/workflows/permissions_probe.yml @@ -0,0 +1,49 @@ +name: Permissions Probe + +on: + workflow_dispatch: + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + probe: + runs-on: ubuntu-latest + steps: + - name: Probe write permissions + uses: actions/github-script@v7 + with: + script: | + const owner = context.repo.owner; + const repo = context.repo.repo; + const sha = context.sha; + const tagName = `permissions-probe-${context.run_id}`; + const ref = `refs/tags/${tagName}`; + + core.info(`Attempting to create tag ${ref} at ${sha}`); + try { + await github.rest.git.createRef({ + owner, + repo, + ref, + sha, + }); + core.info("Tag created successfully."); + } catch (error) { + core.setFailed(`Failed to create tag: ${error.message}`); + return; + } + + core.info(`Attempting to delete tag ${ref}`); + try { + await github.rest.git.deleteRef({ + owner, + repo, + ref: `tags/${tagName}`, + }); + core.info("Tag deleted successfully."); + } catch (error) { + core.setFailed(`Failed to delete tag: ${error.message}`); + } 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()) From c68af92cf8f928e7f4c6c91a384da5d2d10b7486 Mon Sep 17 00:00:00 2001 From: EthanMcManus Date: Fri, 30 Jan 2026 17:21:13 -0500 Subject: [PATCH 2/2] get rid of permissions check --- .github/workflows/permissions_probe.yml | 49 ------------------------- 1 file changed, 49 deletions(-) delete mode 100644 .github/workflows/permissions_probe.yml diff --git a/.github/workflows/permissions_probe.yml b/.github/workflows/permissions_probe.yml deleted file mode 100644 index f634a6a..0000000 --- a/.github/workflows/permissions_probe.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Permissions Probe - -on: - workflow_dispatch: - -permissions: - contents: write - issues: write - pull-requests: write - -jobs: - probe: - runs-on: ubuntu-latest - steps: - - name: Probe write permissions - uses: actions/github-script@v7 - with: - script: | - const owner = context.repo.owner; - const repo = context.repo.repo; - const sha = context.sha; - const tagName = `permissions-probe-${context.run_id}`; - const ref = `refs/tags/${tagName}`; - - core.info(`Attempting to create tag ${ref} at ${sha}`); - try { - await github.rest.git.createRef({ - owner, - repo, - ref, - sha, - }); - core.info("Tag created successfully."); - } catch (error) { - core.setFailed(`Failed to create tag: ${error.message}`); - return; - } - - core.info(`Attempting to delete tag ${ref}`); - try { - await github.rest.git.deleteRef({ - owner, - repo, - ref: `tags/${tagName}`, - }); - core.info("Tag deleted successfully."); - } catch (error) { - core.setFailed(`Failed to delete tag: ${error.message}`); - }