diff --git a/.github/workflows/build-plugin.yml b/.github/workflows/build-plugin.yml index c166be91e..d1a5add96 100644 --- a/.github/workflows/build-plugin.yml +++ b/.github/workflows/build-plugin.yml @@ -248,6 +248,26 @@ jobs: ./scripts/build-plugin.sh "${{ steps.plugin.outputs.target }}" arm64 "${{ steps.plugin.outputs.version }}" ./scripts/build-plugin.sh "${{ steps.plugin.outputs.target }}" x86_64 "${{ steps.plugin.outputs.version }}" + - name: Verify built PluginKit version matches the release label + run: | + BUNDLE_NAME="${{ steps.plugin.outputs.bundleName }}" + EXPECTED="${{ matrix.pluginKitVersion }}" + for ARCH in arm64 x86_64; do + WORK=$(mktemp -d) + unzip -oq "build/Plugins/${BUNDLE_NAME}-${ARCH}.zip" -d "$WORK" + PLIST=$(find "$WORK" -path '*.tableplugin/Contents/Info.plist' | head -1) + if [ -z "$PLIST" ]; then + echo "::error::Could not find Info.plist in the built ${BUNDLE_NAME}-${ARCH} bundle." + exit 1 + fi + ACTUAL=$(plutil -extract TableProPluginKitVersion raw "$PLIST") + if [ "$ACTUAL" != "$EXPECTED" ]; then + echo "::error::${BUNDLE_NAME}-${ARCH} was built for PluginKit $ACTUAL but this release is labeled PluginKit $EXPECTED. Refusing to publish a mislabeled binary. Re-release from a commit whose plugin Info.plist matches the target PluginKit version." + exit 1 + fi + echo "Verified ${BUNDLE_NAME}-${ARCH}: built PluginKit $ACTUAL matches the release label." + done + - name: Read checksums id: sha run: | @@ -290,6 +310,13 @@ jobs: - ARM64: \`$ARM64_SHA\` - x86_64: \`$X86_SHA\`" + EXISTING_PKV=$(gh release view "$TAG" --json body --jq .body 2>/dev/null \ + | grep -oiE 'PluginKit [0-9]+' | grep -oE '[0-9]+' | head -1 || true) + if [ -n "$EXISTING_PKV" ] && [ "$EXISTING_PKV" != "$PKV" ]; then + echo "::error::Release $TAG already exists for PluginKit $EXISTING_PKV. Refusing to overwrite it with PluginKit $PKV; publish the new ABI under a new plugin version." + exit 1 + fi + gh release delete "$TAG" --yes 2>/dev/null || true gh release create "$TAG" \ --title "$DISPLAY_NAME v$VERSION" \ diff --git a/scripts/release-all-plugins.sh b/scripts/release-all-plugins.sh index 9b19a7dc8..8db2bf85c 100755 --- a/scripts/release-all-plugins.sh +++ b/scripts/release-all-plugins.sh @@ -4,9 +4,13 @@ # Usage: ./scripts/release-all-plugins.sh # Example: ./scripts/release-all-plugins.sh 14 # -# Reads the latest tag for each plugin from git, pairs it with the given -# pluginKitVersion, and fires one workflow_dispatch on build-plugin.yml so all -# plugins build in parallel as a single matrix run. +# Reads the latest tag for each plugin, bumps the patch version, and pairs the +# NEW version with the given pluginKitVersion, then fires one workflow_dispatch +# on build-plugin.yml so all plugins build in parallel as a single matrix run. +# +# An ABI bump must publish fresh binaries at a NEW release tag. Reusing the +# existing tag overwrites that release's assets, which breaks the previous ABI's +# consumers and serves stale copies from the GitHub release CDN. # # Prerequisites: gh CLI authenticated, run from repo root. @@ -61,14 +65,17 @@ done TAG_LIST="" FIRST=true -echo "Resolving latest tag for each plugin:" +echo "Resolving next release version for each plugin (PluginKit $PKV):" for PLUGIN in "${PLUGINS[@]}"; do - LATEST_TAG=$(git tag -l "plugin-${PLUGIN}-v*" | sort -V | tail -1) + LATEST_TAG=$(git ls-remote --tags --refs origin "plugin-${PLUGIN}-v*" \ + | sed 's#.*/##' | sort -V | tail -1) if [ -z "$LATEST_TAG" ]; then - echo " WARNING: No tag found for plugin-${PLUGIN}-v*. Skipping." + echo " WARNING: No remote tag found for plugin-${PLUGIN}-v*. Skipping." continue fi - PAIR="${LATEST_TAG}:${PKV}" + LATEST_VER="${LATEST_TAG#plugin-${PLUGIN}-v}" + NEW_TAG="plugin-${PLUGIN}-v${LATEST_VER%.*}.$(( ${LATEST_VER##*.} + 1 ))" + PAIR="${NEW_TAG}:${PKV}" if [ "$FIRST" = true ]; then TAG_LIST="$PAIR" FIRST=false