Get Started

Three steps to
governed architecture

ArchRails enforces your CALM architecture on every pull request. Get from zero to your first automated review in under a day. Walk through the steps below in order — each one tells you exactly what to verify before moving on.

1

Get provisioned

Sign up and your tenant is ready in seconds.

Sign up with your work email. We mint a tenant ID + signing secret automatically — no operator in the loop. The 14-day Trial includes the full Team-tier toolkit on private repos.

2

Wire your repo

Add a workflow file so each PR triggers an ArchRails review.

# .github/workflows/archrails.yml
name: ArchRails Architecture Check
on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review, closed]
jobs:
  archrails-check:
    name: Architecture Governance
    runs-on: ubuntu-latest
    if: github.event.action != 'closed' || github.event.pull_request.merged == true
    permissions:
      contents:      write
      pull-requests: write
      statuses:      write
    steps:
      - name: Dispatch to ArchRails
        id:   dispatch
        env:
          ARCHRAILS_TENANT_ID:    ${{ secrets.ARCHRAILS_TENANT_ID }}
          ARCHRAILS_TOKEN:        ${{ secrets.ARCHRAILS_TOKEN }}
          ARCHRAILS_URL:          ${{ secrets.ARCHRAILS_WEBHOOK_URL }}
          ARCHRAILS_PARENT_TOKEN: ${{ secrets.ARCHRAILS_PARENT_TOKEN }}
          GITHUB_TOKEN:           ${{ secrets.GITHUB_TOKEN }}
          PR_EVENT:               ${{ toJson(github.event) }}
          RUN_ID:                 ${{ github.run_id }}
          RUN_ATTEMPT:            ${{ github.run_attempt }}
        run: |
          : "${ARCHRAILS_TENANT_ID:?ARCHRAILS_TENANT_ID secret is required}"
          : "${ARCHRAILS_TOKEN:?ARCHRAILS_TOKEN secret is required}"
          : "${ARCHRAILS_URL:?ARCHRAILS_WEBHOOK_URL secret is required}"

          PAYLOAD=$(echo "$PR_EVENT" | jq \
            --arg tenant_id    "$ARCHRAILS_TENANT_ID" \
            --arg parent_token "$ARCHRAILS_PARENT_TOKEN" \
            --arg github_token "$GITHUB_TOKEN" \
            '. + {archrails_tenant_id: $tenant_id, archrails_parent_token: $parent_token, github_token: $github_token}')

          RESP=$(curl -sS -o /tmp/ar_resp.json -w "%{http_code}" \
            --max-time 30 \
            -X POST "$ARCHRAILS_URL" \
            -H "Content-Type: application/json" \
            -H "X-GitHub-Event: pull_request" \
            -H "X-GitHub-Delivery: ${RUN_ID}-${RUN_ATTEMPT}" \
            -H "X-ArchRails-CI: github" \
            -H "X-ArchRails-Token: $ARCHRAILS_TOKEN" \
            -d "$PAYLOAD")

          echo "ArchRails response: $RESP"
          cat /tmp/ar_resp.json; echo

          if [[ "$RESP" == "204" ]]; then
            echo "ArchRails skipped this event — nothing to poll."
            exit 0
          fi
          if [[ "$RESP" != "202" ]]; then
            echo "::error::ArchRails rejected the payload (HTTP $RESP)."
            exit 1
          fi

          RUN_ID_OUT=$(jq -r '.run_id // empty' /tmp/ar_resp.json)
          if [[ -z "$RUN_ID_OUT" ]]; then
            echo "::error::ArchRails queued the run but did not return a run_id."
            exit 1
          fi
          echo "run_id=$RUN_ID_OUT" >> "$GITHUB_OUTPUT"
          echo "ArchRails review queued as $RUN_ID_OUT."

      - name: Wait for ArchRails review
        if: steps.dispatch.outputs.run_id
        env:
          ARCHRAILS_TENANT_ID: ${{ secrets.ARCHRAILS_TENANT_ID }}
          ARCHRAILS_TOKEN:     ${{ secrets.ARCHRAILS_TOKEN }}
          ARCHRAILS_URL:       ${{ secrets.ARCHRAILS_WEBHOOK_URL }}
          RUN_ID_OUT:          ${{ steps.dispatch.outputs.run_id }}
        timeout-minutes: 10
        run: |
          POLL_URL="${ARCHRAILS_URL%/}/run/${RUN_ID_OUT}"

          for i in $(seq 1 60); do
            BODY=$(curl -sS --max-time 15 \
              -H "X-ArchRails-Token: $ARCHRAILS_TOKEN" \
              -H "X-ArchRails-Tenant-Id: $ARCHRAILS_TENANT_ID" \
              "$POLL_URL")
            STATUS=$(echo "$BODY" | jq -r '.status // "unknown"')
            case "$STATUS" in
              completed) echo "ArchRails review completed."; exit 0 ;;
              failed)    echo "::error::ArchRails review failed: $(echo "$BODY" | jq -r '.error // "unknown"')"; exit 1 ;;
              running|queued) : ;;
              *)         echo "Unexpected status '$STATUS' — body: $BODY" ;;
            esac
            sleep 10
          done
          echo "::error::Timed out waiting for ArchRails review ($RUN_ID_OUT)"
          exit 1
# .gitlab-ci.yml — append to your existing file
archrails:
  stage: review
  image: alpine:latest
  only: [merge_requests]
  variables:
    ARCHRAILS_API: "https://ugq071csi5.execute-api.us-east-2.amazonaws.com"
  before_script:
    - apk add --no-cache curl jq
  script:
    - |
      RUN=$(curl -fsS -X POST "$ARCHRAILS_API/webhook/gitlab" \
        -H "X-ArchRails-Token: $ARCHRAILS_TENANT_TOKEN" \
        -H "X-ArchRails-Tenant-Id: $ARCHRAILS_TENANT_ID" \
        -H "Content-Type: application/json" \
        -d "{
          \"object_kind\": \"merge_request\",
          \"project\":  { \"id\": \"$CI_PROJECT_ID\", \"path_with_namespace\": \"$CI_PROJECT_PATH\" },
          \"object_attributes\": { \"iid\": \"$CI_MERGE_REQUEST_IID\", \"action\": \"open\" }
        }")
      RUN_ID=$(echo "$RUN" | jq -r '.run_id')
      while :; do
        STATUS=$(curl -fsS "$ARCHRAILS_API/webhook/github/run/$RUN_ID" \
          -H "X-ArchRails-Token: $ARCHRAILS_TENANT_TOKEN" \
          -H "X-ArchRails-Tenant-Id: $ARCHRAILS_TENANT_ID" | jq -r '.status')
        case "$STATUS" in
          SUCCEEDED|FAILED|TIMED_OUT|ABORTED) break ;;
          *) sleep 10 ;;
        esac
      done
      [ "$STATUS" = "SUCCEEDED" ] || exit 1
Add to your repo as secrets ARCHRAILS_TENANT_ID Your tenant ID. Shown above — click Copy in the tenant panel. ARCHRAILS_TOKEN Signing secret. Click Reveal secret in the panel above — auto-hides after 30s. ARCHRAILS_WEBHOOK_URL The endpoint your CI POSTs to. Same value for every tenant on this environment — click Copy in the URL panel above. ARCHRAILS_PARENT_TOKEN Optional. Leave empty unless your tenant has multiple sub-organizations to bill separately.
3

Verify your setup

Read-only diagnostics — sign in first, then run the check.

·
Signed in
Your account is active and the dashboard authenticates you.
Not run
·
Admin access
You can manage repos and users on your tenant.
Not run
·
Repo connected
At least one repo has run the workflow and registered itself.
Not run
·
First PR review
ArchRails has commented on at least one pull request.
Not run
Open dashboard