name: Publish plugin # Builds dist/.plugin and publishes it to the Releases tab. # # The version in plugin.json is the single source of truth: # new version -> a new v tag and release are created # same version -> the existing release is rebuilt, replacing its attachment # # So a normal push to main always produces a downloadable build, and bumping # the version in plugin.json is what cuts a new release. Pushing a v* tag by # hand still works and uses that tag verbatim. # # dist/ is gitignored, so the artifact is always built here rather than # committed. The build uses --release because --dev embeds absolute paths from # whichever machine produced it. on: push: branches: - main tags: - "v*" workflow_dispatch: permissions: contents: write jobs: publish: runs-on: ubuntu-latest steps: - name: Check out sources uses: actions/checkout@v4 - name: Validate plugin metadata and sources run: python3 tools/bundle.py --check - name: Build release bundle id: build run: | set -eu python3 tools/bundle.py --release plugin_id=$(python3 -c "import json; print(json.load(open('plugin.json'))['id'])") version=$(python3 -c "import json; print(json.load(open('plugin.json'))['version'])") artifact="dist/${plugin_id}.plugin" test -s "$artifact" echo "artifact=${artifact}" >> "$GITHUB_OUTPUT" echo "asset_name=${plugin_id}.plugin" >> "$GITHUB_OUTPUT" echo "version=${version}" >> "$GITHUB_OUTPUT" echo "built ${artifact} ($(wc -c < "$artifact") bytes)" - name: Verify the built bundle # Executes the bundle against faked SDK modules and asserts the # plugin's observable behaviour. A build that fails this is not # publishable, so this gates the upload. run: python3 tools/verify_bundle.py "${{ steps.build.outputs.artifact }}" - name: Resolve release tag id: tag run: | set -eu if [ "${GITHUB_REF_TYPE:-}" = "tag" ]; then # Hand-pushed tag: honour it exactly as written. tag="${GITHUB_REF_NAME}" else # Branch push or manual run: the version in plugin.json decides # whether this is a new release or a rebuild of the current one. tag="v${{ steps.build.outputs.version }}" fi echo "tag=${tag}" >> "$GITHUB_OUTPUT" echo "publishing as ${tag}" - name: Publish release and upload plugin env: # Org-level secret holding a user token with write:repository scope. # Not using a `||` fallback to GITEA_TOKEN: Gitea's expression engine # supports only always(), so the operator would not evaluate. GITEA_TOKEN: ${{ secrets.API_TOKEN }} run: | python3 tools/release.py \ --api "${{ github.server_url }}/api/v1/repos/${{ github.repository }}" \ --tag "${{ steps.tag.outputs.tag }}" \ --artifact "${{ steps.build.outputs.artifact }}" \ --asset-name "${{ steps.build.outputs.asset_name }}" \ --commitish "${{ github.sha }}"