From 209db992ffca0498417b3040ccf0304605279014 Mon Sep 17 00:00:00 2001 From: Simon KP Date: Mon, 26 Jan 2026 19:20:54 +1100 Subject: [PATCH] fix: restore deploy workflow lost during fork sync --- .github/workflows/auto-response.yml | 59 --- .github/workflows/ci.yml | 646 -------------------------- .github/workflows/deploy.yaml | 93 ++++ .github/workflows/docker-release.yml | 143 ------ .github/workflows/install-smoke.yml | 41 -- .github/workflows/labeler.yml | 23 - .github/workflows/workflow-sanity.yml | 37 -- 7 files changed, 93 insertions(+), 949 deletions(-) delete mode 100644 .github/workflows/auto-response.yml delete mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/deploy.yaml delete mode 100644 .github/workflows/docker-release.yml delete mode 100644 .github/workflows/install-smoke.yml delete mode 100644 .github/workflows/labeler.yml delete mode 100644 .github/workflows/workflow-sanity.yml diff --git a/.github/workflows/auto-response.yml b/.github/workflows/auto-response.yml deleted file mode 100644 index 7f242a094..000000000 --- a/.github/workflows/auto-response.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Auto response - -on: - issues: - types: [labeled] - pull_request: - types: [labeled] - -permissions: - issues: write - pull-requests: write - -jobs: - auto-response: - runs-on: ubuntu-latest - steps: - - name: Handle labeled items - uses: actions/github-script@v7 - with: - script: | - const rules = [ - { - label: "skill-clawdhub", - close: true, - message: - "Thanks for the contribution! New skills should be published to Clawdhub for everyone to use. We’re keeping the core lean on skills, so I’m closing this out.", - }, - ]; - - const labelName = context.payload.label?.name; - if (!labelName) { - return; - } - - const rule = rules.find((item) => item.label === labelName); - if (!rule) { - return; - } - - const issueNumber = context.payload.issue?.number ?? context.payload.pull_request?.number; - if (!issueNumber) { - return; - } - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: rule.message, - }); - - if (rule.close) { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - state: "closed", - }); - } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 8cc86bd63..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,646 +0,0 @@ -name: CI - -on: - push: - pull_request: - -jobs: - install-check: - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Checkout submodules (retry) - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 22.x - check-latest: true - - - name: Setup pnpm (corepack retry) - run: | - set -euo pipefail - corepack enable - for attempt in 1 2 3; do - if corepack prepare pnpm@10.23.0 --activate; then - pnpm -v - exit 0 - fi - echo "corepack prepare failed (attempt $attempt/3). Retrying..." - sleep $((attempt * 10)) - done - exit 1 - - - name: Runtime versions - run: | - node -v - npm -v - pnpm -v - - - name: Capture node path - run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV" - - - name: Install dependencies (frozen) - env: - CI: true - run: | - export PATH="$NODE_BIN:$PATH" - which node - node -v - pnpm -v - pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true - - checks: - runs-on: blacksmith-4vcpu-ubuntu-2404 - strategy: - fail-fast: false - matrix: - include: - - runtime: node - task: lint - command: pnpm lint - - runtime: node - task: test - command: pnpm test - - runtime: node - task: build - command: pnpm build - - runtime: node - task: protocol - command: pnpm protocol:check - - runtime: node - task: format - command: pnpm format - - runtime: bun - task: test - command: bunx vitest run - - runtime: bun - task: build - command: bunx tsc -p tsconfig.json - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Checkout submodules (retry) - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 22.x - check-latest: true - - - name: Setup pnpm (corepack retry) - run: | - set -euo pipefail - corepack enable - for attempt in 1 2 3; do - if corepack prepare pnpm@10.23.0 --activate; then - pnpm -v - exit 0 - fi - echo "corepack prepare failed (attempt $attempt/3). Retrying..." - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - - name: Runtime versions - run: | - node -v - npm -v - bun -v - pnpm -v - - - name: Capture node path - run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV" - - - name: Install dependencies - env: - CI: true - run: | - export PATH="$NODE_BIN:$PATH" - which node - node -v - pnpm -v - pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true || pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true - - - name: Run ${{ matrix.task }} (${{ matrix.runtime }}) - run: ${{ matrix.command }} - - secrets: - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - - name: Install detect-secrets - run: | - python -m pip install --upgrade pip - python -m pip install detect-secrets==1.5.0 - - - name: Detect secrets - run: | - if ! detect-secrets scan --baseline .secrets.baseline; then - echo "::error::Secret scanning failed. See docs/gateway/security.md#secret-scanning-detect-secrets" - exit 1 - fi - - checks-windows: - runs-on: blacksmith-4vcpu-windows-2025 - env: - NODE_OPTIONS: --max-old-space-size=4096 - defaults: - run: - shell: bash - strategy: - fail-fast: false - matrix: - include: - - runtime: node - task: lint - command: pnpm lint - - runtime: node - task: test - command: pnpm test - - runtime: node - task: build - command: pnpm build - - runtime: node - task: protocol - command: pnpm protocol:check - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Checkout submodules (retry) - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 22.x - check-latest: true - - - name: Setup pnpm (corepack retry) - run: | - set -euo pipefail - corepack enable - for attempt in 1 2 3; do - if corepack prepare pnpm@10.23.0 --activate; then - pnpm -v - exit 0 - fi - echo "corepack prepare failed (attempt $attempt/3). Retrying..." - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - - name: Runtime versions - run: | - node -v - npm -v - bun -v - pnpm -v - - - name: Capture node path - run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV" - - - name: Install dependencies - env: - CI: true - run: | - export PATH="$NODE_BIN:$PATH" - which node - node -v - pnpm -v - pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true || pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true - - - name: Run ${{ matrix.task }} (${{ matrix.runtime }}) - run: ${{ matrix.command }} - - checks-macos: - if: github.event_name == 'pull_request' - runs-on: macos-latest - strategy: - fail-fast: false - matrix: - include: - - task: test - command: pnpm test - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Checkout submodules (retry) - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 22.x - check-latest: true - - - name: Setup pnpm (corepack retry) - run: | - set -euo pipefail - corepack enable - for attempt in 1 2 3; do - if corepack prepare pnpm@10.23.0 --activate; then - pnpm -v - exit 0 - fi - echo "corepack prepare failed (attempt $attempt/3). Retrying..." - sleep $((attempt * 10)) - done - exit 1 - - - name: Runtime versions - run: | - node -v - npm -v - pnpm -v - - - name: Capture node path - run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV" - - - name: Install dependencies - env: - CI: true - run: | - export PATH="$NODE_BIN:$PATH" - which node - node -v - pnpm -v - pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true || pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true - - - name: Run ${{ matrix.task }} - env: - NODE_OPTIONS: --max-old-space-size=4096 - run: ${{ matrix.command }} - - macos-app: - if: github.event_name == 'pull_request' - runs-on: macos-latest - strategy: - fail-fast: false - matrix: - include: - - task: lint - command: | - swiftlint --config .swiftlint.yml - swiftformat --lint apps/macos/Sources --config .swiftformat - - task: build - command: | - set -euo pipefail - for attempt in 1 2 3; do - if swift build --package-path apps/macos --configuration release; then - exit 0 - fi - echo "swift build failed (attempt $attempt/3). Retrying…" - sleep $((attempt * 20)) - done - exit 1 - - task: test - command: | - set -euo pipefail - for attempt in 1 2 3; do - if swift test --package-path apps/macos --parallel --enable-code-coverage --show-codecov-path; then - exit 0 - fi - echo "swift test failed (attempt $attempt/3). Retrying…" - sleep $((attempt * 20)) - done - exit 1 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Checkout submodules (retry) - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Select Xcode 26.1 - run: | - sudo xcode-select -s /Applications/Xcode_26.1.app - xcodebuild -version - - - name: Install XcodeGen / SwiftLint / SwiftFormat - run: | - brew install xcodegen swiftlint swiftformat - - - name: Show toolchain - run: | - sw_vers - xcodebuild -version - swift --version - - - name: Run ${{ matrix.task }} - run: ${{ matrix.command }} - ios: - if: false # ignore iOS in CI for now - runs-on: macos-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Checkout submodules (retry) - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Select Xcode 26.1 - run: | - sudo xcode-select -s /Applications/Xcode_26.1.app - xcodebuild -version - - - name: Install XcodeGen - run: brew install xcodegen - - - name: Install SwiftLint / SwiftFormat - run: brew install swiftlint swiftformat - - - name: Show toolchain - run: | - sw_vers - xcodebuild -version - swift --version - - - name: Generate iOS project - run: | - cd apps/ios - xcodegen generate - - - name: iOS tests - run: | - set -euo pipefail - RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult" - DEST_ID="$( - python3 - <<'PY' - import json - import subprocess - import sys - import uuid - - def sh(args: list[str]) -> str: - return subprocess.check_output(args, text=True).strip() - - # Prefer an already-created iPhone simulator if it exists. - devices = json.loads(sh(["xcrun", "simctl", "list", "devices", "-j"])) - candidates: list[tuple[str, str]] = [] - for runtime, devs in (devices.get("devices") or {}).items(): - for dev in devs or []: - if not dev.get("isAvailable"): - continue - name = str(dev.get("name") or "") - udid = str(dev.get("udid") or "") - if not udid or not name.startswith("iPhone"): - continue - candidates.append((name, udid)) - - candidates.sort(key=lambda it: (0 if "iPhone 16" in it[0] else 1, it[0])) - if candidates: - print(candidates[0][1]) - sys.exit(0) - - # Otherwise, create one from the newest available iOS runtime. - runtimes = json.loads(sh(["xcrun", "simctl", "list", "runtimes", "-j"])).get("runtimes") or [] - ios = [rt for rt in runtimes if rt.get("platform") == "iOS" and rt.get("isAvailable")] - if not ios: - print("No available iOS runtimes found.", file=sys.stderr) - sys.exit(1) - - def version_key(rt: dict) -> tuple[int, ...]: - parts: list[int] = [] - for p in str(rt.get("version") or "0").split("."): - try: - parts.append(int(p)) - except ValueError: - parts.append(0) - return tuple(parts) - - ios.sort(key=version_key, reverse=True) - runtime = ios[0] - runtime_id = str(runtime.get("identifier") or "") - if not runtime_id: - print("Missing iOS runtime identifier.", file=sys.stderr) - sys.exit(1) - - supported = runtime.get("supportedDeviceTypes") or [] - iphones = [dt for dt in supported if dt.get("productFamily") == "iPhone"] - if not iphones: - print("No iPhone device types for iOS runtime.", file=sys.stderr) - sys.exit(1) - - iphones.sort( - key=lambda dt: ( - 0 if "iPhone 16" in str(dt.get("name") or "") else 1, - str(dt.get("name") or ""), - ) - ) - device_type_id = str(iphones[0].get("identifier") or "") - if not device_type_id: - print("Missing iPhone device type identifier.", file=sys.stderr) - sys.exit(1) - - sim_name = f"CI iPhone {uuid.uuid4().hex[:8]}" - udid = sh(["xcrun", "simctl", "create", sim_name, device_type_id, runtime_id]) - if not udid: - print("Failed to create iPhone simulator.", file=sys.stderr) - sys.exit(1) - print(udid) - PY - )" - echo "Using iOS Simulator id: $DEST_ID" - xcodebuild test \ - -project apps/ios/Clawdis.xcodeproj \ - -scheme Clawdis \ - -destination "platform=iOS Simulator,id=$DEST_ID" \ - -resultBundlePath "$RESULT_BUNDLE_PATH" \ - -enableCodeCoverage YES - - - name: iOS coverage summary - run: | - set -euo pipefail - RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult" - xcrun xccov view --report --only-targets "$RESULT_BUNDLE_PATH" - - - name: iOS coverage gate (43%) - run: | - set -euo pipefail - RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult" - RESULT_BUNDLE_PATH="$RESULT_BUNDLE_PATH" python3 - <<'PY' - import json - import os - import subprocess - import sys - - target_name = "Clawdis.app" - minimum = 0.43 - - report = json.loads( - subprocess.check_output( - ["xcrun", "xccov", "view", "--report", "--json", os.environ["RESULT_BUNDLE_PATH"]], - text=True, - ) - ) - - target_coverage = None - for target in report.get("targets", []): - if target.get("name") == target_name: - target_coverage = float(target["lineCoverage"]) - break - - if target_coverage is None: - print(f"Could not find coverage for target: {target_name}") - sys.exit(1) - - print(f"{target_name} line coverage: {target_coverage * 100:.2f}% (min {minimum * 100:.2f}%)") - if target_coverage + 1e-12 < minimum: - sys.exit(1) - PY - - android: - runs-on: blacksmith-4vcpu-ubuntu-2404 - strategy: - fail-fast: false - matrix: - include: - - task: test - command: ./gradlew --no-daemon :app:testDebugUnitTest - - task: build - command: ./gradlew --no-daemon :app:assembleDebug - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: false - - - name: Checkout submodules (retry) - run: | - set -euo pipefail - git submodule sync --recursive - for attempt in 1 2 3 4 5; do - if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then - exit 0 - fi - echo "Submodule update failed (attempt $attempt/5). Retrying…" - sleep $((attempt * 10)) - done - exit 1 - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 21 - - - name: Setup Android SDK - uses: android-actions/setup-android@v3 - with: - accept-android-sdk-licenses: false - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - gradle-version: 8.11.1 - - - name: Install Android SDK packages - run: | - yes | sdkmanager --licenses >/dev/null - sdkmanager --install \ - "platform-tools" \ - "platforms;android-36" \ - "build-tools;36.0.0" - - - name: Run Android ${{ matrix.task }} - working-directory: apps/android - run: ${{ matrix.command }} diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 000000000..5f407f4bc --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,93 @@ +on: + push: + branches: + - main + workflow_dispatch: + +name: deploy-clawdbot + +permissions: + id-token: write + contents: read + +jobs: + build-and-deploy: + environment: prod + runs-on: ubuntu-latest + env: + HELM_FILE: deploy/prod/values.yaml + REGION: us-east-1 + CLUSTER_NAME: maker-prod + NAMESPACE: clawdbot + SERVICE_NAME: clawdbot + AWS_ECR_NAME: clawdbot + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-oidc-eks-prod + aws-region: ${{ env.REGION }} + + - name: Login to AWS ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + + - name: Set up Docker Buildx + if: ${{ !contains(github.event.head_commit.message, '[skip build]') }} + uses: docker/setup-buildx-action@v3 + + - name: Extract commit hash + id: vars + if: ${{ !contains(github.event.head_commit.message, '[skip build]') }} + shell: bash + run: | + echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Build, tag, and push image to ECR + id: build-image + if: ${{ !contains(github.event.head_commit.message, '[skip build]') }} + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile.prod + push: true + tags: | + ${{ steps.login-ecr.outputs.registry }}/${{ env.AWS_ECR_NAME }}:${{ steps.vars.outputs.sha_short }} + ${{ steps.login-ecr.outputs.registry }}/${{ env.AWS_ECR_NAME }}:latest + ${{ steps.login-ecr.outputs.registry }}/${{ env.AWS_ECR_NAME }}:prod + cache-from: type=registry,ref=${{ steps.login-ecr.outputs.registry }}/${{ env.AWS_ECR_NAME }}:cache + cache-to: type=registry,ref=${{ steps.login-ecr.outputs.registry }}/${{ env.AWS_ECR_NAME }}:cache,mode=max + + - name: Replace variables in the Helm values file + if: ${{ !contains(github.event.head_commit.message, '[skip deploy]') }} + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + IMAGE_TAG: ${{ steps.vars.outputs.sha_short }} + run: | + sed -i 's|${ECR_REGISTRY}|'"$ECR_REGISTRY"'|g' $HELM_FILE + sed -i 's|${IMAGE_TAG}|'"$IMAGE_TAG"'|g' $HELM_FILE + + - name: Configure kubectl + if: ${{ !contains(github.event.head_commit.message, '[skip deploy]') }} + run: | + aws eks update-kubeconfig --name ${{ env.CLUSTER_NAME }} --region ${{ env.REGION }} + + - name: Deploy to Kubernetes with Helm + if: ${{ !contains(github.event.head_commit.message, '[skip deploy]') }} + uses: bitovi/github-actions-deploy-eks-helm@v1.2.10 + with: + cluster-name: ${{ env.CLUSTER_NAME }} + config-files: ${{ env.HELM_FILE }} + chart-path: techops-services/common + namespace: ${{ env.NAMESPACE }} + timeout: 5m0s + name: ${{ env.SERVICE_NAME }} + chart-repository: https://techops-services.github.io/helm-charts + version: 0.2.1 + atomic: true diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml deleted file mode 100644 index aa175961d..000000000 --- a/.github/workflows/docker-release.yml +++ /dev/null @@ -1,143 +0,0 @@ -name: Docker Release - -on: - push: - branches: - - main - tags: - - "v*" - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - # Build amd64 image - build-amd64: - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - outputs: - image-digest: ${{ steps.build.outputs.digest }} - image-metadata: ${{ steps.meta.outputs.json }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - type=semver,pattern={{version}},suffix=-amd64 - type=semver,pattern={{version}},suffix=-arm64 - type=ref,event=branch,suffix=-amd64 - type=ref,event=branch,suffix=-arm64 - - - name: Build and push amd64 image - id: build - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/amd64 - labels: ${{ steps.meta.outputs.labels }} - tags: ${{ steps.meta.outputs.tags }} - cache-from: type=gha - cache-to: type=gha,mode=max - provenance: false - push: true - - # Build arm64 image - build-arm64: - runs-on: ubuntu-24.04-arm - permissions: - packages: write - contents: read - outputs: - image-digest: ${{ steps.build.outputs.digest }} - image-metadata: ${{ steps.meta.outputs.json }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - type=semver,pattern={{version}},suffix=-amd64 - type=semver,pattern={{version}},suffix=-arm64 - type=ref,event=branch,suffix=-amd64 - type=ref,event=branch,suffix=-arm64 - - - name: Build and push arm64 image - id: build - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/arm64 - labels: ${{ steps.meta.outputs.labels }} - tags: ${{ steps.meta.outputs.tags }} - cache-from: type=gha - cache-to: type=gha,mode=max - provenance: false - push: true - - # Create multi-platform manifest - create-manifest: - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - needs: [build-amd64, build-arm64] - steps: - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata for manifest - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - - - name: Create and push manifest - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - ${{ needs.build-amd64.outputs.image-digest }} \ - ${{ needs.build-arm64.outputs.image-digest }} - env: - DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }} diff --git a/.github/workflows/install-smoke.yml b/.github/workflows/install-smoke.yml deleted file mode 100644 index 16eba4eed..000000000 --- a/.github/workflows/install-smoke.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Install Smoke - -on: - push: - branches: [main] - pull_request: - workflow_dispatch: - -jobs: - install-smoke: - runs-on: ubuntu-latest - steps: - - name: Checkout CLI - uses: actions/checkout@v4 - - - name: Setup pnpm (corepack retry) - run: | - set -euo pipefail - corepack enable - for attempt in 1 2 3; do - if corepack prepare pnpm@10.23.0 --activate; then - pnpm -v - exit 0 - fi - echo "corepack prepare failed (attempt $attempt/3). Retrying..." - sleep $((attempt * 10)) - done - exit 1 - - - name: Install pnpm deps (minimal) - run: pnpm install --ignore-scripts --frozen-lockfile - - - name: Run installer docker tests - env: - CLAWDBOT_INSTALL_URL: https://clawd.bot/install.sh - CLAWDBOT_INSTALL_CLI_URL: https://clawd.bot/install-cli.sh - CLAWDBOT_NO_ONBOARD: "1" - CLAWDBOT_INSTALL_SMOKE_SKIP_CLI: "1" - CLAWDBOT_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }} - CLAWDBOT_INSTALL_SMOKE_PREVIOUS: "2026.1.11-4" - run: pnpm test:install:smoke diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml deleted file mode 100644 index 8d078774b..000000000 --- a/.github/workflows/labeler.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Labeler - -on: - pull_request_target: - types: [opened, synchronize, reopened] - -permissions: - contents: read - pull-requests: write - -jobs: - label: - runs-on: ubuntu-latest - steps: - - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: "2729701" - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - uses: actions/labeler@v5 - with: - configuration-path: .github/labeler.yml - repo-token: ${{ steps.app-token.outputs.token }} diff --git a/.github/workflows/workflow-sanity.yml b/.github/workflows/workflow-sanity.yml deleted file mode 100644 index b8ce0879a..000000000 --- a/.github/workflows/workflow-sanity.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Workflow Sanity - -on: - pull_request: - push: - -jobs: - no-tabs: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Fail on tabs in workflow files - run: | - python - <<'PY' - from __future__ import annotations - - import pathlib - import sys - - root = pathlib.Path(".github/workflows") - bad: list[str] = [] - for path in sorted(root.rglob("*.yml")): - if b"\t" in path.read_bytes(): - bad.append(str(path)) - - for path in sorted(root.rglob("*.yaml")): - if b"\t" in path.read_bytes(): - bad.append(str(path)) - - if bad: - print("Tabs found in workflow file(s):") - for path in bad: - print(f"- {path}") - sys.exit(1) - PY