Skip to content

Add governance to my CI/CD

You live in your terminal and your CI/CD pipeline. You want API governance without opening a dashboard.

  • An Apiway tenant (register free — no card, and free credit to explore with; every capability is on every tier, so see pricing only for how much usage each one carries)
  • A CI/CD pipeline (GitHub Actions, GitLab CI, Azure Pipelines, Jenkins — anything that can make HTTP calls)
  • Your OpenAPI specs in your repository
  1. Add a governance check to your pipeline

    On every pull request that changes an OpenAPI spec, call the platform API:

    # GitHub Actions example
    - name: Check API governance
    run: |
    curl -X POST https://core.api.apiway.net/v1/programmes/validate \
    -H "Authorization: Bearer ${{ secrets.APIWAY_TOKEN }}" \
    -H "Content-Type: application/json" \
    -d '{
    "specification": "'$(base64 -w0 openapi.yaml)'"
    }'

    The platform returns:

    • Compliance score against your design standards
    • Breaking change detection against the previous version
    • Security analysis (missing auth, open endpoints)
    • Recommendations for improvement
  2. Fail the build on violations

    Set your quality gate:

    - name: Enforce governance
    run: |
    SCORE=$(curl -s https://core.api.apiway.net/v1/programmes/{id}/compliance \
    -H "Authorization: Bearer ${{ secrets.APIWAY_TOKEN }}" \
    | jq '.score')
    if [ "$SCORE" -lt 80 ]; then
    echo "API compliance score $SCORE is below threshold (80)"
    exit 1
    fi

    Breaking changes? Build fails. Missing security? Build fails. Non-compliant naming? Build fails. All before a human reviewer even looks at it.

    This step checks the design. Your implementation is verified against the contract on every push by default — including code changes that do not touch the contract — with nothing to add to your pipeline.

  3. Auto-deploy on merge

    When the PR merges, deploy through the full pipeline:

    - name: Deploy API
    if: github.ref == 'refs/heads/main'
    run: |
    curl -X POST https://core.api.apiway.net/v1/programmes \
    -H "Authorization: Bearer ${{ secrets.APIWAY_TOKEN }}" \
    -H "Content-Type: application/json" \
    -d '{
    "name": "Orders API",
    "specification": "'$(base64 -w0 openapi.yaml)'"
    }'

    Governance, security, deployment, activation — all automated. The 8-step pipeline runs without a single click.

  4. Use MCP for local development

    Before you even push, your AI coding assistant can check governance:

    “Check if my Orders API spec passes governance”

    “Deploy my updated Payments API to staging”

    “Show me which consumers are subscribed to the Orders API”

    The assistant calls the same platform API. Same governance. Same rules. Different interface.

name: API Governance
on:
pull_request:
paths: ['**/openapi.yaml', '**/openapi.json']
push:
branches: [main]
paths: ['**/openapi.yaml', '**/openapi.json']
jobs:
governance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate & score
id: validate
run: |
RESULT=$(curl -s -X POST https://core.api.apiway.net/v1/programmes/validate \
-H "Authorization: Bearer ${{ secrets.APIWAY_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"specification": "'$(base64 -w0 openapi.yaml)'"}')
echo "score=$(echo $RESULT | jq '.score')" >> $GITHUB_OUTPUT
echo "$RESULT" | jq '.findings[]'
- name: Enforce quality gate
if: github.event_name == 'pull_request'
run: |
if [ "${{ steps.validate.outputs.score }}" -lt 80 ]; then
echo "::error::API governance score ${{ steps.validate.outputs.score }}/100 — below threshold"
exit 1
fi
- name: Deploy
if: github.ref == 'refs/heads/main'
run: |
curl -X POST https://core.api.apiway.net/v1/programmes \
-H "Authorization: Bearer ${{ secrets.APIWAY_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{
"name": "Orders API",
"specification": "'$(base64 -w0 openapi.yaml)'"
}'
  • Automated quality gate — every spec change checked before merge
  • Breaking change detection — caught in the PR, not in production
  • Zero UI dependency — everything via API calls in your pipeline
  • Same governance — CI/CD, CLI, MCP, and UI all enforce the same rules
  • Audit trail — every check, every deploy, every approval recorded

If your team runs its infrastructure through GitOps, your first instinct may be to put Apiway in your repository too: the gateway, the authorisation server, every client and scope, declared in Terraform and applied by your pipeline. It is a sound instinct for infrastructure you own. For a platform you bought, it is like saying “I really like your house — now give me the blueprints so I can rebuild it.” The point of the house is that you do not have to build it.

GitOps assumes one team authors all of the desired state and nothing else changes it. Apiway’s state is produced by many parties, all the time:

  • a customer subscribes at two in the morning, and their credentials and scopes exist;
  • an approver signs off, and a version goes live;
  • a credential rotates on its own schedule;
  • protection acts on a caller that is misbehaving;
  • a new design arrives, and customers start calling its mock.

None of that can wait for a pull request, and most of it is not yours to author — a customer’s sign-up belongs to the customer. A repository mirroring it would always be behind, or a pipeline would be chasing every event. You would not keep your customers’ sign-ups in Git; you keep the contract that decided what they could sign up for.

What your team authors: the contract. Your OpenAPI specification — and your service levels — live in your repository, change through pull requests, and are checked on every push, exactly as the pipeline above shows. That is your one declaration.

Everything else follows from it. Routes, security, per-operation scopes, limits and quotas are derived from the contract rather than configured next to it, so there is no second description to keep in step, and nothing of that kind to drift.

Nothing to configure in the authorisation server

Section titled “Nothing to configure in the authorisation server”

The authorisation server is not something you configure. It behaves as the OAuth 2.0 and OpenID Connect standards say — discovery, signing keys, revocation, PKCE — the same for every customer. Clients, scopes and grants are not settings: they follow from subscriptions and the contract.

That is deliberate. Every setting on an authorisation server is a way to make it less standard and less safe — a longer token lifetime, a weaker way for clients to authenticate, a grant switched on “for now”. Most authorisation-server incidents are misconfigurations. Not having the settings is the security property.

Nothing secret in your pipeline (rolling out)

Section titled “Nothing secret in your pipeline (rolling out)”

Declaring clients and credentials in Terraform brings their secrets back into Terraform state, readable by anyone with the state file, and applying it needs a standing administrator credential stored in your pipeline variables — the kind of secret that leaks most often. With Apiway your pipeline sends a contract and reads results through the API, and it authenticates without a stored secret: the CI system vouches for the pipeline run, and Apiway decides what it may do. (Rolling out: until then, the pipeline credential is an Apiway-issued secret you can rotate and revoke.)

What GitOps gave youWith Apiway
Every change reviewedThe contract changes through pull requests; the gate checks it on push
History and rollbackEvery contract version is kept; roll back to a version; a breaking change cannot go onto a version in use
The same result in every environmentOne contract, promoted through environments; everything else derived the same way each time
Knowing when something changed by handWhat runs is checked against the contract
Not locked into a consoleEverything is an API your pipeline calls; the contract is a file you own

One declaration instead of three, nothing to configure in the authorisation server, and — as federated pipeline credentials roll out — nothing secret in your pipeline.