Skip to content

Commit

Permalink
Action-quality-gates (#13)
Browse files Browse the repository at this point in the history
* feat(quality-gates): Add spell checking job

* feat(quality-gates): add api linting job

* chore: update node version

* chore: rename cspell config file

* chore: fix typos and extend custom-words

* chore: fix typos and exclusions

* chore: adjust job execution logic for linting skip

* chore: change how key is passed to SHUB CLI

* chore: jq parse issue

* chore: change file endlines to LF

* chore: set debug

* chore: modify script to deal with jq parsing

* chore: set debug for action output

* chore: add environment

* feat(quality-gates): create utilities script

* chore: log message level

* feat(quality-gates): update ReadMe with job info
  • Loading branch information
frankkilcommins authored Jun 24, 2024
1 parent 270bc0d commit c8b8d3e
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 90 deletions.
19 changes: 19 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"version": "0.2",
"language": "en",
"dictionaries": [
"custom-words"
],
"dictionaryDefinitions": [
{
"name": "custom-words",
"path": "./custom-words.txt",
"description": "Custom dictionary for specific words that are common and correct within our Portal documentation"
}
],
"ignorePaths": [
"**/node_modules/**",
"**/dist/**"
]
}

77 changes: 77 additions & 0 deletions .github/workflows/docs-as-code.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,92 @@ on:
description: 'Log level: 1=DEBUG, 2=INFO, 3=WARNING, 4=ERROR'
required: false
default: '2' # Set the default log level to INFO
skip_api_linting:
description: 'Skip the API linting job'
required: false
default: 'false'

env:
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
LOG_LEVEL: ${{ github.event.inputs.log_level }}

jobs:
spell-check:
runs-on: ubuntu-latest
environment: Production

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Install Node.js
uses: actions/setup-node@v2
with:
node-version: '18'

- name: Install cspell
run: npm install -g cspell

- name: Run cspell
run: cspell --config ./.cspell.json "./products/**/*.md"

lint-api:
runs-on: ubuntu-latest
if: github.event.inputs.skip_api_linting != 'true'
environment: Production

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Install SwaggerHub CLI
run: npm install -g swaggerhub-cli

- name: Iterate over product folders and validate APIs
shell: bash
run: |
# source the utility script
. ./scripts/utilities.sh
for product in ./products/*; do
log_message $DEBUG "Product: $product"
if [[ -d "$product" ]]; then
log_message $DEBUG "Product is a directory"
product_name=${product#./products/}
log_message $DEBUG "Product name: $product_name"
manifest="./products/$product_name/manifest.json"
log_message $DEBUG "Manifest: $manifest"
if [[ -f "$manifest" ]]; then
log_message $DEBUG "Manifest is a file"
validateAPIs=$(jq -r '.productMetadata.validateAPIs' "$manifest")
if [[ "$validateAPIs" == "true" ]]; then
log_message $INFO "Validating APIs for product: $product_name"
contentMetadata=$(jq -c '.contentMetadata[] | select(.type | ascii_downcase == "apiurl")' "$manifest")
echo "$contentMetadata" | jq -c '.' | while IFS= read -r contentMetadataItem; do
slug=$(echo "$contentMetadataItem" | jq -r '.slug')
log_message $INFO "Validating API: $slug"
swaggerhub api:validate "${SWAGGERHUB_ORG_NAME}/$slug" --fail-on-critical
done
else
log_message $WARNING "API validation is not enabled for product: $product_name"
fi
else
log_message $ERROR "Manifest is not a file"
fi
else
log_message $ERROR "Product is not a directory"
fi
done
env:
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
SWAGGERHUB_ORG_NAME: ${{ vars.SWAGGERHUB_ORG_NAME }}


publish:
runs-on: ubuntu-latest
environment: Production
needs: [spell-check, lint-api]
if: github.event.inputs.skip_api_linting == 'true' || (needs.spell-check.result == 'success' && needs['lint-api'].result == 'success')

steps:
- name: Checkout repository
Expand Down
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ A sample manifest is as follows:
"hidden": false,
"logo": "images/AdoptionsAPI.png",
"logoDark": "",
"autoPublish": true
"autoPublish": true,
"validateAPIs": true
},
"contentMetadata": [
{
Expand Down Expand Up @@ -134,6 +135,7 @@ The `productMetadata` defines the following properties:
| logo | The logo property specifies the path to the product logo image file. It is used to display the logo in the portal. |
| logoDark | The logoDark property specifies the path to an alternative version of the product logo image file. It is used when a dark version of the logo is needed. |
| autoPublish | This property determines whether the product should be automatically published after deployment or not. If set to true, the product will be published automatically. If set to false, the product will not be published automatically. |
| validateAPIs | This property determines whether API standardization rules should be ran against the API to determine conformance with organizational rules. |


The `contentMetadata` defines the following properties:
Expand All @@ -158,5 +160,11 @@ The action requires the following **repository secrets** to be configured:
The action requires the following **repository environment** to be configured:
- `Production` - the default environment. Feel free to configure additional environment and adjust the action as required if applicable for your use case.

The action requires the following **repository environment variable** to be configured:
- `SWAGGERHUB_PORTAL_SUBDOMAIN` - the sub-domain used by your portal
The action requires the following **repository environment variables** to be configured:
- `SWAGGERHUB_PORTAL_SUBDOMAIN` - the sub-domain used by your portal
- `SWAGGERHUB_ORG_NAME` - the SwaggerHub organization housing the APIs and standardization rules

The action performs the following jobs:
1. `spell-check`: Performs spell checking on all of the markdown files under the _products_ folder (**note** to add a list of known good custom words update the ./custom-words.txt file)
2. `lint-api`: Performs API standardization checks against each API referenced by a product manifest.json file. There is the ability to skip API validation for a specific API product via the productMetadata in the manifest.json.
3. `publish`: Publishes all of configured products into the referenced SwaggerHub Portal instance.
14 changes: 14 additions & 0 deletions custom-words.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
APIKEY
Arazzo
DevRel
fontname
Kilcommins
Lato
Merriweather
petco
petcopetstore
Petstore
Playfair
Roboto
SmartBear
SWAGGERHUB
105 changes: 53 additions & 52 deletions products/Adopt a Pet/manifest.json
Original file line number Diff line number Diff line change
@@ -1,53 +1,54 @@
{
"productMetadata": {
"description": "This product gives the ability to programmatically embedded a Pet adoption workflow into your application 🐶",
"slug": "pet-adoptions",
"public": true,
"hidden": false,
"logo": "images/AdoptionsAPI.png",
"logoDark": "",
"autoPublish": true
},
"contentMetadata": [
{
"order": 0,
"parent": "",
"name": "Getting Started with Pet Adoptions",
"slug": "getting-started-with-pet-adoptions",
"type": "markdown",
"contentUrl": "Getting-Started-With-Pet-Adoptions.md"
},
{
"order": 1,
"parent": "getting-started-with-pet-adoptions",
"name": "Client Code (C#)",
"slug": "client-code-csharp",
"type": "markdown",
"contentUrl": "Client-Code-Csharp.md"
},
{
"order": 2,
"parent": "getting-started-with-pet-adoptions",
"name": "Client Code (Typescript)",
"slug": "client-code-typescript",
"type": "markdown",
"contentUrl": "Client-Code-Typescript.md"
},
{
"order": 5,
"parent": "",
"name": "Pets API",
"type": "apiUrl",
"slug": "pets-api",
"contentUrl": "https://api.swaggerhub.com/apis/frank-kilcommins/Pets/1.0.0/swagger.json"
},
{
"order": 6,
"parent": "",
"name": "Adoptions API",
"type": "apiUrl",
"slug": "adoptions-api",
"contentUrl": "https://api.swaggerhub.com/apis/frank-kilcommins/Adoptions/1.0.0/swagger.json"
}
]
{
"productMetadata": {
"description": "This product gives the ability to programmatically embedded a Pet adoption workflow into your application 🐶",
"slug": "pet-adoptions",
"public": true,
"hidden": false,
"logo": "images/AdoptionsAPI.png",
"logoDark": "",
"autoPublish": true,
"validateAPIs": true
},
"contentMetadata": [
{
"order": 0,
"parent": "",
"name": "Getting Started with Pet Adoptions",
"slug": "getting-started-with-pet-adoptions",
"type": "markdown",
"contentUrl": "Getting-Started-With-Pet-Adoptions.md"
},
{
"order": 1,
"parent": "getting-started-with-pet-adoptions",
"name": "Client Code (C#)",
"slug": "client-code-csharp",
"type": "markdown",
"contentUrl": "Client-Code-Csharp.md"
},
{
"order": 2,
"parent": "getting-started-with-pet-adoptions",
"name": "Client Code (Typescript)",
"slug": "client-code-typescript",
"type": "markdown",
"contentUrl": "Client-Code-Typescript.md"
},
{
"order": 5,
"parent": "",
"name": "Pets API",
"type": "apiUrl",
"slug": "Pets",
"contentUrl": "https://api.swaggerhub.com/apis/frank-kilcommins/Pets/1.0.0/swagger.json"
},
{
"order": 6,
"parent": "",
"name": "Adoptions API",
"type": "apiUrl",
"slug": "Adoptions",
"contentUrl": "https://api.swaggerhub.com/apis/frank-kilcommins/Adoptions/1.0.0/swagger.json"
}
]
}
6 changes: 3 additions & 3 deletions products/SwaggerHub Portal APIs/Manage-Portal-Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ The following table outlines the settings per level
| branding | `faviconId` | A reference to the favicon attachment. *Note* A *favicon* must be 16x16 pixels, have a `.ico`, `.gif`, or `.png` file format, and be less than 5MB in size. |
| branding | `logoId` | A reference to the logo attachment. *Note* A *logo* must be 64x64 pixels, have a `.jpg`, `.gif`, or `.png` file format, and be less than 5MB in size. |
| branding | `fontName` | The font to use for the portal landing page and for all product pages. Support fonts are `Open Sans`, `Montserrat`, `Roboto`, `Playfair Display`, `Lato`, or `Merriweather`. |
| branding | `accentColor` | A hexidecimal color value to use for the accent color of the landing page and all product pages. |
| branding | `accentColor` | A hexadecimal color value to use for the accent color of the landing page and all product pages. |
| landingPage | `heroImageId` | A reference to the hero image attachment. *Note* A *hero* image can be up to 566 x 80 pixels, have a `.jpg`, or `.png` file format, and be less than 5MB in size. |
| landingPage | `illustrationImageId` | A reference to the illustration image attachment. *Note* An *illustration* image should be at least 566 x 320 pixels, with a 16:9 aspect ratio, have a `.jpg`, or `.png` file format, and be less than 5MB in size. |
| landingPage | `pageDescription` | A short description for the portal landing page (upto 500 characters long). Markdown format supported. |
| landingPage | `pageDescription` | A short description for the portal landing page (up to 500 characters long). Markdown format supported. |

## Retrieve the base information of your portal

Expand Down Expand Up @@ -83,7 +83,7 @@ Below is a sample *request body* which can be supplied with the request.
},
"branding": {
"fontName": "<The fontname to use for portal>",
"accentColor": "<The hexidecimal value for the accent color>"
"accentColor": "<The hexadecimal value for the accent color>"
}
}
```
Expand Down
5 changes: 3 additions & 2 deletions products/SwaggerHub Portal APIs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"hidden": false,
"logo": "images/SwaggerHub.png",
"logoDark": "",
"autoPublish": true
"autoPublish": true,
"validateAPIs": true
},
"contentMetadata": [
{
Expand Down Expand Up @@ -63,7 +64,7 @@
"name": "SwaggerHub Portal API",
"slug":"swaggerhub-portal-api",
"type": "apiUrl",
"contentUrl": "https://api.swaggerhub.com/apis/smartbear-public/swaggerhub-portal-api/0.2.0-beta/swagger.json"
"contentUrl": "https://api.swaggerhub.com/apis/frank-kilcommins/swaggerhub-portal-api/0.2.0-beta/swagger.json"
},
{
"order": 7,
Expand Down
5 changes: 3 additions & 2 deletions products/Zephyr Squad APIs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"hidden": false,
"logo": "images/Zephyr-Squad.png",
"logoDark": "",
"autoPublish": true
"autoPublish": true,
"validateAPIs": false
},
"contentMetadata": [
{
Expand All @@ -31,7 +32,7 @@
"name": "Zephyr Squad Cloud API",
"slug":"zephyr-squad-cloud-api",
"type": "apiUrl",
"contentUrl": "https://api.swaggerhub.com/apis/smartbear-public/zephyr-squad-cloud-api/2.4/swagger.json"
"contentUrl": "https://api.swaggerhub.com/apis/frank-kilcommins/zephyr-squad-cloud-api/2.4/swagger.json"
}
]
}
30 changes: 2 additions & 28 deletions scripts/publish-portal-content.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,8 @@
# - SWAGGERHUB_API_KEY: SwaggerHub API Key
# - SWAGGERHUB_PORTAL_SUBDOMAIN: SwaggerHub Portal subdomain

#trap 'echo "Error on line $LINENO"' ERR

# Log levels
DEBUG=1
INFO=2
WARNING=3
ERROR=4

# Default log level
LOG_LEVEL=${LOG_LEVEL:=$INFO}
# Source the utility script to use its functions
source ./utilities.sh

PORTAL_SUBDOMAIN="${SWAGGERHUB_PORTAL_SUBDOMAIN}"
SWAGGERHUB_API_KEY="${SWAGGERHUB_API_KEY}"
Expand All @@ -30,24 +22,6 @@ declare -g product_id
declare -g document_id

## HELPER FUNCTIONS
log_message() {
local log_level=$1
shift
local message="$@"

case $log_level in
$DEBUG)
([ $LOG_LEVEL -le $DEBUG ] && echo "$(date '+%Y-%m-%d %H:%M:%S') [DEBUG] $message") || true ;;
$INFO)
([ $LOG_LEVEL -le $INFO ] && echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $message") || true ;;
$WARNING)
([ $LOG_LEVEL -le $WARNING ] && echo "$(date '+%Y-%m-%d %H:%M:%S') [WARNING] $message") || true ;;
$ERROR)
([ $LOG_LEVEL -le $ERROR ] && echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $message" >&2) || true ;;
*)
echo "$(date '+%Y-%m-%d %H:%M:%S') [UNKNOWN] $message" ;;
esac
}

function publish_response_check() {
local response=$1
Expand Down
Loading

0 comments on commit c8b8d3e

Please sign in to comment.