diff --git a/.github/workflows/create-release-pr.yml b/.github/workflows/create-release-pr.yml index 44076609b..21286a3bd 100644 --- a/.github/workflows/create-release-pr.yml +++ b/.github/workflows/create-release-pr.yml @@ -146,7 +146,4 @@ jobs: To ensure this release is ready to be merged: - [ ] Review updated CHANGELOG(s) - After merging this PR, please do the following: - - [ ] Run the `tag-release` CI workflow (specifying the commit hash of this PR once fast-forwarded onto `main`) - - [ ] Run the `release` CI workflow (specifying the released tag) - - [ ] Make releases to downstream repositories (e.g. NPM) for the released artifacts as necessary + After this PR is merged tagging, artifacts and releasing should run automatically. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..05d712dd5 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,91 @@ +name: lint + +on: + merge_group: + pull_request: + branches: + - main + +permissions: + contents: none + +jobs: + conventional-commits: + runs-on: ubuntu-22.04 + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-node@v3 + + - name: Cache npm install + id: cache-node-modules + uses: actions/cache@v4 + with: + key: node-modules-dev-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json') }} + path: | + node_modules + - name: Install debug NPM packages + run: | + npm install -D + + - name: Validate PR commits with commitlint + id: cc + env: + COMMITLINT_START_REF: ${{ github.event.pull_request.base.sha || 'HEAD^' }} + COMMITLINT_END_REF: ${{ github.event.pull_request.head.sha || 'HEAD' }} + run: | + node scripts/lint-cc.mjs + + - name: Create CC fix comment + if: ${{ steps.cc.outputs.fail == 'true' }} + uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db # v2.9.2 + with: + number: ${{ github.event.pull_request.number }} + header: tip-cc + recreate: true + hide_and_recreate: true + skip_unchanged: true + message: | # markdown + ### :warning: It looks like your commit is not formatted in line with Conventional Commits + + This repository uses [Conventional Commits][cc] to enable automation and ensure consistent commit messages across the project. + + ### โŒ Errors + + | Error Name | Error Message | Commit Message | + |------------|---------------|----------------| + ${{ steps.cc.outputs.error-rows-md-table }} + + ### โš  Warnings + + | Warning Name | Warning Message | Commit Message | + |------------|---------------|----------------| + ${{ steps.cc.outputs.warning-rows-md-table }} + + ### How to fix this issue + + Please `git amend` (including a `git rebase` if necessary) your commits to follow the [Conventional Commits][cc] format. + + > [!NOTE] + > If you don't feel comfortable doing this, don't worryโ€”a project maintainer can help correct this for you, before merging. + > + > Ensure that maintainers are allowed to modify your pull requests. + + [cc]: https://www.conventionalcommits.org/en/v1.0.0 + + - name: Hide PR Comment + if: ${{ steps.cc.outputs.success == 'true' }} + uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db # v2.9.2 + with: + number: ${{ github.event.pull_request.number }} + header: tip-cc + hide: true + hide_classify: "RESOLVED" + append: true + skip_unchanged: true + only_update: true + message: "This PR is now formatted in line with Conventional Commits" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 814da50d5..8fe42a428 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ defaults: jobs: build: name: Jco Build - runs-on: "ubuntu-latest" + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index d236af2b8..48822bb12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,5 @@ # Changelog -All notable changes to this project will be documented in this file. - ## [jco-v1.11.0] - 2025-04-28 ### ๐Ÿš€ Features @@ -13,4 +11,4 @@ All notable changes to this project will be documented in this file. ## New Contributors * @tanishiking made their first contribution in [#631](https://github.com/bytecodealliance/jco/pull/631) * @marosset made their first contribution in [#609](https://github.com/bytecodealliance/jco/pull/609) -* @MendyBerger made their first contribution in [#591](https://github.com/bytecodealliance/jco/pull/591) \ No newline at end of file +* @MendyBerger made their first contribution in [#591](https://github.com/bytecodealliance/jco/pull/591) diff --git a/cliff.toml b/cliff.toml index f93ababa8..f9a8d776a 100644 --- a/cliff.toml +++ b/cliff.toml @@ -3,13 +3,12 @@ [changelog] header = """ # Changelog\n -All notable changes to this project will be documented in this file.\n """ # template for the changelog body # https://keats.github.io/tera/docs/#introduction body = """ {% if version %}\ - ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} + ## [{{ version | trim_start_matches(pat="jco-v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} {% else %}\ ## [unreleased] {% endif %}\ diff --git a/commitlint.config.mjs b/commitlint.config.mjs new file mode 100644 index 000000000..aae497062 --- /dev/null +++ b/commitlint.config.mjs @@ -0,0 +1,28 @@ +const config = { + extends: ["@commitlint/config-conventional"], + parserPreset: "conventional-changelog-conventionalcommits", + rules: { + "type-enum": [ + 2, + "always", + [ + "build", + "debug", + "chore", + "ci", + "docs", + "feat", + "fix", + "perf", + "refactor", + "revert", + "style", + "test", + ], + ], + "scope-enum": [1, "always", ["jco", "bindgen", "p2-shim"]], + "scope-case": [2, "always", "kebab-case"], + }, +}; + +export default config; diff --git a/crates/js-component-bindgen/CHANGELOG.md b/crates/js-component-bindgen/CHANGELOG.md index e04ef9509..1081fe7cd 100644 --- a/crates/js-component-bindgen/CHANGELOG.md +++ b/crates/js-component-bindgen/CHANGELOG.md @@ -1,6 +1,5 @@ # Changelog -All notable changes to this project will be documented in this file. ## [js-component-bindgen-v1.11.0] - 2025-04-28 diff --git a/crates/js-component-bindgen/cliff.toml b/crates/js-component-bindgen/cliff.toml index a1e42e4b2..35da9e85f 100644 --- a/crates/js-component-bindgen/cliff.toml +++ b/crates/js-component-bindgen/cliff.toml @@ -3,13 +3,12 @@ [changelog] header = """ # Changelog\n -All notable changes to this project will be documented in this file.\n """ # template for the changelog body # https://keats.github.io/tera/docs/#introduction body = """ {% if version %}\ - ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} + ## [{{ version | trim_start_matches(pat="js-component-bindgen-v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} {% else %}\ ## [unreleased] {% endif %}\ diff --git a/package.json b/package.json index e399bf72d..a5f8458ef 100644 --- a/package.json +++ b/package.json @@ -34,9 +34,12 @@ "terser": "^5" }, "devDependencies": { + "@commitlint/config-conventional": "^19.8.1", "@types/node": "^20.14.12", "@typescript-eslint/eslint-plugin": "^8.2.0", "@typescript-eslint/parser": "^8.2.0", + "commitlint": "^19.8.1", + "conventional-changelog-conventionalcommits": "^8.0.0", "eslint": "^9.9.0", "eslint-config-prettier": "^10.1.1", "eslint-plugin-prettier": "^5.2.3", diff --git a/packages/preview2-shim/cliff.toml b/packages/preview2-shim/cliff.toml index 3b8b04d9d..e0f4fa782 100644 --- a/packages/preview2-shim/cliff.toml +++ b/packages/preview2-shim/cliff.toml @@ -3,13 +3,12 @@ [changelog] header = """ # Changelog\n -All notable changes to this project will be documented in this file.\n """ # template for the changelog body # https://keats.github.io/tera/docs/#introduction body = """ {% if version %}\ - ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} + ## [{{ version | trim_start_matches(pat="preview2-shim-v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} {% else %}\ ## [unreleased] {% endif %}\ diff --git a/scripts/lint-cc.mjs b/scripts/lint-cc.mjs new file mode 100644 index 000000000..66b05854c --- /dev/null +++ b/scripts/lint-cc.mjs @@ -0,0 +1,154 @@ +import { env } from "node:process"; +import { appendFile } from "node:fs/promises"; + +import load from "@commitlint/load"; +import lint from "@commitlint/lint"; +import read from "@commitlint/read"; + +import { default as config } from "../commitlint.config.mjs"; + +/** + * Entrypoint that performs conventional commit checks on this repository + */ +async function main() { + // Load config for the relevant project + const opts = await load(config); + + // Figure out the start/end of the commits to check + const start = env.COMMITLINT_START_REF; + const end = env.COMMITLINT_END_REF; + if (!start || !end) { + throw new Error(`Missing/invalid start/end (${start}/${end})`); + } + + // Get the commit messages + const commits = await read({ to: end, from: start }); + + // Lint commit messages + let invalidCommits = []; + for (const msg of commits) { + console.error(`checking commit msg\n---\n${msg}\n---\n`); + const title = msg.split("\n")[0]; + const { valid, errors, warnings } = await lint( + title, + opts.rules, + opts.parserPreset ? { parserOpts: opts.parserPreset.parserOpts } : {}, + ); + if (!valid) { + invalidCommits.push({ + title, + errors, + warnings, + }); + } + } + + await logJobOutput({ + invalidCommits, + }); +} + +/** Print job output */ +async function logJobOutput(output) { + // If we're in CI, then use GITHUB_STEP_SUMMARY & GITHUB_OUTPUT + // to produce useful output + if (env.CI) { + if (!env.GITHUB_STEP_SUMMARY) { + throw new Error("Missing/invalid GITHUB_STEP_SUMMARY ENV variable in CI"); + } + if (!env.GITHUB_OUTPUT) { + throw new Error("Missing/invalid GITHUB_OUTPUT ENV variable in CI"); + } + + // Print all errors, if present + const failed = output.invalidCommits.length > 0; + if (failed) { + output.invalidCommits.forEach((c) => { + c.errors.forEach((e) => { + console.log(`::error::[${e.name}]: ${e.message}`); + }); + }); + } + + await appendFile(env.GITHUB_STEP_SUMMARY, genCIStepSummary(output)); + await appendFile(env.GITHUB_OUTPUT, `success=${!failed}\n`); + await appendFile(env.GITHUB_OUTPUT, `fail=${failed}\n`); + await appendFile( + env.GITHUB_OUTPUT, + `invalid-commit-count=${output.invalidCommits.length}\n`, + ); + + const errorRowsMd = []; + output.invalidCommits.forEach((c) => { + c.errors.forEach((e) => { + errorRowsMd.push("|" + [e.name, e.message, c.title].join("|") + "|"); + }); + }); + await appendFile( + env.GITHUB_OUTPUT, + `error-rows-md-table< { + c.warnings.forEach((w) => { + warningRowsMd.push("|" + [w.name, w.message, c.title].join("|") + "|"); + }); + }); + await appendFile( + env.GITHUB_OUTPUT, + `warning-rows-md-table< { + c.warnings.forEach((w) => { + console.error(`warning: [${w.name}]: ${w.message}`); + }); + }); + + // Print all errors + output.invalidCommits.forEach((c) => { + c.errors.forEach((e) => { + console.error(`error: [${e.name}]: ${e.message}`); + }); + }); + + // Pretty print information to STDOUT + console.log(JSON.stringify(output, 2, null)); + return; +} + +/** Generate summary for CI (GitHub) step */ +function genCIStepSummary(output) { + let summary = "### Conventional Commits: "; + + summary += output.hasError ? "โŒ" : "โœ…"; + summary += "\n"; + + if (output.invalidCommits.length > 0) { + summary += "## Invalid Commits"; + output.invalidCommits.forEach((c) => { + c.errors.forEach((e) => { + summary += `error: [${e.name}]: ${e.message}\n`; + }); + }); + + summary += "## Warnings"; + output.invalidCommits.forEach((c) => { + c.warnings.forEach((w) => { + summary += `warning: [${w.name}]: ${w.message}\n`; + }); + }); + } + + return summary; +} + +await main(); diff --git a/src/jco.js b/src/jco.js index 846ce04c0..4b1fdb60d 100755 --- a/src/jco.js +++ b/src/jco.js @@ -13,7 +13,7 @@ program .name('jco') .description(c`{bold jco - WebAssembly JS Component Tools}\n JS Component Transpilation Bindgen & Wasm Tools for JS`) .usage(' [options]') - .version('1.10.2'); + .version('1.11.1'); function myParseInt(value) { return parseInt(value, 10);