diff --git a/.github/workflows/bump-linter.yaml b/.github/workflows/bump-linter.yaml new file mode 100644 index 0000000..5a114d2 --- /dev/null +++ b/.github/workflows/bump-linter.yaml @@ -0,0 +1,86 @@ +# The linter comes from npm as `@abap2ui5/linter`, and package-lock.json is +# what actually decides which version the gate runs: `npm ci` reads the lock, +# so a new release reaches this corpus only when the lock moves. Nothing moved +# it here for two releases - the lock sat at 0.2.2 while the range said +# `^0.2.2`, which cannot reach 0.3.x at all, so the corpus was frozen on a +# linter two releases old and its green check said less every week without +# saying so. This workflow moves it weekly and opens a PR. +# +# It tracks `latest` rather than staying inside the declared range, because the +# range is the thing being maintained here: a linter release that adds rules is +# additive for the linter and breaking for a corpus, so a range that pins the +# corpus out of new rules is the failure, not the protection. The gate runs +# before the PR exists, which is what makes that safe - a rule regression over +# the corpus fails this workflow instead of landing on main. +# +# The render runtime rides along deliberately: the two are ONE release with one +# version (the linter's metadata snapshot is generated from exactly the +# @openui5 version pinned over there), so bumping one alone is the drift the +# split was allowed on condition of avoiding. +name: bump-linter + +on: + schedule: + - cron: '47 6 * * 1' # Mondays 06:47 UTC - after samples and samples-controls + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + bump-linter: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: '22' + + - name: Move @abap2ui5/linter to the latest published version + id: pin + run: | + set -euo pipefail + # Resolved first and checked, because `npm view` prints nothing and + # still exits 0 when a package has no `latest` dist-tag - installing + # `@abap2ui5/linter@` would then resolve to whatever npm felt like. + VERSION=$(npm view @abap2ui5/linter version) + test -n "$VERSION" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + # Writes the range in package.json AND the exact version in the lock. + # Both matter: the range is what a fresh install reads, the lock is + # what `npm ci` reads, and the gate below runs on the lock. + npm install --save-dev "@abap2ui5/linter@$VERSION" "@abap2ui5/render-runtime@$VERSION" + # package.json alone is not the signal: a release inside the declared + # range moves only package-lock.json, and that is exactly the bump this + # corpus needs to see. + if git diff --quiet package.json package-lock.json; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + # the gate that consumes the linter - a rule regression over the corpus + # surfaces here, in the PR run, not on main + - if: steps.pin.outputs.changed == 'true' + run: npx playwright install --with-deps chromium + - if: steps.pin.outputs.changed == 'true' + run: npm run check:abap2ui5 + + # the badges are written by the run above; they belong to the gate's own + # workflow, not to this one + - if: steps.pin.outputs.changed == 'true' + run: git checkout -- .github/badges/ || true + + - if: steps.pin.outputs.changed == 'true' + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 + with: + branch: bump-linter + title: 'chore: bump @abap2ui5/linter' + commit-message: 'chore: bump @abap2ui5/linter to ${{ steps.pin.outputs.version }}' + body: | + Weekly move of `@abap2ui5/linter` and `@abap2ui5/render-runtime` to + the latest version on npm (${{ steps.pin.outputs.version }}). The + linter gate ran over the full corpus in the workflow that opened + this PR. diff --git a/package-lock.json b/package-lock.json index 25d2f44..6ab0921 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@abap2ui5/linter": "^0.2.2", - "@abap2ui5/render-runtime": "^0.2.2", + "@abap2ui5/linter": "^0.3.0", + "@abap2ui5/render-runtime": "^0.3.0", "@abaplint/cli": "^2.120.23" }, "engines": { @@ -18,9 +18,9 @@ } }, "node_modules/@abap2ui5/linter": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@abap2ui5/linter/-/linter-0.2.2.tgz", - "integrity": "sha512-WegxIRN5M5gH13Ye5Mo13fbpjAZ183J0ei1iArCfEiKUPAGqHot20NnckpNnXHX+YPHCkehA+Z0QapXjaLK1Tw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@abap2ui5/linter/-/linter-0.3.0.tgz", + "integrity": "sha512-Z02eNr8Q1TbdEf7/EHbB0aUQmyZi/KvjMi89+H08AFwvJN5ZEPmIHfdge+cwgxqzS28CtUdDmWERsnnQblIz5w==", "dev": true, "license": "MIT", "workspaces": [ @@ -33,7 +33,7 @@ "node": ">=22" }, "peerDependencies": { - "@abap2ui5/render-runtime": "^0.1.0 || ^0.2.0" + "@abap2ui5/render-runtime": "^0.1.0 || ^0.2.0 || ^0.3.0" }, "peerDependenciesMeta": { "@abap2ui5/render-runtime": { @@ -42,9 +42,9 @@ } }, "node_modules/@abap2ui5/render-runtime": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@abap2ui5/render-runtime/-/render-runtime-0.2.2.tgz", - "integrity": "sha512-6DTHLxaIUoFb1I7qPLqjFFBtLNbgOE7cFpAlWKRBLzM/x+3mmm6JG5uIAGJaS3AFmFMV/J9coAxCXez1hqL7Tw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@abap2ui5/render-runtime/-/render-runtime-0.3.0.tgz", + "integrity": "sha512-xXv3dJuD1qk5GS/u7p9V7g/Yf1wKu1qUj/ya1rSqeXKgvZ1AbaQGi0gJ7zukAjin+eNkAtXLira4kDFukEIhqw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 305d7f1..58708fc 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ }, "homepage": "https://github.com/abap2UI5/samples-stack#readme", "devDependencies": { - "@abap2ui5/linter": "^0.2.2", - "@abap2ui5/render-runtime": "^0.2.2", + "@abap2ui5/linter": "^0.3.0", + "@abap2ui5/render-runtime": "^0.3.0", "@abaplint/cli": "^2.120.23" }, "engines": {