Skip to content

AI Gateway uses GitHub Actions for continuous integration and deployment. The main CI pipeline runs on every push and pull request to main, with additional workflows for code analysis, dependency review, releases, and supply-chain scoring.

The CI pipeline has 6 jobs. The first 4 run in parallel as quality and security gates. The build and deploy jobs run sequentially, gated on all 4 passing.

flowchart TD
    trigger[Push / PR to main] --> quality
    trigger --> sast
    trigger --> iac
    trigger --> container

    subgraph "Parallel Quality + Security Gates"
        quality[Code Quality<br>ruff lint + format<br>pyright typecheck]
        sast[SAST<br>semgrep scan<br>gitleaks secrets]
        iac[IaC Security<br>terraform fmt + validate<br>terraform-docs check<br>TFLint + Checkov]
        container[Container Security<br>hadolint lint<br>trivy image scan<br>syft SBOM]
    end

    quality --> gate{All passed?}
    sast --> gate
    iac --> gate
    container --> gate

    gate -->|main branch push only| build[Build and Push<br>Pull + tag image<br>Push to ECR<br>cosign sign]
    build --> deploy[Deploy to ECS<br>Force new deployment<br>Wait for stability]

Trigger: Every push and PR to main.

StepWhat It Checks
ruff checkLint Python code (30+ rule sets, --output-format=github for inline annotations)
ruff format —checkVerify code formatting matches ruff standards
pyrightType check src/ in standard mode

Fails when: Any lint violation, formatting difference, or type error is found.

2. SAST (Static Application Security Testing)

Section titled “2. SAST (Static Application Security Testing)”

Trigger: Every push and PR to main.

StepWhat It Checks
SemgrepPython code against OWASP Top 10, security audit, and Python-specific rules
GitleaksRepository history for leaked secrets, API keys, and credentials

Fails when: Semgrep finds a security issue or gitleaks detects a secret.

Trigger: Every push and PR to main.

StepWhat It Checks
terraform fmt -checkTerraform files are properly formatted
terraform validateTerraform configuration is syntactically valid
terraform-docsGenerated documentation in infrastructure/README.md is up to date
TFLintTerraform linting with AWS ruleset (naming conventions, documented variables, unused declarations)
Checkov2,500+ Terraform security policies (output as SARIF, uploaded to GitHub Security tab)

Fails when: Any formatting issue, validation error, outdated docs, lint violation, or Checkov policy failure.

Trigger: Every push and PR to main.

StepWhat It Checks
HadolintDockerfile best practices (ShellCheck integration, SARIF output)
TrivyVulnerability scan of the Portkey gateway image (CRITICAL + HIGH, exit code 1 on findings)
SyftSBOM generation in CycloneDX format (uploaded as artifact, 90-day retention)

Fails when: Hadolint finds violations, or trivy finds CRITICAL/HIGH vulnerabilities in the container image.

Trigger: Push to main only (not PRs). Requires: All 4 gate jobs passed.

StepWhat It Does
Configure AWS credentialsOIDC-based assume-role (no long-lived keys)
Login to ECRAuthenticate with Amazon ECR
Pull + tag + pushPull portkeyai/gateway:1.15.2, tag with SHA and latest, push to ECR
cosign signKeyless image signing via Sigstore OIDC

Trigger: Push to main only. Requires: Build-and-push completed. Environment: production.

StepWhat It Does
Force new deploymentaws ecs update-service --force-new-deployment
Wait for stabilityaws ecs wait services-stable (10-minute timeout)

The security scanning follows the 3-phase architecture from ADR-004:

flowchart LR
    subgraph "Phase 1: Pre-Build"
        H[hadolint<br>Dockerfile lint]
        CH[checkov<br>IaC security<br>2500+ policies]
    end

    subgraph "Phase 2: Post-Build"
        T[trivy<br>Image vulnerabilities<br>HIGH + CRITICAL]
        S[syft<br>SBOM generation<br>CycloneDX]
    end

    subgraph "Phase 3: Post-Scan"
        CO[cosign<br>Keyless signing<br>Sigstore OIDC]
    end

    H --> T
    CH --> T
    T --> CO
    S --> CO

Beyond the main CI pipeline, 4 additional workflows provide continuous security monitoring.

File: .github/workflows/codeql.yml

AspectDetail
TriggerPush to main, PRs to main, weekly schedule (Monday 06:15 UTC)
LanguagesPython
Query suitessecurity-and-quality (extended rules)
OutputSARIF uploaded to GitHub Security tab

CodeQL performs deep semantic analysis of Python code, detecting vulnerabilities that pattern-based tools like semgrep may miss.

File: .github/workflows/dependency-review.yml

AspectDetail
TriggerPull requests to main only
Fail thresholdHIGH severity vulnerabilities
Denied licensesGPL-3.0, AGPL-3.0 (and -only, -or-later variants)
PR commentsSummary posted on every PR

Blocks PRs that introduce vulnerable or incompatibly-licensed dependencies.

File: .github/workflows/release.yml

AspectDetail
TriggerTag push matching v* (e.g., v1.0.0, v1.1.0-rc.1)
Image tagsv* tag, SHA, and latest pushed to ECR
Signingcosign keyless signing
SBOMsDual format: CycloneDX JSON + SPDX JSON
GitHub ReleaseAuto-generated changelog, container image digest, verification command
Pre-releaseTags containing -rc, -beta, or -alpha are marked as pre-release

File: .github/workflows/scorecard.yml

AspectDetail
TriggerPush to main, branch protection rule changes, weekly schedule (Monday 07:30 UTC)
OutputSARIF uploaded to GitHub Security tab, score published to scorecard.dev

Evaluates the repository against OpenSSF best practices for supply chain security.

Dependabot monitors 3 ecosystems for outdated dependencies. All checks run weekly on Mondays at 08:00 Eastern.

EcosystemDirectoryPR LimitGroupingCommit Prefix
pip (Python)/10Minor + patch groupeddeps(python):
Terraform/infrastructure5Minor + patch groupeddeps(terraform):
GitHub Actions/10Minor + patch groupeddeps(actions):

All Dependabot PRs are assigned to @theagenticguy and labeled by ecosystem.

To create a release:

  1. Ensure main is in a releasable state (all CI passing).

  2. Create and push a version tag:

    Terminal window
    git tag v1.0.0
    git push origin v1.0.0
  3. The release workflow automatically:

    • Pulls and tags the Portkey gateway image with the version.
    • Pushes to ECR with version, SHA, and latest tags.
    • Signs the image with cosign (keyless via Sigstore OIDC).
    • Generates dual SBOMs (CycloneDX + SPDX).
    • Creates a GitHub Release with auto-generated changelog and SBOM attachments.

Both the CI and CodeQL workflows use concurrency groups tied to workflow + ref. This means:

  • A new push to the same branch cancels any in-progress run for that branch.
  • Multiple branches can run in parallel.
  • The pages deployment uses a dedicated concurrency group to prevent overlapping deploys.