ci: improve workflow configuration and reliability

- Replace global read-all permissions with scoped permissions (contents: read, actions: write)
- Fix cache configuration to exclude node_modules and include package-lock.json
- Improve CI workflow resolution with flexible path matching and pagination
- Verify version instead of committing version bumps from CI
- Detect prereleases and publish with appropriate npm tags (next vs latest)
- Use generic test suite description in release notes to avoid drift
This commit is contained in:
2025-12-11 19:28:48 +02:00
parent 5bc95f0bcd
commit 4cc202c687
2 changed files with 43 additions and 41 deletions

View File

@@ -71,36 +71,28 @@ jobs:
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
// Find CI workflow by name or filename
const { data: allWorkflows } = await github.rest.actions.listRepoWorkflows({
owner: context.repo.owner,
repo: context.repo.repo
});
const ciWorkflow = allWorkflows.workflows.find(w =>
w.name === 'CI' ||
w.path === '.github/workflows/test.yml'
);
if (!ciWorkflow) {
core.setFailed('Could not find CI workflow');
return;
}
const { data: workflows } = await github.rest.actions.listWorkflowRuns({
const wfList = await github.rest.actions.listRepoWorkflows({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: ciWorkflow.id,
head_sha: context.sha,
status: 'completed'
});
const latestRun = workflows.workflow_runs[0];
if (!latestRun || latestRun.conclusion !== 'success') {
core.setFailed(`CI workflow has not passed for this commit. Status: ${latestRun?.conclusion || 'not found'}`);
const wf =
wfList.data.workflows.find(w => w.path.endsWith('/test.yml')) ||
wfList.data.workflows.find(w => (w.name || '').toLowerCase() === 'ci');
if (!wf) core.setFailed('CI workflow not found (test.yml or CI).');
const { data } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: wf.id,
head_sha: context.sha,
status: 'completed',
per_page: 1
});
const latestRun = data.workflow_runs?.[0];
if (!latestRun) core.setFailed('No completed CI runs found for this commit.');
if (latestRun.conclusion !== 'success') {
core.setFailed(`CI workflow conclusion: ${latestRun.conclusion}`);
}
console.log(`CI workflow ID: ${ciWorkflow.id}, Status: ${latestRun?.conclusion || 'not found'}`)
console.log(`CI status: ${latestRun.conclusion}`)
security:
name: 🔒 Security Scan
@@ -197,22 +189,24 @@ jobs:
- name: 🏗️ Build Parser
run: npm run build
- name: 📋 Update Package Version
- name: 🔎 Verify package.json version matches input
if: github.event_name == 'workflow_dispatch'
run: |
VERSION="${{ github.event.inputs.version }}"
npm version ${VERSION} --no-git-tag-version
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add package.json package-lock.json
git commit -m "chore: bump version to ${VERSION}" || true
INPUT="${{ github.event.inputs.version }}"
EXPECTED="v${INPUT#v}"
PKG="v$(node -p "require('./package.json').version")"
if [ "$PKG" != "$EXPECTED" ]; then
echo "package.json version ($PKG) does not match requested release ($EXPECTED)."
echo "Bump package.json in a PR before running workflow_dispatch."
exit 1
fi
- name: 🏷️ Create Tag
if: github.event_name == 'workflow_dispatch'
run: |
VERSION="v${{ github.event.inputs.version }}"
git tag ${VERSION}
git push origin ${VERSION}
git tag "${VERSION#v}"
git push origin "${VERSION#v}"
- name: 📝 Generate Release Notes
id: release_notes
@@ -237,7 +231,7 @@ jobs:
echo ""
echo "- Initial release of tree-sitter-shellspec"
echo "- Complete ShellSpec grammar support"
echo "- 59 comprehensive test cases"
echo "- Comprehensive test suite with broad coverage"
echo "- Real-world compatibility with official ShellSpec examples"
} >> release_notes.md
fi
@@ -262,7 +256,14 @@ jobs:
generate_release_notes: false
- name: 📦 Publish to npm
run: npm publish --access public
run: |
if [[ "${{ needs.validate.outputs.version }}" == *"-"* ]]; then
PUBLISH_TAG="next"
else
PUBLISH_TAG="latest"
fi
echo "Publishing with tag: $PUBLISH_TAG"
npm publish --access public --tag "$PUBLISH_TAG"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -12,7 +12,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
permissions:
contents: read
actions: write
jobs:
test:
@@ -89,9 +91,8 @@ jobs:
id: cache-parser
with:
path: |
src/
node_modules/
key: ${{ runner.os }}-parser-${{ matrix.node-version }}-${{ hashFiles('src/parser.c', 'binding.gyp', 'package.json') }}
build/
key: ${{ runner.os }}-parser-${{ matrix.node-version }}-${{ hashFiles('package-lock.json', 'src/parser.c', 'binding.gyp', 'src/**/*.cc', 'src/**/*.h') }}
- name: Build Parser
if: steps.cache-parser.outputs.cache-hit != 'true'