name: Release # Builds the plugin zip, proves it installs and works, and publishes it here. # # This copy is the one that matters: Gitea is where the update feed lives, so # this is the run that decides whether shops are offered the new version. The # .github copy does the same work and publishes to GitHub — deliberately not # byte-identical, and ci/workflows-in-sync.sh knows that. # # Nothing is published before the tests have passed against the current # WordPress and WooCommerce. A release that fails here is one that was never # offered to anybody, which is the entire point of doing it in this order. on: push: tags: ['v*'] workflow_dispatch: inputs: tag: description: 'Tag to publish, e.g. v1.4.0' required: true permissions: contents: write jobs: release: runs-on: ubuntu-latest steps: - name: Which tag id: tag run: | TAG="${{ github.event.inputs.tag || github.ref_name }}" [ -n "$TAG" ] || { echo "Could not determine the tag."; exit 1; } echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" - uses: actions/checkout@v4 with: ref: ${{ steps.tag.outputs.tag }} # ci/publish-release.sh re-fetches the tag as a ref before reading # its message, because checkout overwrites that ref with the commit # SHA and turns the annotated tag into a lightweight one. It needs # the history to do that. fetch-depth: 0 - name: The tools this release needs are present # Checked first, because everything below takes about ten minutes and # discovering that the runner image has no python3 at the publishing # step means doing all of it again. run: | missing= for t in git curl python3 tar; do command -v "$t" >/dev/null 2>&1 || missing="$missing $t" done if [ -n "$missing" ]; then echo "::error::This runner is missing:$missing" exit 1 fi echo "git, curl, python3 and tar are all present." - name: The header version is the tag run: | HEADER=$(ci/version.sh) TAG_VERSION="${{ steps.tag.outputs.version }}" echo "plugin header: $HEADER" echo "tag: $TAG_VERSION" if [ "$HEADER" != "$TAG_VERSION" ]; then echo "::error::WordPress compares the update feed against the plugin header and nothing else." echo "::error::With the header at $HEADER and the tag at $TAG_VERSION, every shop that installs this update is offered it again immediately, forever." exit 1 fi - name: Static checks run: ci/static.sh - name: It installs and works on the current WordPress and WooCommerce env: WP_VERSION: latest WC_VERSION: latest PHP_VERSION: '8.3' run: ci/site-test.sh - name: Build the zip run: ci/build-zip.sh - name: Publish, then read the feed back anonymously env: TAG: ${{ steps.tag.outputs.tag }} GH_TOKEN: ${{ github.token }} run: ci/publish-release.sh