diff --git a/.github/actions/node-minify/README.md b/.github/actions/node-minify/README.md index 2f74ef34e..7be0ac9cf 100644 --- a/.github/actions/node-minify/README.md +++ b/.github/actions/node-minify/README.md @@ -3,7 +3,7 @@ > **This action is deprecated.** Please use the new bundled action instead: > > ```yaml -> - uses: srod/node-minify@v1 +> - uses: srod/node-minify@v11 > ``` The new action includes: @@ -29,7 +29,7 @@ Replace: With: ```yaml -- uses: srod/node-minify@v1 +- uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -64,7 +64,7 @@ If you use the `gcc` compressor that requires Java: distribution: 'temurin' java-version: '17' -- uses: srod/node-minify@v1 +- uses: srod/node-minify@v11 with: compressor: gcc ``` diff --git a/.github/actions/node-minify/action.yml b/.github/actions/node-minify/action.yml index 9efd1160e..71e717a8a 100644 --- a/.github/actions/node-minify/action.yml +++ b/.github/actions/node-minify/action.yml @@ -1,5 +1,5 @@ name: "node-minify (deprecated)" -description: "DEPRECATED: Use srod/node-minify@v1 instead. This composite action will be removed in a future release." +description: "DEPRECATED: Use srod/node-minify@v11 instead. This composite action will be removed in a future release." author: "srod" branding: icon: "minimize-2" @@ -70,7 +70,7 @@ runs: - name: Deprecation warning shell: bash run: | - echo "::warning::This action (.github/actions/node-minify) is DEPRECATED. Please migrate to 'uses: srod/node-minify@v1' for the new bundled action with more features (PR comments, annotations, benchmarking)." + echo "::warning::This action (.github/actions/node-minify) is DEPRECATED. Please migrate to 'uses: srod/node-minify@v11' for the new bundled action with more features (PR comments, annotations, benchmarking)." - name: Setup Java (for gcc) if: contains(fromJSON('["gcc", "google-closure-compiler"]'), inputs.compressor) @@ -136,6 +136,6 @@ runs: | **Gzip Size** | ${{ steps.minify.outputs.gzip-size-formatted }} | | **Time** | ${{ steps.minify.outputs.time-ms }}ms | - > **Note:** This action is deprecated. Please migrate to \`uses: srod/node-minify@v1\` for enhanced features. + > **Note:** This action is deprecated. Please migrate to \`uses: srod/node-minify@v11\` for enhanced features. EOF diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index aa0c2c640..c31200355 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,6 +10,8 @@ permissions: id-token: write contents: write pull-requests: write + # Required to dispatch release-action.yml after the release is created. + actions: write concurrency: ${{ github.workflow }}-${{ github.ref }} @@ -61,11 +63,25 @@ jobs: # Format package list as markdown PACKAGE_LIST=$(echo "$PACKAGES" | jq -r '.[] | "- `\(.name)@\(.version)`"') - # Create release notes - cat > /tmp/release-notes.md << 'EOF' - ## Published Packages + # Lead with this version's own CHANGELOG entry so breaking changes are + # visible on the releases page instead of only in the package files. + # awk prints the body between this version's heading and the next one. + NOTES=$(awk -v ver="## ${VERSION}" ' + $0 == ver { capture = 1; next } + capture && /^## / { exit } + capture { print } + ' packages/core/CHANGELOG.md) - EOF + : > /tmp/release-notes.md + if [ -n "$(echo "$NOTES" | tr -d '[:space:]')" ]; then + echo "$NOTES" >> /tmp/release-notes.md + echo "" >> /tmp/release-notes.md + echo "---" >> /tmp/release-notes.md + echo "" >> /tmp/release-notes.md + fi + + echo "## Published Packages" >> /tmp/release-notes.md + echo "" >> /tmp/release-notes.md echo "$PACKAGE_LIST" >> /tmp/release-notes.md echo "" >> /tmp/release-notes.md echo "See individual package CHANGELOGs for details." >> /tmp/release-notes.md @@ -75,3 +91,15 @@ jobs: --notes-file /tmp/release-notes.md env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Releases created with GITHUB_TOKEN do not emit `release: published`, + # so release-action.yml would never run on its own. workflow_dispatch is + # exempt from that recursion guard, so trigger it explicitly to publish + # the action's version and major tags. + - name: 🏷️ Trigger action tag release + if: steps.changesets.outputs.published == 'true' + run: | + VERSION=$(jq -r '.version' packages/core/package.json) + gh workflow run release-action.yml -f tag="v${VERSION}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index 1f51957c7..3154a7cb1 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -20,6 +20,32 @@ jobs: name: Build and Release Action runs-on: ubuntu-latest steps: + # Runs before checkout: a manual dispatch can name any tag-shaped ref, + # and this workflow force-updates tags and overwrites release assets. + # Require the tag to already exist as a published (non-draft) release. + - name: Verify tag is a published release + if: github.event_name == 'workflow_dispatch' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + INPUT_TAG: ${{ github.event.inputs.tag }} + run: | + if ! [[ "$INPUT_TAG" =~ ^v[0-9]+(\.[0-9]+)*$ ]]; then + echo "Error: '$INPUT_TAG' is not a valid release tag." + exit 1 + fi + + if ! gh release view "$INPUT_TAG" \ + --repo "$GITHUB_REPOSITORY" \ + --json isDraft > /tmp/release.json 2>/dev/null; then + echo "Error: '$INPUT_TAG' is not a published release of this repository." + exit 1 + fi + + if [ "$(jq -r '.isDraft' /tmp/release.json)" != "false" ]; then + echo "Error: release '$INPUT_TAG' is a draft; refusing to publish action tags." + exit 1 + fi + - name: Checkout uses: actions/checkout@v4 with: @@ -124,8 +150,13 @@ jobs: cd release-action zip -r ../node-minify-action-${{ steps.version.outputs.version }}.zip . + # Also runs for workflow_dispatch: publish.yml dispatches this workflow + # because a GITHUB_TOKEN release never emits `release: published`. - name: Upload release artifact - if: github.event_name == 'release' uses: softprops/action-gh-release@v2 with: + tag_name: ${{ steps.version.outputs.version }} files: node-minify-action-${{ steps.version.outputs.version }}.zip + # Re-runs and repeated dispatches target the same tag. This is the + # action's default, set explicitly so the intent survives upgrades. + overwrite_files: true diff --git a/AGENTS.md b/AGENTS.md index e19356f65..97cece0ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -153,10 +153,10 @@ Custom `scripts/publish.ts` resolves `workspace:*` → concrete versions before ## GitHub Action -Published as `srod/node-minify@v1`. See `packages/action/AGENTS.md` for details. +Published as `srod/node-minify@v11`. See `packages/action/AGENTS.md` for details. ```yaml -- uses: srod/node-minify@v1 +- uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -165,7 +165,7 @@ Published as `srod/node-minify@v1`. See `packages/action/AGENTS.md` for details. Zero-config mode: ```yaml -- uses: srod/node-minify@v1 +- uses: srod/node-minify@v11 with: auto: true output-dir: dist diff --git a/docs/src/content/docs/github-action.md b/docs/src/content/docs/github-action.md index 15b1caa38..93a1e6e66 100644 --- a/docs/src/content/docs/github-action.md +++ b/docs/src/content/docs/github-action.md @@ -72,7 +72,7 @@ Enable automatic file discovery and compressor selection with `auto: true`. The npm install @node-minify/terser @node-minify/lightningcss - name: Minify all files - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: auto: 'true' ``` @@ -87,7 +87,7 @@ Override default patterns to target specific files: ```yaml - name: Minify custom locations - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: auto: 'true' patterns: 'public/**/*.js,assets/**/*.css' @@ -100,7 +100,7 @@ Add additional ignore patterns (merges with defaults): ```yaml - name: Minify with custom ignores - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: auto: 'true' ignore: '**/*.config.js,**/vendor/**' @@ -112,7 +112,7 @@ Preview which files would be processed without minifying: ```yaml - name: Preview auto mode - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: auto: 'true' dry-run: 'true' @@ -143,7 +143,7 @@ For a project with JavaScript, CSS, and HTML: @node-minify/html-minifier - name: Minify all assets - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: auto: 'true' output-dir: 'public/dist' @@ -161,7 +161,7 @@ For a project with JavaScript, CSS, and HTML: run: npm install @node-minify/terser - name: Minify JavaScript - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -193,7 +193,7 @@ jobs: run: npm install @node-minify/terser - name: Minify JS - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -211,7 +211,7 @@ When enabled, PR comments include a **"vs Base"** column showing size changes co ```yaml - name: Minify and Report - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -229,7 +229,7 @@ When enabled, PR comments include a **"vs Base"** column showing size changes co run: npm install @node-minify/lightningcss - name: Minify CSS - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/styles.css" output: "dist/styles.min.css" @@ -240,7 +240,7 @@ When enabled, PR comments include a **"vs Base"** column showing size changes co ```yaml - name: Minify with Thresholds - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -258,7 +258,7 @@ Compare multiple compressors to find the best one for your project: run: npm install @node-minify/terser @node-minify/esbuild @node-minify/swc @node-minify/oxc - name: Benchmark Compressors - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -344,7 +344,7 @@ The `type` parameter is **required** for: ```yaml - name: Minify id: minify - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -372,7 +372,7 @@ The `type` parameter is **required** for: run: npm install @node-minify/google-closure-compiler - name: Minify with GCC - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -387,7 +387,7 @@ The `type` parameter is **required** for: run: npm install @node-minify/html-minifier - name: Minify HTML - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/index.html" output: "dist/index.html" @@ -402,14 +402,14 @@ The `type` parameter is **required** for: run: npm install @node-minify/terser @node-minify/lightningcss - name: Minify JS bundle - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/**/*.js" output: "dist/bundle.min.js" compressor: "terser" - name: Minify CSS bundle - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/**/*.css" output: "dist/styles.min.css" @@ -446,7 +446,7 @@ jobs: - name: Minify Assets id: minify - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "dist/**/*.js" compressor: "esbuild" diff --git a/packages/action/README.md b/packages/action/README.md index 4ddc77906..25dc0388f 100644 --- a/packages/action/README.md +++ b/packages/action/README.md @@ -27,7 +27,7 @@ Compressor packages contain native dependencies that cannot be bundled into the run: npm install @node-minify/terser - name: Minify JavaScript - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -38,7 +38,7 @@ Compressor packages contain native dependencies that cannot be bundled into the ```yaml - name: Minify JavaScript - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -55,7 +55,7 @@ Automatically discover and minify files with `auto: true`: run: npm install @node-minify/terser @node-minify/lightningcss - name: Minify all files - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: auto: 'true' ``` @@ -68,7 +68,7 @@ See [full zero-config documentation](https://node-minify.2clics.net/github-actio ```yaml - name: Minify and Report - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" @@ -83,7 +83,7 @@ See [full zero-config documentation](https://node-minify.2clics.net/github-actio ```yaml - name: Minify with Quality Gates - uses: srod/node-minify@v1 + uses: srod/node-minify@v11 with: input: "src/app.js" output: "dist/app.min.js" diff --git a/packages/minify-html/__tests__/minify-html-error.test.ts b/packages/minify-html/__tests__/minify-html-error.test.ts index 81e2455f8..52c8cb6a3 100644 --- a/packages/minify-html/__tests__/minify-html-error.test.ts +++ b/packages/minify-html/__tests__/minify-html-error.test.ts @@ -15,7 +15,9 @@ describe("Package: minify-html error handling", () => { vi.doUnmock("@minify-html/node"); }); - test("should wrap minification errors", async () => { + // Resetting the module registry and re-importing the compressor exceeds + // vitest's 5s default on Windows runners, so widen this test only. + test("should wrap minification errors", { timeout: 30000 }, async () => { // Mirrors the real module shape: @minify-html/node is CommonJS, so its // exports are reached through the default export. vi.doMock("@minify-html/node", () => ({