CI/CD Integration

Automated Compliance Testing

Integrate Tork SDK verification into your CI/CD pipelines to ensure continuous compliance and catch issues before they reach production.

Why CI/CD Integration?

Prevent Regressions

Catch compliance issues in pull requests before they merge to main.

Continuous Monitoring

Run daily verification checks to maintain compliance over time.

Fast Feedback

Get immediate feedback on your verification score with every commit.

Quick Setup

  1. 1

    Add your API key as a secret

    Store TORK_API_KEY in your CI/CD platform's secret management.

  2. 2

    Copy the configuration for your platform

    Use one of the examples below for GitHub Actions, GitLab CI, Jenkins, or others.

  3. 3

    Customize thresholds and notifications

    Set your minimum score threshold and configure notifications for failures.

What the pipeline install does and does not do

pip install tork-governance installs the on-device package. tork-governance makes the governance decision on your machine. PII detection, redaction and the returned verdict are computed on-device. With no API key it makes zero network calls: prompts, completions and detected PII values never leave the machine, and nothing appears in your dashboard.

The score and certificate these pipelines produce do not come from that package. They come from the verification REST API, which the script below calls with your TORK_API_KEY. The package is installed so the script can report the exact SDK version under test.

Supply an API key and the SDK additionally reports a metadata-only attestation of each decision — the action taken, PII type labels and counts, a risk classification, policy labels and a salted fingerprint. It never sends input text, output text or PII values. The decision itself is still made on-device and is never delayed or changed by reporting. Those attestations appear in your dashboard and are included in the daily on-chain anchor — each one recorded as a client attestation (capture_mode=edge, attested_by=client), a claim Tork recorded but did not execute and cannot independently verify. Requires tork-governance 0.24.0+ (PyPI) or 0.11.0+ (npm).

A decision reported by an on-device SDK is recorded as a client attestation (capture_mode=edge, attested_by=client): a claim Tork recorded but did not execute and cannot independently verify. A decision made by @torknetwork/sdk is recorded as capture_mode=cloud, attested_by=tork — Tork made that call itself. Both are equally immutable once anchored; they differ in what is immutable. A client attestation freezes your claim. A server-governed receipt freezes Tork's own decision.

GitHub Actions

The most comprehensive integration with PR comments and artifacts.

# .github/workflows/tork-verify.yml
name: Tork SDK Verification

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * *' # Daily at midnight

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          pip install tork-governance pytest httpx

      - name: Run Tork Verification
        env:
          TORK_API_KEY: ${{ secrets.TORK_API_KEY }}
        run: |
          python tork_verify.py
          python -c "
          import json, sys
          cert = json.load(open('verification-result.json'))['certification']
          print(f\"Score: {cert['score']}/100\")
          print(f\"Grade: {cert['grade']}\")
          print(f\"Report: {cert['report_url']}\")
          if cert['score'] < 80:
              print('::error::Verification score below threshold')
              sys.exit(1)
          "

      - name: Upload Results
        uses: actions/upload-artifact@v4
        with:
          name: tork-verification
          path: verification-result.json

      - name: Comment on PR
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const { certification } = JSON.parse(fs.readFileSync('verification-result.json'));
            const emoji = certification.score >= 80 ? '✅' : certification.score >= 60 ? '⚠️' : '❌';

            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## ${emoji} Tork Verification Results

| Metric | Value |
|--------|-------|
| Score | **${certification.score}/100** |
| Grade | **${certification.grade}** |
| Tests | ${certification.passed_tests}/${certification.total_tests} passed |

[View Full Report](https://tork.network${certification.report_url})
`
            });

GitLab CI

Native GitLab CI/CD integration with artifacts and merge request rules.

# .gitlab-ci.yml
stages:
  - test
  - verify

tork-verification:
  stage: verify
  image: python:3.11
  variables:
    TORK_API_KEY: $TORK_API_KEY
  script:
    - pip install tork-governance httpx
    - python tork_verify.py
    - |
      python << 'EOF'
      import json
      import sys

      cert = json.load(open("verification.json"))["certification"]

      print(f"Score: {cert['score']}/100")
      print(f"Grade: {cert['grade']}")

      if cert["score"] < 80:
          sys.exit(1)
      EOF
  artifacts:
    paths:
      - verification.json
    reports:
      dotenv: tork-results.env
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Jenkins

Declarative pipeline with email notifications on failure.

// Jenkinsfile
pipeline {
    agent any

    environment {
        TORK_API_KEY = credentials('tork-api-key')
    }

    stages {
        stage('Verify Tork Integration') {
            steps {
                sh '''
                    pip install tork-governance httpx
                    python tork_verify.py
                    python - <<'PY'
import json
import sys

cert = json.load(open("verification.json"))["certification"]

print("Score: {}/100".format(cert["score"]))
print("Grade: {}".format(cert["grade"]))

sys.exit(0 if cert["score"] >= 80 else 1)
PY
                '''
            }
            post {
                always {
                    archiveArtifacts artifacts: 'verification.json'
                }
                failure {
                    emailext(
                        subject: 'Tork Verification Failed',
                        body: 'Score dropped below threshold. Check Jenkins for details.',
                        to: '${DEFAULT_RECIPIENTS}'
                    )
                }
            }
        }
    }
}

CircleCI

CircleCI workflow with context-based credentials.

# .circleci/config.yml
version: 2.1

orbs:
  python: circleci/python@2.1

jobs:
  tork-verify:
    executor: python/default
    steps:
      - checkout
      - run:
          name: Install Tork SDK
          command: pip install tork-governance httpx
      - run:
          name: Run Verification
          command: |
            python tork_verify.py
            python << 'EOF'
            import json
            import sys

            cert = json.load(open("verification.json"))["certification"]

            print(f"Score: {cert['score']}/100")
            print(f"Grade: {cert['grade']}")

            if cert["score"] < 80:
                sys.exit(1)
            EOF
      - store_artifacts:
          path: verification.json
          destination: tork-verification

workflows:
  verify:
    jobs:
      - tork-verify:
          context: tork-credentials

Bitbucket Pipelines

Bitbucket Pipelines with PR-specific verification.

# bitbucket-pipelines.yml
image: python:3.11

pipelines:
  default:
    - step:
        name: Tork Verification
        script:
          - pip install tork-governance httpx
          - python tork_verify.py
          - |
            python << 'EOF'
            import json
            import sys

            cert = json.load(open("verification.json"))["certification"]

            print(f"Score: {cert['score']}/100")
            print(f"Grade: {cert['grade']}")

            sys.exit(0 if cert["score"] >= 80 else 1)
            EOF
        artifacts:
          - verification.json

  pull-requests:
    '**':
      - step:
          name: Verify on PR
          script:
            - pip install tork-governance httpx
            - python tork_verify.py --min-score 80

Best Practices

Set appropriate thresholds

Start with a threshold of 80 and increase as your integration matures. Use different thresholds for PRs vs. main branch.

Run on schedule, not just on push

Schedule daily runs to catch issues with external dependencies or API changes that might affect your score.

Save verification artifacts

Always save the full verification result as an artifact for debugging and compliance audits.

Don't fail silently

Configure notifications for verification failures. Use Slack, email, or your team's preferred channel.

The tork_verify.py Script

The pipelines above call a small script you commit to your repository. It drives the verification REST API — register a session, submit results, request certification — and writes verification.json for the pipeline to read. See Testing Suite for the full endpoint reference and the list of required tests per SDK.

tork_verify.py
import argparse
import json
import os
import platform
import sys

import httpx
from tork_governance import __version__

API_BASE = "https://tork.network"


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--min-score", type=int, default=80)
    parser.add_argument("--save", default="verification.json")
    args = parser.parse_args()

    api_key = os.environ["TORK_API_KEY"]

    # 1. Register a test session
    session = httpx.post(
        f"{API_BASE}/api/v1/testing/register",
        json={
            "api_key": api_key,
            "client_id": f"ci-{platform.node()}",
            "sdk_type": "python",
            "sdk_version": __version__,
            "platform": {
                "os": platform.system().lower(),
                "arch": platform.machine(),
                "runtime_version": platform.python_version(),
            },
        },
        timeout=30,
    ).raise_for_status().json()

    session_id = session["session_id"]
    test_token = session["test_token"]

    # 2. Run the required tests locally and submit the results
    results = [run_test(*t.split(".")) for t in session["test_config"]["required_tests"]]
    httpx.post(
        f"{API_BASE}/api/v1/testing/submit",
        json={
            "session_id": session_id,
            "test_token": test_token,
            "results": results,
            "complete": True,
        },
        timeout=30,
    ).raise_for_status()

    # 3. Request certification
    cert = httpx.post(
        f"{API_BASE}/api/v1/testing/certify",
        json={"session_id": session_id, "test_token": test_token},
        timeout=30,
    ).raise_for_status().json()

    with open(args.save, "w") as f:
        json.dump(cert, f, indent=2)

    score = cert["certification"]["score"]
    print(f"Score: {score}/100  Grade: {cert['certification']['grade']}")
    return 0 if score >= args.min_score else 1


if __name__ == "__main__":
    sys.exit(main())

Need Help?

Our team is here to help you set up CI/CD integration. Reach out if you need assistance with custom configurations or enterprise deployments.