Merge pull request #22 from techops-services/fix/restore-deploy-workflow
fix: restore deploy workflow, remove upstream workflows
This commit is contained in:
commit
26a71d11ed
59
.github/workflows/auto-response.yml
vendored
59
.github/workflows/auto-response.yml
vendored
@ -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",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
646
.github/workflows/ci.yml
vendored
646
.github/workflows/ci.yml
vendored
@ -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 }}
|
|
||||||
93
.github/workflows/deploy.yaml
vendored
Normal file
93
.github/workflows/deploy.yaml
vendored
Normal file
@ -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
|
||||||
143
.github/workflows/docker-release.yml
vendored
143
.github/workflows/docker-release.yml
vendored
@ -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 }}
|
|
||||||
41
.github/workflows/install-smoke.yml
vendored
41
.github/workflows/install-smoke.yml
vendored
@ -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
|
|
||||||
23
.github/workflows/labeler.yml
vendored
23
.github/workflows/labeler.yml
vendored
@ -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 }}
|
|
||||||
37
.github/workflows/workflow-sanity.yml
vendored
37
.github/workflows/workflow-sanity.yml
vendored
@ -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
|
|
||||||
Loading…
Reference in New Issue
Block a user