generated from exteraGramPlugins/pluginBase
96 lines
3.7 KiB
YAML
96 lines
3.7 KiB
YAML
name: Publish plugin
|
|
|
|
# Builds dist/<id>.plugin and publishes it to the Releases tab.
|
|
#
|
|
# The version in plugin.json is the single source of truth:
|
|
# new version -> a new v<version> 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:
|
|
# Passed under a name the runner does not reserve. A step-level
|
|
# GITEA_TOKEN is overridden by the runner's own job token, so the
|
|
# org secret would be silently ignored under that name.
|
|
#
|
|
# RELEASE_TOKEN is the org-wide API_TOKEN secret. If it is empty --
|
|
# which happens when Actions is disabled on the repository, so org
|
|
# secrets are never exposed to it -- release.py falls back to the
|
|
# runner's GITEA_TOKEN, which can still publish to its own repo.
|
|
RELEASE_TOKEN: ${{ secrets.API_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
if [ -n "${RELEASE_TOKEN:-}" ]; then
|
|
echo "org secret API_TOKEN is present (${#RELEASE_TOKEN} chars)"
|
|
else
|
|
echo "org secret API_TOKEN is empty; falling back to the runner token"
|
|
fi
|
|
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 }}"
|