Skip to content

Fix stale API Readiness Checklist pointer in mandatory error-response template #58

Fix stale API Readiness Checklist pointer in mandatory error-response template

Fix stale API Readiness Checklist pointer in mandatory error-response template #58

Workflow file for this run

# =========================================================================================
# CAMARA Commonalities - Artifacts Lint
#
# Lints the distributed artifacts (artifacts/**) so broken content is caught at
# PR time instead of after a downstream sync into an API repository:
# 1. yamllint over all YAML files in artifacts/ - including Github_templates/,
# whose installed copies in API repositories are not checked there.
# 2. Spectral over the full-OpenAPI templates (api-templates/,
# notification-templates/), one invocation per template, with the CAMARA
# ruleset of the release line under development; $ref resolution
# transitively lints the referenced common definitions (artifacts/common/).
# 3. gplint over the Gherkin feature templates (artifacts/testing/).
#
# All three checks gate at error level; warnings and hints are reported but do
# not block. Lint configurations, rule metadata and tool versions are taken
# from camaraproject/tooling at the same pinned ref API repositories use for
# CAMARA Validation, so findings here match the validation toolchain - no local
# copies that could drift.
#
# The Spectral results of the per-template invocations are merged by
# .github/scripts/spectral_annotations.py, which deduplicates them, annotates
# the findings that need review, collapses the findings documented as expected
# into one notice per file, and reports how the counts reconcile. See that
# script's docstring for why each part exists.
#
# The Spectral ruleset is pinned to the release line main currently targets
# (r4.x); update SPECTRAL_RULESET when main starts targeting the next line.
#
# Changelog:
# - 2026-07-16: Initial version (yamllint + Spectral + gplint)
# - 2026-07-29: Spectral runs per template and its results are merged into
# attributed annotations plus a reconciled report
#
# SEE ALSO: artifacts/linting_rules/README.md
# =========================================================================================
name: Artifacts Lint
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: artifacts-lint-${{ github.ref }}
cancel-in-progress: true
env:
TOOLING_REF: v1-rc
SPECTRAL_RULESET: .spectral-r4.yaml
PYTHON_VERSION: "3.14"
NODE_VERSION: "24"
jobs:
lint:
name: Lint artifacts
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
# Lint configurations and dependency pins from tooling at the pinned ref.
- name: Checkout tooling lint configs
uses: actions/checkout@v7
with:
repository: camaraproject/tooling
ref: ${{ env.TOOLING_REF }}
path: .tooling
sparse-checkout: |
linting/config/
requirements.txt
validation/package.json
validation/package-lock.json
validation/.npmrc
validation/rules/spectral-rules.yaml
sparse-checkout-cone-mode: false
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install yamllint (tooling-pinned version)
run: pip install --quiet -r .tooling/requirements.txt
- name: Install Spectral and gplint (tooling-pinned versions)
run: npm ci --ignore-scripts
working-directory: .tooling/validation
# The three checks run independently of each other's outcome, so a PR
# touching several artifact types reports all findings in one run.
- name: yamllint over artifacts/
if: ${{ !cancelled() }}
run: yamllint -c .tooling/linting/config/.yamllint.yaml -f github artifacts/
# One invocation per template, because Spectral loses source attribution
# for most findings when several input files share $ref targets
# (stoplightio/spectral#2640) - the same bug CAMARA Validation works
# around the same way. Findings in transitively referenced common files
# then carry their real artifacts/common/** paths.
#
# Each invocation writes pretty output for the log and JSON for the
# annotation step; JSON goes to a file so it survives the non-zero exit
# of the lint command. A Spectral runtime error (exit status 2 or above)
# on one template does not stop the others - the step reports what the
# remaining templates found and then fails.
- name: Spectral over API and notification templates
if: ${{ !cancelled() }}
env:
NODE_PATH: ${{ github.workspace }}/.tooling/validation/node_modules
run: |
export PATH="${{ github.workspace }}/.tooling/validation/node_modules/.bin:${PATH}"
results="${RUNNER_TEMP}/spectral-results"
mkdir -p "${results}"
shopt -s nullglob
templates=(artifacts/api-templates/*.yaml artifacts/notification-templates/*.yaml)
shopt -u nullglob
if [ ${#templates[@]} -eq 0 ]; then
echo "::error::No templates matched - nothing was linted"
exit 1
fi
status=0
for template in "${templates[@]}"; do
# Path-derived so two templates of the same name in different
# directories cannot overwrite each other's results.
name="${template//\//-}"
rc=0
spectral lint \
--ruleset ".tooling/linting/config/${SPECTRAL_RULESET}" \
--fail-severity error \
-f pretty -f json \
-o.pretty /dev/stdout \
-o.json "${results}/${name}.json" \
"${template}" \
|| rc=$?
printf '%s\t%s\n' "${rc}" "${template}" >> "${results}/status.tsv"
if [ "${rc}" -gt "${status}" ]; then status=$rc; fi
done
python3 .github/scripts/spectral_annotations.py \
--findings-dir "${results}" \
--rules .tooling/validation/rules/spectral-rules.yaml \
--status-file "${results}/status.tsv"
exit $status
# gplint exits non-zero only on error-level findings; warnings are
# reported in the log.
- name: gplint over feature templates
if: ${{ !cancelled() }}
run: |
export PATH="${{ github.workspace }}/.tooling/validation/node_modules/.bin:${PATH}"
gplint --config .tooling/linting/config/.gplintrc artifacts/testing/*.feature