Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions .github/workflows/artifacts-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# =========================================================================================
# 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/) 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 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 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)
#
# 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
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/

# Findings in transitively referenced common files carry their real
# artifacts/common/** paths. The github-actions output goes to a file
# first so annotations survive the non-zero exit of the lint command.
- 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}"
status=0
spectral lint \
--ruleset ".tooling/linting/config/${SPECTRAL_RULESET}" \
--fail-severity error \
-f pretty -f github-actions \
-o.pretty /dev/stdout \
-o.github-actions "${RUNNER_TEMP}/spectral-annotations.log" \
artifacts/api-templates/*.yaml artifacts/notification-templates/*.yaml \
|| status=$?
cat "${RUNNER_TEMP}/spectral-annotations.log"
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
blank_issues_enabled: true
contact_links:
- name: 🗣 Subproject discussions
- name: 🗣 Subproject discussions
url: https://github.com/camaraproject/Commonalities/discussions
about: Please ask and answer questions here.
- name: 📖 CAMARA API Design Guidelines
Expand Down
4 changes: 2 additions & 2 deletions artifacts/api-templates/sample-implicit-events.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@

externalDocs:
description: Product documentation at CAMARA
url: https://github.com/camaraproject/apiRepository
# {apiRepository} MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted.
url: https://github.com/camaraproject/APIRepositoryName
# APIRepositoryName MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted.
servers:
- url: "{apiRoot}/sample-implicit-events/vwip"
variables:
Expand Down Expand Up @@ -439,10 +439,10 @@
required:
- name
properties:
name:
type: string
maxLength: 128
description: Human-readable name for the resource

Check warning on line 445 in artifacts/api-templates/sample-implicit-events.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

owasp:api4:2023-string-restricted

Schema of type string should specify a format, pattern, enum, or const.
device:
$ref: "../common/CAMARA_common.yaml#/components/schemas/Device"
sink:
Expand All @@ -464,10 +464,10 @@
properties:
resourceId:
$ref: "#/components/schemas/ResourceId"
name:
type: string
maxLength: 128
description: Human-readable name for the resource

Check warning on line 470 in artifacts/api-templates/sample-implicit-events.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

owasp:api4:2023-string-restricted

Schema of type string should specify a format, pattern, enum, or const.
device:
$ref: "../common/CAMARA_common.yaml#/components/schemas/Device"
sink:
Expand Down Expand Up @@ -537,26 +537,26 @@
# Concrete event schemas — API-specific (API project-owned)
# ─────────────────────────────────────────────────────────────────────────

EventApiSpecific1:
description: event structure for event-type event 1
allOf:
- $ref: "#/components/schemas/ApiNotificationEvent"
- type: object
properties:
data:
type: object
description: |
Event-specific payload for event-type1.
Replace with the actual data schema for this event type.

Check warning on line 551 in artifacts/api-templates/sample-implicit-events.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

oas3-unused-component

Potentially unused component has been detected.
EventApiSpecific2:
description: event structure for event-type event 2
allOf:
- $ref: "#/components/schemas/ApiNotificationEvent"
- type: object
properties:
data:
type: object
description: |
Event-specific payload for event-type2.
Replace with the actual data schema for this event type.

Check warning on line 562 in artifacts/api-templates/sample-implicit-events.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

oas3-unused-component

Potentially unused component has been detected.
4 changes: 2 additions & 2 deletions artifacts/api-templates/sample-service-subscriptions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ info:

externalDocs:
description: Product documentation at CAMARA
url: https://github.com/camaraproject/apiRepository
# {apiRepository} MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted.
url: https://github.com/camaraproject/APIRepositoryName
# APIRepositoryName MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted.
servers:
- url: "{apiRoot}/sample-service-subscriptions/vwip"
variables:
Expand Down
4 changes: 2 additions & 2 deletions artifacts/api-templates/sample-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ info:
x-camara-commonalities: wip
externalDocs:
description: Product documentation at CAMARA
url: https://github.com/camaraproject/{apiRepository}
# {apiRepository} MUST be replaced by the CAMARA API Repository name where the API specification is hosted.
url: https://github.com/camaraproject/APIRepositoryName
# APIRepositoryName MUST be replaced by the CAMARA API Repository name where the API specification is hosted.
servers:
- url: "{apiRoot}/sample-service/vwip"
variables:
Expand Down
2 changes: 1 addition & 1 deletion artifacts/common/CAMARA_event_common.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
info:
title: CAMARA common event and subscription data types
description: |
description: |

Check failure on line 3 in artifacts/common/CAMARA_event_common.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

3:17 [trailing-spaces] trailing spaces
Common data types for CAMARA event notification and subscription management.
This file contains Commonalities-owned schemas that are identical across all
CAMARA APIs supporting event notifications and/or explicit subscriptions.
Expand Down Expand Up @@ -47,19 +47,19 @@
- type
- time
properties:
id:
type: string
maxLength: 256
description: Identifier of this event, unique within the source context.

Check warning on line 53 in artifacts/common/CAMARA_event_common.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

owasp:api4:2023-string-restricted

Schema of type string should specify a format, pattern, enum, or const.
source:
$ref: "#/components/schemas/Source"
type:
type: string
maxLength: 512
description: |
Identifies the event type. CAMARA APIs use reverse-DNS notation:
`org.camaraproject.<api-name>.<event-version>.<event-name>`
The api-name segment makes each type globally unique across API groups.

Check warning on line 62 in artifacts/common/CAMARA_event_common.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

owasp:api4:2023-string-restricted

Schema of type string should specify a format, pattern, enum, or const.
specversion:
type: string
description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version)
Expand Down
17 changes: 17 additions & 0 deletions artifacts/linting_rules/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
Linting rules and their usage documentation are maintained within CAMARA [tooling repository](https://github.com/camaraproject/tooling/tree/main/linting).

## Linting of the artifacts in this repository

The [Artifacts Lint workflow](../../.github/workflows/artifacts-lint.yml) runs on every pull request and on pushes to `main`:

- **yamllint** over all YAML files in `artifacts/` (including `Github_templates/`, whose installed copies in API repositories are not checked there)
- **Spectral** over the full-OpenAPI templates (`api-templates/`, `notification-templates/`) with the CAMARA ruleset of the release line under development; `$ref` resolution transitively checks the referenced definitions in `common/`
- **gplint** over the Gherkin feature templates (`testing/`)

Lint configurations and tool versions are taken from the [tooling repository](https://github.com/camaraproject/tooling/tree/main/linting/config) at the same pinned ref API repositories use for CAMARA Validation, so findings here match the validation toolchain.

All three checks block only on error-level findings; warnings and hints are reported in the workflow log but do not fail the check.

### When a check fails

- The finding points at a real problem in the changed artifact (parse error, violated convention): fix the content.
- The artifact is intentional and the rule itself no longer matches a Commonalities convention: the rules live in the tooling repository, so open a paired change there — the tooling change merges first, then the change in this repository lints green.
4 changes: 2 additions & 2 deletions artifacts/notification-templates/sample-notification.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
- url: "{apiRoot}"
variables:
apiRoot:
default: https://localhost:8080

Check notice on line 24 in artifacts/notification-templates/sample-notification.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

camara-api-root-default

apiRoot default should be 'http://localhost:9091', got 'https://localhost:8080'.
description: Can be any notification server address sent by the client application

Check notice on line 25 in artifacts/notification-templates/sample-notification.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

camara-api-root-description

apiRoot description does not match the standard CAMARA text.

tags:
- name: CAMARA Cloud Event
Expand All @@ -33,40 +33,40 @@
- {}

paths:
/your_webhook_notification_url:
post:
tags:
- CAMARA Cloud Event
summary: Cloud Event notification endpoint to notify consumer that statement of fact had occurred
description: |
INFORMATIVE ENDPOINT: The value of this endpoint is freely declared by each client app by means of resource-based
subscription or instance-based subscription. `/your_webhook_notification_url` is
subscription or instance-based subscription. `/your-webhook-notification-url` is
just a convention naming referring to an absolute URL, indeed the one indicated by API client
in the triggering of the procedure (resource-based or instance-based). In this way, it represents an absolute
URL, i.e.: notifications won't be sent to `/event-notification/vX/your_webhook_notification_url`.
URL, i.e.: notifications won't be sent to `/event-notification/vX/your-webhook-notification-url`.
operationId: sendEvent
parameters:
- $ref: "../common/CAMARA_common.yaml#/components/parameters/x-correlator"
requestBody:
required: true
content:
application/cloudevents+json:
schema:
$ref: "../common/CAMARA_event_common.yaml#/components/schemas/CloudEvent"
responses:
"204":
description: No Content
headers:
x-correlator:
$ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator"
"400":
$ref: "../common/CAMARA_common.yaml#/components/responses/Generic400"
"401":
$ref: "../common/CAMARA_common.yaml#/components/responses/Generic401"
"403":
$ref: "../common/CAMARA_common.yaml#/components/responses/Generic403"
"429":
$ref: "../common/CAMARA_common.yaml#/components/responses/Generic429"

Check failure on line 69 in artifacts/notification-templates/sample-notification.yaml

View workflow job for this annotation

GitHub Actions / Lint artifacts

camara-path-casing-convention

/your_webhook_notification_url is not kebab-case: Object{} must match the pattern "^/([a-z0-9]+(-[a-z0-9]+)*)?(/[a-z0-9]+(-[a-z0-9]+)*|/{.+})*$"

components:
securitySchemes:
Expand Down
Loading