Builds & Artifacts

Building from source and uploading compiled binaries as artifacts.

An artifact is a compiled binary or bundle stored in zectre-registry. A build takes source (tarball or git ref) and produces an artifact. Once you have an artifact UUID, reference it when creating a deployment.

There are two paths:

PathWhen to use
Upload a binaryYou compiled locally and want to push the binary directly
Build from sourceYou want the platform to compile from a project tarball
Git-triggered buildYou have source config set and want one-command deploy

Upload a binary

POST /api/v1/artifacts — Create record

Creates the artifact metadata entry. The binary is uploaded separately.

Body

  • name (string): Human-readable name
  • content_type (string): e.g. "application/octet-stream"
ARTIFACT_ID=$(curl -sf -X POST http://localhost:47080/api/v1/artifacts \
  -H 'Content-Type: application/json' \
  -d '{"name":"my-app-v1.0","content_type":"application/octet-stream"}' \
  | jq -r .id)

POST /api/v1/artifacts//upload — Upload binary

Body is raw bytes. Proxied to zectre-registry.

curl -X POST http://localhost:47080/api/v1/artifacts/$ARTIFACT_ID/upload \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @./my-app

GET /api/v1/artifacts//download

Download the artifact bytes. Also proxied to zectre-registry.

GET /api/v1/artifacts/

Fetch artifact metadata (name, content type, size, SHA-256).

GET /api/v1/artifacts

List all artifacts.

Full upload example

# 1. Create record
ARTIFACT_ID=$(curl -sf -X POST http://localhost:47080/api/v1/artifacts \
  -H 'Content-Type: application/json' \
  -d '{"name":"my-app-v1.0","content_type":"application/octet-stream"}' \
  | jq -r .id)
 
# 2. Upload binary
curl -X POST http://localhost:47080/api/v1/artifacts/$ARTIFACT_ID/upload \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @./target/release/my-app
 
# 3. Deploy
curl -X POST http://localhost:47080/api/v1/apps/$APP_ID/deployments \
  -H 'Content-Type: application/json' \
  -d "{\"artifact_id\":\"$ARTIFACT_ID\",\"process_type\":\"tish\",\"replicas\":1}"

Build from source

POST /api/v1/builds — Submit

Accepts a multipart body (100MB limit) with two fields:

FieldTypeContent
metadataJSON text{"app_id":"uuid","features":["full"]}
projectfileGzipped tarball of the project
# Pack the project (exclude build outputs)
tar czf /tmp/project.tar.gz --exclude='.git' --exclude='target' .
 
# Submit
BUILD=$(curl -sf -X POST http://localhost:47080/api/v1/builds \
  -F 'metadata={"app_id":"'$APP_ID'","features":["full"]}' \
  -F 'project=@/tmp/project.tar.gz')
 
BUILD_ID=$(echo $BUILD | jq -r .id)

Metadata fields

  • app_id (UUID): The app this build is for
  • features (array, optional): Feature flags for the build (e.g. ["full"], ["http","process"])
  • deployment_id (UUID, optional): If set, build logs are attached to this deployment and the deployment is updated on completion

GET /api/v1/builds/ — Poll status

while true; do
  BUILD=$(curl -sf http://localhost:47080/api/v1/builds/$BUILD_ID)
  STATUS=$(echo $BUILD | jq -r .status)
  STAGE=$(echo $BUILD | jq -r '.stage // ""')
  echo "Build $STATUS$STAGE"
  [ "$STATUS" = "succeeded" ] || [ "$STATUS" = "failed" ] && break
  sleep 5
done
 
ARTIFACT_ID=$(echo $BUILD | jq -r .artifact_id)

Response fields

  • status: pending | running | succeeded | failed
  • progress: 0–100
  • stage: Current build stage (e.g. "compiling", "done")
  • artifact_id: UUID of the produced artifact (populated on success)
  • error: Error message (populated on failure)

Full build + deploy example

import time, requests
 
BASE = "http://localhost:47080"
 
def build_and_deploy(app_id, tarball_path):
    # 1. Submit build
    with open(tarball_path, "rb") as f:
        r = requests.post(f"{BASE}/api/v1/builds", files={
            "metadata": (None, f'{{"app_id":"{app_id}","features":["full"]}}'),
            "project": ("project.tar.gz", f, "application/gzip"),
        })
    build_id = r.json()["id"]
    print(f"Build started: {build_id}")
 
    # 2. Poll
    while True:
        build = requests.get(f"{BASE}/api/v1/builds/{build_id}").json()
        print(f"  {build['status']}{build.get('stage','')}")
        if build["status"] == "succeeded":
            break
        if build["status"] == "failed":
            raise RuntimeError(f"Build failed: {build.get('error')}")
        time.sleep(5)
 
    artifact_id = build["artifact_id"]
 
    # 3. Deploy
    r = requests.post(f"{BASE}/api/v1/apps/{app_id}/deployments", json={
        "artifact_id": artifact_id,
        "process_type": "tish",
        "replicas": 1,
    })
    d = r.json()
    print(f"Deployed: {d['id']} — preview: {d.get('preview_url')}")
    return d

Git-triggered build (deploy/trigger)

If you have source config set up, one call handles build + deploy. See POST /api/v1/apps//deploy/trigger in the Deployments page.

See also