APIOps for Konnect with kongctl and GitHub Actions

Uses: kongctl

This quickstart builds a CI/CD pipeline to deliver an API and its OpenAPI specification to a Dev Portal using GitOps and GitHub Actions. Store Konnect declarative configuration in GitHub and deploy a GitHub Actions workflow that shows diffs on pull requests and applies changes on pushes to main.

Use a test Konnect organization: this example creates a Dev Portal and API with publicly accessible API documentation.

Prerequisites

  • Konnect access: You need a Konnect account and a personal or system account access token with permission to manage Dev Portals and APIs. For this quickstart in a test organization, you can use an account in the Organization Admin team to get started. For production, follow least privilege: assign only the API roles and Dev Portal roles your workflow needs. See kongctl authentication for token setup.
  • GitHub repository: Use a GitHub repository with Actions enabled and main as its default branch. You need permission to add repository secrets and variables, create branches and pull requests, and merge them into main.

Configure GitHub authentication

In your GitHub repository’s web interface, go to Settings > Secrets and variables > Actions and add:

Type Name Value
Secret KONNECT_TOKEN Your Konnect access token
Variable KONNECT_REGION Your Konnect region, such as us or eu

Create a branch

On your development machine, clone your GitHub repository if necessary and change into its directory. Create a new branch to build this example:

git switch -c konnect-apiops

Declare the Dev Portal and API

Create the configuration directory if it doesn’t already exist:

mkdir -p konnect

On your new branch, create a file konnect/portal.yaml with the following kongctl resource definitions:

portals:
  - ref: example-portal
    name: Example Portal
    display_name: Example Portal
    authentication_enabled: false
    default_api_visibility: public
    default_page_visibility: public

apis:
  - ref: example-api
    name: Example API
    description: A simple API managed with GitHub Actions
    versions:
      - ref: example-api-v1
        version: "1.0.0"
        spec: |
          openapi: 3.0.3
          info:
            title: Example API
            version: 1.0.0
          paths:
            /hello:
              get:
                operationId: getHello
                responses:
                  '200':
                    description: A greeting
    publications:
      - ref: example-api-publication
        portal_id: !ref example-portal#id
        visibility: public

This configuration defines a Dev Portal, an API with an inline OpenAPI specification, and a publication that makes the API available in the Dev Portal. The publication’s !ref links it to the Dev Portal. Authentication is disabled so anyone can read the API documentation. See the Dev Portal example for separate specification files and customization.

Add the GitHub Actions workflow

Create the workflows directory if it doesn’t already exist:

mkdir -p .github/workflows

Create a file .github/workflows/konnect.yaml with the following GitHub Actions workflow definition:

name: Konnect APIOps

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    paths:
      - konnect/**
      - .github/workflows/konnect.yaml
  push:
    branches: [main]
    paths:
      - konnect/**
      - .github/workflows/konnect.yaml

permissions:
  contents: read
  pull-requests: write

concurrency:
  group: konnect-${{ github.ref }}
  cancel-in-progress: false

jobs:
  configure:
    if: >-
      ((github.event_name == 'push' ||
        github.event_name == 'workflow_dispatch') &&
       github.ref == 'refs/heads/main') ||
      (github.event_name == 'pull_request' &&
       github.event.pull_request.head.repo.full_name == github.repository &&
       github.actor != 'dependabot[bot]')
    runs-on: ubuntu-latest
    env:
      KONGCTL_DEFAULT_KONNECT_PAT: ${{ secrets.KONNECT_TOKEN }}
      KONGCTL_DEFAULT_KONNECT_REGION: ${{ vars.KONNECT_REGION }}
      NO_COLOR: '1'
    steps:
      - uses: actions/checkout@v7
      - uses: kong/setup-kongctl@v1
        with:
          kongctl-version: >-
            1.16.0
      - name: Check configuration
        run: |
          : "${KONGCTL_DEFAULT_KONNECT_PAT:?Set the KONNECT_TOKEN secret}"
          : "${KONGCTL_DEFAULT_KONNECT_REGION:?Set KONNECT_REGION}"
      - name: Show diff
        if: github.event_name == 'pull_request'
        shell: bash
        run: |
          kongctl diff --mode apply -f konnect/portal.yaml -o text \
            --region "$KONGCTL_DEFAULT_KONNECT_REGION" | tee diff.txt
          {
            echo '## Konnect configuration diff'
            echo '```text'
            cat diff.txt
            echo '```'
          } > comment.md
          cat comment.md >> "$GITHUB_STEP_SUMMARY"
      - name: Post diff comment
        if: github.event_name == 'pull_request'
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          header: konnect-diff
          path: comment.md
      - name: Apply configuration
        if: >-
          github.ref == 'refs/heads/main' &&
          (github.event_name == 'push' ||
           github.event_name == 'workflow_dispatch')
        run: |
          kongctl apply -f konnect/portal.yaml --auto-approve -o text \
            --region "$KONGCTL_DEFAULT_KONNECT_REGION"

The workflow installs the pinned kongctl version and does the following:

  • On pull requests targeting main: Compares configuration with live Konnect state and posts a diff in the summary and an updating PR comment. It doesn’t apply changes. pull-requests: write allows the comment.
  • On pushes or manual runs on main: Calculates a fresh plan and applies it without prompting. Concurrency prevents overlapping applies. Manual runs on other branches are skipped.

Only give trusted contributors branch access; they can edit workflows that use your Konnect token. Fork and dependency-bot pull requests are skipped because they don’t receive repository secrets.

The version comes from the Kong Developer site’s shared release data when the page is built. Your copied workflow stays pinned; update kongctl-version when you’re ready to upgrade.

Review and deploy

  1. Commit both files, push your branch, and open a PR targeting main. Wait for the Konnect APIOps workflow to finish, then review its diff comment.
  2. Merge the PR. In Actions, open the Konnect APIOps run for the push to main, then open configure > Apply configuration. Expect four creates in the default namespace: portal, api, api_version, and api_publication, followed by successful creation messages. Open your Dev Portal in Konnect and verify the published API and spec.

Every matching push to main deploys, including direct pushes. Use branch rules if all changes must go through PR review. apply creates and updates resources; use sync when you want removed declarations to delete resources.

Update the API

  1. On your development machine, switch to main, pull the merged changes, and create a new branch:

    git switch main
    git pull --ff-only
    git switch -c update-example-api
  2. In konnect/portal.yaml, change the API’s description to An example API deployed with GitOps.
  3. Commit the change, push your branch, and open a PR targeting main. Wait for the Konnect APIOps workflow to finish, then check that its diff comment shows an update to the API description.
  4. Merge the PR and check that the Apply configuration step succeeds. Open your Dev Portal and verify that the API description has changed.
  5. In your GitHub repository’s Actions tab, select Konnect APIOps, click Run workflow, select the main branch, and confirm with Run workflow. When the run completes, open configure > Apply configuration. It should report no further changes if the configuration and live state are unchanged.

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!