CI/CD intake
Connect GitHub Actions, Jenkins, GitLab CI/CD or AWS CodePipeline to OrkStage. Publish image versions by digest, validate templates, deploy and wait.
Three endpoints exist for pipelines. Pipelines also use the regular deploy and deployment endpoints.
| Method | Path | Scope | Body and result |
|---|---|---|---|
PUT | /api/v1/applications/:name | applications:write | { displayName, repository, port, registryKind?, healthPath?, readinessPath? } |
POST | /api/v1/applications/:name/versions | applications:write | { version, imageUri, digest: "sha256:…", architectures? } |
POST | /api/v1/templates/validate | templates:read | { source, tenantId? }, returns a validation report; with tenantId, also that tenant's limits and feature flags |
POST | /api/v1/instances/:id/deploy | instances:deploy | {}, returns 202 and a deployment summary |
GET | /api/v1/deployments/:id/events?after= | instances:read | Progress events |
Register the application
Every image version belongs to an application in the catalog. Create the application from the pipeline before the first publish. The call is idempotent: the same body sent again changes nothing, so you can run it on every build.
curl -fsS -X PUT "$ORK_API_URL/api/v1/applications/orders-api" -H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json" -d '{ "displayName": "Orders API", "repository": "123456789012.dkr.ecr.us-east-1.amazonaws.com/orders-api", "port": 8080, "healthPath": "/health" }'- A name has 2 to 63 characters: lowercase letters, digits and dashes, starting with a letter.
Other names get
422 INVALID_NAME. registryKindisecr(the default),acr,ocir,gar,dockerhub,ghcrorother.healthPathdefaults to/health.- The response contains
"created": truethe first time. Every change is audited asCREATEorUPDATEonApplication. - The catalog is shared by all tenants, so the call needs an organization key with the
PlatformAdminrole and theapplications:writescope.
Publish an image version
Templates refer to images through the application catalog (image: catalog://orders-api). When
OrkStage compiles an instance, each reference resolves to the most recently published version of
that application, by digest. A deployment therefore always runs an immutable image.
curl -fsS -X POST "$ORK_API_URL/api/v1/applications/orders-api/versions" \
-H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json" \
-d '{
"version": "1.14.2",
"imageUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/orders-api:1.14.2",
"digest": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"architectures": ["amd64", "arm64"]
}'digestmust besha256:followed by 64 lowercase hex characters.architecturesdefaults to["amd64"].- Versions are immutable. Publishing a version again with the same digest is idempotent (the
response has
"idempotent": true). With a different digest it fails with409 VERSION_EXISTS. - Every publish is audited as
PUBLISHonApplicationVersion. - Publishing needs the same organization key as registration: role
PlatformAdmin, scopeapplications:write.
Validate a template in a pull request
The validation endpoint is stateless. It needs no template id and stores nothing.
jq -Rs '{source: .}' < .ork/template.yaml \
| curl -fsS -X POST "$ORK_API_URL/api/v1/templates/validate" \
-H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json" -d @- \
| tee report.json | jq -e '.valid'The report lists every issue with its stage, severity, code, message and path.
Deploy and wait
DEPLOYMENT=$(curl -fsS -X POST "$ORK_API_URL/api/v1/instances/$INSTANCE_ID/deploy" \
-H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json" -d '{}' | jq -r '.id')
while :; do
STATUS=$(curl -fsS "$ORK_API_URL/api/v1/deployments/$DEPLOYMENT" -H "Authorization: Bearer $ORK_TOKEN" | jq -r '.status')
case "$STATUS" in
SUCCEEDED) echo "deployed"; break ;;
FAILED|PARTIALLY_FAILED|CANCELLED) echo "deployment $STATUS"; exit 1 ;;
AWAITING_APPROVAL) echo "waiting for approval in the console…" ;;
esac
sleep 5
doneIf you deploy while another operation is running, the API answers 409 INSTANCE_BUSY. Treat it as
"try again later", not as a failed build.
The examples below call this loop as scripts/orkstage-deploy.sh <instance id>: save it in your
repository with INSTANCE_ID="$1" at the top. Every CI system follows the same three steps:
- Store the API key as a secret of the CI system and expose it as
ORK_TOKEN, withORK_API_URLas a plain variable. Never print it or put it in the repository. - After the image is pushed, publish its version by digest (
POST /applications/:name/versions). - Deploy the instance and wait (
scripts/orkstage-deploy.sh). Production deployments may stop atAWAITING_APPROVALuntil someone approves them in the console.
GitHub Actions
name: release
on:
push:
tags: ['v*']
jobs:
publish-and-deploy:
runs-on: ubuntu-latest
env:
ORK_API_URL: https://orkstage.example.com
ORK_TOKEN: ${{ secrets.ORK_TOKEN }} # organization key (PlatformAdmin): preset "CI/CD deploy" + applications:write
steps:
- uses: actions/checkout@v5
# … build and push the image, capture its digest in steps.push.outputs.digest …
- name: Publish the version to OrkStage
run: |
curl -fsS -X POST "$ORK_API_URL/api/v1/applications/orders-api/versions" \
-H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json" \
-d "{\"version\":\"${GITHUB_REF_NAME#v}\",\"imageUri\":\"$IMAGE:${GITHUB_REF_NAME}\",\"digest\":\"${{ steps.push.outputs.digest }}\"}"
- name: Deploy staging
run: ./scripts/orkstage-deploy.sh "${{ vars.STAGING_INSTANCE_ID }}"To keep publishing and deploying apart, use two keys: an organization key with the Image publishing preset for the publish step, and a tenant key with the CI/CD deploy preset for the deploy step.
Jenkins
Store the key as a Secret text credential with the id orkstage-token.
pipeline {
agent any
environment {
ORK_API_URL = 'https://orkstage.example.com'
ORK_TOKEN = credentials('orkstage-token')
}
stages {
// ... build and push the image, set IMAGE and DIGEST ...
stage('Publish version') {
steps {
sh '''curl -fsS -X POST "$ORK_API_URL/api/v1/applications/orders-api/versions" -H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json" -d "{\"version\":\"$BUILD_NUMBER\",\"imageUri\":\"$IMAGE\",\"digest\":\"$DIGEST\"}"'''
}
}
stage('Deploy staging') {
steps { sh './scripts/orkstage-deploy.sh "$STAGING_INSTANCE_ID"' }
}
}
}GitLab CI/CD
Add ORK_TOKEN under Settings > CI/CD > Variables, masked and protected.
deploy-staging:
stage: deploy
image: alpine:3.22
variables:
ORK_API_URL: https://orkstage.example.com
before_script:
- apk add --no-cache curl jq
script:
# ... the image was pushed in an earlier job; IMAGE and DIGEST come from its dotenv report ...
- >
curl -fsS -X POST "$ORK_API_URL/api/v1/applications/orders-api/versions"
-H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json"
-d "{\"version\":\"$CI_COMMIT_SHORT_SHA\",\"imageUri\":\"$IMAGE\",\"digest\":\"$DIGEST\"}"
- ./scripts/orkstage-deploy.sh "$STAGING_INSTANCE_ID"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCHAWS CodePipeline
Add a CodeBuild action after the build stage. Keep the key in Secrets Manager and let CodeBuild
read it; the CodeBuild role needs secretsmanager:GetSecretValue on that secret only.
version: 0.2
env:
variables:
ORK_API_URL: https://orkstage.example.com
secrets-manager:
ORK_TOKEN: orkstage/ci-token
phases:
build:
commands:
# IMAGE and DIGEST come from the build stage (exported variables or an artifact).
- >
curl -fsS -X POST "$ORK_API_URL/api/v1/applications/orders-api/versions"
-H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json"
-d "{\"version\":\"$CODEBUILD_RESOLVED_SOURCE_VERSION\",\"imageUri\":\"$IMAGE\",\"digest\":\"$DIGEST\"}"
- ./scripts/orkstage-deploy.sh "$STAGING_INSTANCE_ID"The same shape works in Azure Pipelines, CircleCI, Bitbucket Pipelines or any runner with curl
and jq: a secret for the key, one call to publish, one script to deploy and wait.
Notifications instead of polling
Subscribe a webhook to deployment.succeeded, deployment.failed and
deployment.awaiting_approval. Your systems then react to the result without a job that keeps
polling.
Webhooks
Receive signed OrkStage events over HTTPS. Event types, payload, signature checks in Node.js, Python and Go, retries, testing and redelivery.
ork CLI reference
The ork CLI (Preview). Install it, log in with an API key, scan a project into a template, push it, deploy instances. Commands, flags and exit codes.