Skip to content
Merged
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
76 changes: 76 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: CI

on:
pull_request:
branches:
- main

jobs:
validate-pr:
uses: entur/gha-meta/.github/workflows/verify-pr.yml@v1

lint-reference-spec:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- name: Install Spectral
run: npm install -g @stoplight/spectral-cli
- name: Lint OpenAPI
shell: bash
run: |
set -o errexit
set -o nounset
set -o pipefail

annotations=$(mktemp)
markdown=$(mktemp)
spectral lint ./specs/reference-spec.json --ruleset ".spectral.yml" -F hint -f github-actions -o.github-actions "$annotations" -f markdown -o.markdown="$markdown" && rc=$? || rc=$?

#Return code 2 means that spectral command failed to run (not linting errors), so fail workflow.
if [ "$rc" -eq 2 ]; then
echo "::error::Spectral execution error (exit code $rc)."
exit $rc
fi

if [ "$rc" -eq 1 ]; then
cat $annotations
cat $markdown >> $GITHUB_STEP_SUMMARY
echo
echo "::error::There were linting errors (exit code $rc)."
exit $rc
fi

lint-reference-spec-with-errors:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- name: Install Spectral
run: npm install -g @stoplight/spectral-cli
- name: Lint OpenAPI
shell: bash
run: |
set -o errexit
set -o nounset
set -o pipefail

annotations=$(mktemp)
markdown=$(mktemp)
spectral lint ./specs/reference-spec-with-errors.json --ruleset ".spectral.yml" -F hint -f github-actions -o.github-actions "$annotations" -f markdown -o.markdown="$markdown" && rc=$? || rc=$?

#Return code 2 means that spectral command failed to run (not linting errors), so fail workflow.
if [ "$rc" -eq 2 ]; then
echo "::error::Spectral execution error (exit code $rc)."
exit $rc
fi

if [ "$rc" -ne 1 ]; then
echo "::error::There were no linting errors when there should be (exit code $rc)."
exit $rc
else
cat $annotations
cat $markdown >> $GITHUB_STEP_SUMMARY
fi
13 changes: 0 additions & 13 deletions .github/workflows/pr-validate.yml

This file was deleted.

284 changes: 284 additions & 0 deletions specs/reference-spec-with-errors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
{
"openapi": "3.1.0",
"info": {
"title": "Items API",

Check warning on line 4 in specs/reference-spec-with-errors.json

View workflow job for this annotation

GitHub Actions / lint-reference-spec-with-errors

entur-info-title-no-api

API titles SHOULD NOT contain the word 'api'.
"version": "1.0.0",
"description": "A long and descriptive description",
"termsOfService": "https://developer.entur.org/terms-of-service",
"contact": {
"name": "API Support",
"url": "https://entur.no",
"email": "support@entur.no"
},
"x-entur-metadata": {
"id": "Items",

Check failure on line 14 in specs/reference-spec-with-errors.json

View workflow job for this annotation

GitHub Actions / lint-reference-spec-with-errors

entur-info-metadata-id-kebab-case

The "x-entur-metadata.id" MUST be in lower-kebab-case format. Invalid value: Items
"owner": "api",
"audience": "public"
}
},

"tags": [
{"name": "Items"}
],
"servers": [
{
"url": "https://api.entur.io/product/v1",
"description": "Production"
},
{
"url": "https://api.staging.entur.io/product/v1",
"description": "Staging"
}
],
"components": {
"parameters": {
"Item-Id": {
"name": "itemId",
"description": "The item ID.",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"example": "100"
},
"Page": {
"description": "Results page you want to retrieve (0..N)",
"in": "query",
"required": true,
"name": "page",
"schema": { "type": "integer", "example": 0 }
},
"Page-Size": {
"description": "Number of records per page.",
"in": "query",
"name": "size",
"schema": { "type": "integer", "example": 20 }
}
},
"schemas": {
"Item": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "100"
},
"name": {
"type": "string",
"example": "Item 100"
}
},
"example": {
"id": "100",
"name": "Item 100"
}
},
"Items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Item"
},
"example": [
{
"id": "100",
"name": "Item 100"
},
{
"id": "101",
"name": "Item 101"
}
]
},
"Problem": {
"type": "object",
"properties": {
"type": {
"type": "string",
"example": "https://example.com/probs/invalid-parameter"
},
"title": {
"type": "string",
"example": "Invalid parameter"
},
"detail": {
"type": "string",
"example": "The parameter 'exampleParameter' is invalid."
},
"status": {
"type": "integer",
"example": 400
}
},
"example": {
"type": "https://example.com/probs/invalid-parameter",
"title": "Invalid parameter",
"detail": "The parameter 'exampleParameter' is invalid.",
"status": 400
}
}
},
"securitySchemes": {
"jwt": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
}
},
"paths": {
"/items": {
"get": {
"tags": [
"Items"
],
"parameters": [
{
"$ref": "#/components/parameters/Page"
},
{
"$ref": "#/components/parameters/Page-Size"
},
{
"name": "status",
"description": "Filters items to return on status",
"in": "query",
"schema": {
"type": "string"
},
"example": "completed"
}
],
"summary": "Get items",
"description": "Get items matching a status filter, with pagination support.",
"operationId": "getItems",
"responses": {
"200": {
"description": "Get items",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Items"
}
}
}
}
},
"x-entur-permissions": {
"value": "items:les"
}
},
"post": {
"tags": [
"Items"
],
"security": [{"jwt": []}],
"summary": "Create an item",
"description": "Create a new item, given in request body.",
"operationId": "createItem",
"requestBody": {
"description": "Item to create",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
}
},
"x-entur-permissions": {
"description": "You need access to read organisations, and create items.",
"value": {
"all": [
"organisations:les",
{
"any": [
"items:opprett",
"items-global:opprett"
]
}
]
}
}
}
},
"/items/{itemId}": {
"parameters": [
{
"$ref": "#/components/parameters/Item-Id"
}
],
"get": {
"tags": [
"Items"
],
"summary": "Get an item",
"description": "Get an item with given id.",
"operationId": "getItem",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Problem"
}
}
}
}
}
},
"put": {
"tags": [
"Items"
],
"security": [{"jwt": []}],
"summary": "Update an item",
"description": "Update an item according to given item request body.",
"operationId": "updateItem",
"requestBody": {
"description": "Item to update",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
}
}
}
}
}
}
6 changes: 4 additions & 2 deletions specs/reference-spec.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"openapi": "3.1.0",
"info": {
"title": "Example",
"title": "Items",
"version": "1.0.0",
"description": "A long and descriptive description",
"termsOfService": "https://developer.entur.org/terms-of-service",
Expand All @@ -11,7 +11,9 @@
"email": "support@entur.no"
},
"x-entur-metadata": {
"id": "example"
"id": "items",
"owner": "team-api",
"audience": "partner"
}
},

Expand Down