mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 08:52:21 +00:00
1347 lines
58 KiB
YAML
1347 lines
58 KiB
YAML
name: Deploy Test
|
|
|
|
on:
|
|
workflow_run:
|
|
workflows: ["CI"]
|
|
types: [completed]
|
|
branches: [main]
|
|
pull_request:
|
|
types: [synchronize, labeled]
|
|
workflow_dispatch:
|
|
inputs:
|
|
expected_sha:
|
|
description: Exact branch SHA permitted for a temporary protected Test deploy
|
|
required: false
|
|
type: string
|
|
branch_test_confirm:
|
|
description: Confirmation phrase for an explicitly guarded branch-only Test deploy
|
|
required: false
|
|
type: string
|
|
|
|
concurrency:
|
|
group: deploy-test
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
deploy-test:
|
|
if: >-
|
|
(github.event_name == 'workflow_dispatch' &&
|
|
(github.ref == 'refs/heads/main' ||
|
|
((github.ref == 'refs/heads/pe/claw-563-skills-sh-mirror-10k' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-563-to-permanent-test') ||
|
|
(github.ref == 'refs/heads/pe/claw-589-trending-rank-overlay' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-589-to-permanent-test') ||
|
|
(github.ref == 'refs/heads/pe/claw-577-canonical-mixed-search' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-577-to-permanent-test') ||
|
|
(github.ref == 'refs/heads/pe/claw-583-mirrored-search-journey' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-583-to-permanent-test') ||
|
|
(github.ref == 'refs/heads/pe/claw-560-verified-adoption' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-560-to-permanent-test') ||
|
|
(github.ref == 'refs/heads/pe/claw-590-trending-snapshot' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-590-to-permanent-test')) &&
|
|
github.actor == 'Patrick-Erichsen' &&
|
|
inputs.expected_sha != '')) ||
|
|
(github.event_name == 'pull_request' &&
|
|
((github.event.pull_request.head.ref == 'pe/claw-563-skills-sh-mirror-10k' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-mirror-load')) ||
|
|
(github.event.pull_request.head.ref == 'pe/claw-589-trending-rank-overlay' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-trending-load')) ||
|
|
(github.event.pull_request.head.ref == 'pe/claw-577-canonical-mixed-search' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-search-load')) ||
|
|
(github.event.pull_request.head.ref == 'pe/claw-583-mirrored-search-journey' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-external-catalog'))) &&
|
|
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
github.actor == 'Patrick-Erichsen' &&
|
|
github.event.pull_request.head.sha != '') ||
|
|
(github.event.workflow_run.conclusion == 'success' &&
|
|
github.event.workflow_run.event == 'push')
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
environment:
|
|
name: Test
|
|
url: ${{ vars.SITE_URL }}
|
|
outputs:
|
|
deployment_url: ${{ steps.vercel.outputs.deployment_url }}
|
|
deploy_sha: ${{ steps.revision.outputs.deploy_sha }}
|
|
fixture_version: ${{ steps.revision.outputs.fixture_version }}
|
|
branch_test: ${{ steps.revision.outputs.branch_test }}
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
ref: >-
|
|
${{
|
|
github.event_name == 'workflow_run' && github.event.workflow_run.head_sha ||
|
|
github.event_name == 'pull_request' && github.event.pull_request.head.sha ||
|
|
github.ref
|
|
}}
|
|
|
|
- name: Resolve deployment revision
|
|
id: revision
|
|
run: |
|
|
set -euo pipefail
|
|
deploy_sha="$(git rev-parse HEAD)"
|
|
git fetch --no-tags origin main
|
|
main_sha="$(git rev-parse origin/main)"
|
|
if [[ "$deploy_sha" != "$main_sha" ]]; then
|
|
branch_test_allowed=false
|
|
if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]] &&
|
|
[[ "$GITHUB_REF" == refs/heads/pe/claw-563-skills-sh-mirror-10k ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ inputs.branch_test_confirm }}" == deploy-claw-563-to-permanent-test ]] &&
|
|
[[ "${{ inputs.expected_sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]] &&
|
|
[[ "$GITHUB_REF" == refs/heads/pe/claw-589-trending-rank-overlay ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ inputs.branch_test_confirm }}" == deploy-claw-589-to-permanent-test ]] &&
|
|
[[ "${{ inputs.expected_sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]] &&
|
|
[[ "$GITHUB_REF" == refs/heads/pe/claw-577-canonical-mixed-search ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ inputs.branch_test_confirm }}" == deploy-claw-577-to-permanent-test ]] &&
|
|
[[ "${{ inputs.expected_sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]] &&
|
|
[[ "$GITHUB_REF" == refs/heads/pe/claw-583-mirrored-search-journey ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ inputs.branch_test_confirm }}" == deploy-claw-583-to-permanent-test ]] &&
|
|
[[ "${{ inputs.expected_sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]] &&
|
|
[[ "$GITHUB_REF" == refs/heads/pe/claw-560-verified-adoption ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ inputs.branch_test_confirm }}" == deploy-claw-560-to-permanent-test ]] &&
|
|
[[ "${{ inputs.expected_sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]] &&
|
|
[[ "$GITHUB_REF" == refs/heads/pe/claw-590-trending-snapshot ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ inputs.branch_test_confirm }}" == deploy-claw-590-to-permanent-test ]] &&
|
|
[[ "${{ inputs.expected_sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == pull_request ]] &&
|
|
[[ "$GITHUB_HEAD_REF" == pe/claw-563-skills-sh-mirror-10k ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ github.event.pull_request.head.repo.full_name }}" == "$GITHUB_REPOSITORY" ]] &&
|
|
[[ "${{ github.event.pull_request.head.sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == pull_request ]] &&
|
|
[[ "$GITHUB_HEAD_REF" == pe/claw-589-trending-rank-overlay ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ github.event.pull_request.head.repo.full_name }}" == "$GITHUB_REPOSITORY" ]] &&
|
|
[[ "${{ github.event.pull_request.head.sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == pull_request ]] &&
|
|
[[ "$GITHUB_HEAD_REF" == pe/claw-577-canonical-mixed-search ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ github.event.pull_request.head.repo.full_name }}" == "$GITHUB_REPOSITORY" ]] &&
|
|
[[ "${{ github.event.pull_request.head.sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$GITHUB_EVENT_NAME" == pull_request ]] &&
|
|
[[ "$GITHUB_HEAD_REF" == pe/claw-583-mirrored-search-journey ]] &&
|
|
[[ "$GITHUB_ACTOR" == Patrick-Erichsen ]] &&
|
|
[[ "${{ github.event.pull_request.head.repo.full_name }}" == "$GITHUB_REPOSITORY" ]] &&
|
|
[[ "${{ github.event.pull_request.head.sha }}" == "$deploy_sha" ]]
|
|
then
|
|
branch_test_allowed=true
|
|
fi
|
|
if [[ "$branch_test_allowed" != true ]]; then
|
|
echo "::error::Refusing non-main Test deploy without an exact approved branch guard"
|
|
exit 1
|
|
fi
|
|
echo "branch_test=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "branch_test=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
fixture_version="$(
|
|
git hash-object convex/devSeed.ts convex/lib/testSeed.ts |
|
|
sha256sum |
|
|
cut -c1-12
|
|
)"
|
|
echo "deploy_sha=$deploy_sha" >> "$GITHUB_OUTPUT"
|
|
echo "fixture_version=$fixture_version" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Check Test configuration
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
VERCEL_ORG_ID: ${{ vars.VERCEL_ORG_ID }}
|
|
VERCEL_PROJECT_ID: ${{ vars.VERCEL_PROJECT_ID }}
|
|
VERCEL_SCOPE: ${{ vars.VERCEL_SCOPE }}
|
|
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VITE_CONVEX_SITE_URL: ${{ vars.VITE_CONVEX_SITE_URL }}
|
|
VITE_CONVEX_URL: ${{ vars.VITE_CONVEX_URL }}
|
|
run: |
|
|
set -euo pipefail
|
|
missing=()
|
|
for name in \
|
|
CONVEX_DEPLOY_KEY \
|
|
VERCEL_AUTOMATION_BYPASS_SECRET \
|
|
VERCEL_ORG_ID \
|
|
VERCEL_PROJECT_ID \
|
|
VERCEL_SCOPE \
|
|
VERCEL_TOKEN \
|
|
TEST_SITE_URL \
|
|
VITE_CONVEX_SITE_URL \
|
|
VITE_CONVEX_URL
|
|
do
|
|
if [[ -z "${!name}" ]]; then
|
|
missing+=("$name")
|
|
fi
|
|
done
|
|
if (( ${#missing[@]} > 0 )); then
|
|
echo "::error::Missing Test environment configuration: ${missing[*]}"
|
|
exit 1
|
|
fi
|
|
if [[ "$CONVEX_DEPLOY_KEY" != prod:academic-chihuahua-392\|* ]]; then
|
|
echo "::error::CONVEX_DEPLOY_KEY must target academic-chihuahua-392"
|
|
exit 1
|
|
fi
|
|
|
|
- uses: ./.github/actions/setup-bun
|
|
|
|
- name: Enable Test rollout modes
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
run: |
|
|
set -euo pipefail
|
|
bunx convex env set CLAWHUB_SKILLS_SH_ROLLOUT_MODE test --prod
|
|
bunx convex env set CLAWHUB_GITHUB_SKILL_SYNC_ROLLOUT_MODE test --prod
|
|
|
|
- name: Stamp Convex build SHA
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
run: bunx convex env set APP_BUILD_SHA "${{ steps.revision.outputs.deploy_sha }}" --prod
|
|
|
|
- name: Stamp Convex deploy time
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
run: bunx convex env set APP_DEPLOYED_AT "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" --prod
|
|
|
|
- name: Deploy Convex Test
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
run: bun run convex:deploy
|
|
|
|
- name: Verify Convex contract
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
run: bun run verify:convex-contract -- --prod
|
|
|
|
- name: Verify Test rollout capabilities
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
run: |
|
|
set -euo pipefail
|
|
capabilities="$(bunx convex run rolloutCapabilities:getPublicCapabilities --prod)"
|
|
jq -e '
|
|
.environment == "test" and
|
|
.skillsSh.mode == "test" and
|
|
.skillsSh.runtimeEnabled == true and
|
|
.githubSkillSync.mode == "test" and
|
|
.githubSkillSync.selfServiceEnabled == true
|
|
' <<< "$capabilities"
|
|
|
|
- name: Apply additive Test fixtures
|
|
if: steps.revision.outputs.branch_test != 'true'
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
CONVEX_DEPLOYMENT: ${{ vars.CONVEX_DEPLOYMENT }}
|
|
run: bun run seed:test
|
|
|
|
- name: Deploy unpromoted Vercel Test candidate
|
|
id: vercel
|
|
env:
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VERCEL_ORG_ID: ${{ vars.VERCEL_ORG_ID }}
|
|
VERCEL_PROJECT_ID: ${{ vars.VERCEL_PROJECT_ID }}
|
|
VERCEL_SCOPE: ${{ vars.VERCEL_SCOPE }}
|
|
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
VITE_CONVEX_SITE_URL: ${{ vars.VITE_CONVEX_SITE_URL }}
|
|
VITE_CONVEX_URL: ${{ vars.VITE_CONVEX_URL }}
|
|
run: |
|
|
set -euo pipefail
|
|
deployment_json="$(
|
|
bunx --bun vercel@50.44.0 deploy \
|
|
--target=preview \
|
|
--yes \
|
|
--scope "$VERCEL_SCOPE" \
|
|
--token "$VERCEL_TOKEN" \
|
|
--meta githubSha="${{ steps.revision.outputs.deploy_sha }}" \
|
|
--meta clawhubEnvironment=test \
|
|
--build-env CONVEX_DEPLOY_KEY= \
|
|
--build-env VERCEL_TARGET_ENV=test \
|
|
--build-env CLAWHUB_ENV=test \
|
|
--build-env CLAWHUB_SKILLS_SH_ROLLOUT_MODE=test \
|
|
--build-env CLAWHUB_GITHUB_SKILL_SYNC_ROLLOUT_MODE=test \
|
|
--build-env CLAWHUB_SKILLS_SH_TEST_LIVE_FETCH_ENABLED=1 \
|
|
--build-env SITE_URL="$TEST_SITE_URL" \
|
|
--build-env VITE_CLAWHUB_DEPLOY_ENV=test \
|
|
--build-env VITE_CONVEX_URL="$VITE_CONVEX_URL" \
|
|
--build-env VITE_CONVEX_SITE_URL="$VITE_CONVEX_SITE_URL" \
|
|
--build-env VITE_SITE_URL="$TEST_SITE_URL" \
|
|
--env CONVEX_DEPLOY_KEY= \
|
|
--env VERCEL_TARGET_ENV=test \
|
|
--env CLAWHUB_ENV=test \
|
|
--env CLAWHUB_SKILLS_SH_ROLLOUT_MODE=test \
|
|
--env CLAWHUB_GITHUB_SKILL_SYNC_ROLLOUT_MODE=test \
|
|
--env CLAWHUB_SKILLS_SH_TEST_LIVE_FETCH_ENABLED=1 \
|
|
--env SITE_URL="$TEST_SITE_URL" \
|
|
--env VITE_CLAWHUB_DEPLOY_ENV=test \
|
|
--env VITE_CONVEX_URL="$VITE_CONVEX_URL" \
|
|
--env VITE_CONVEX_SITE_URL="$VITE_CONVEX_SITE_URL" \
|
|
--env VITE_SITE_URL="$TEST_SITE_URL" \
|
|
--format=json
|
|
)"
|
|
deployment_url="$(jq -r '.url // .deployment.url // empty' <<< "$deployment_json")"
|
|
if [[ -z "$deployment_url" ]]; then
|
|
echo "::error::Vercel did not return a candidate deployment URL"
|
|
exit 1
|
|
fi
|
|
if [[ "$deployment_url" != http* ]]; then
|
|
deployment_url="https://$deployment_url"
|
|
fi
|
|
echo "deployment_url=$deployment_url" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Install Playwright browser
|
|
run: bunx playwright install --with-deps chromium
|
|
|
|
- name: Smoke Test candidate HTTP
|
|
env:
|
|
CLAWHUB_E2E_CANONICAL_SITE: ${{ vars.SITE_URL }}
|
|
CLAWHUB_E2E_EXPECT_TEST_BACKEND: academic-chihuahua-392
|
|
CLAWHUB_E2E_SITE: ${{ steps.vercel.outputs.deployment_url }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: bun run test:e2e:prod-http
|
|
|
|
- name: Smoke Test candidate UI
|
|
env:
|
|
PLAYWRIGHT_BASE_URL: ${{ steps.vercel.outputs.deployment_url }}
|
|
PLAYWRIGHT_WORKERS: "1"
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: bunx playwright test --project=chromium e2e/ci-smoke.pw.test.ts
|
|
|
|
- name: Assign stable Test alias
|
|
env:
|
|
DEPLOYMENT_URL: ${{ steps.vercel.outputs.deployment_url }}
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VERCEL_ORG_ID: ${{ vars.VERCEL_ORG_ID }}
|
|
VERCEL_PROJECT_ID: ${{ vars.VERCEL_PROJECT_ID }}
|
|
VERCEL_SCOPE: ${{ vars.VERCEL_SCOPE }}
|
|
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
alias="${TEST_SITE_URL#https://}"
|
|
bunx --bun vercel@50.44.0 alias set \
|
|
"$DEPLOYMENT_URL" \
|
|
"$alias" \
|
|
--scope "$VERCEL_SCOPE" \
|
|
--token "$VERCEL_TOKEN"
|
|
|
|
- name: Verify stable Test URL
|
|
env:
|
|
CLAWHUB_E2E_CANONICAL_SITE: ${{ vars.SITE_URL }}
|
|
CLAWHUB_E2E_EXPECT_TEST_BACKEND: academic-chihuahua-392
|
|
CLAWHUB_E2E_SITE: ${{ vars.SITE_URL }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: bun run test:e2e:prod-http
|
|
|
|
- name: Write deployment summary
|
|
if: always()
|
|
env:
|
|
CANDIDATE_URL: ${{ steps.vercel.outputs.deployment_url }}
|
|
DEPLOY_SHA: ${{ steps.revision.outputs.deploy_sha }}
|
|
FIXTURE_VERSION: ${{ steps.revision.outputs.fixture_version }}
|
|
STABLE_URL: ${{ vars.SITE_URL }}
|
|
run: |
|
|
{
|
|
echo "## ClawHub Test deployment"
|
|
echo
|
|
echo "- Git SHA: \`${DEPLOY_SHA:-unresolved}\`"
|
|
echo "- Convex deployment: \`academic-chihuahua-392\`"
|
|
echo "- Vercel candidate: ${CANDIDATE_URL:-not created}"
|
|
echo "- Stable Test URL: ${STABLE_URL:-not configured}"
|
|
echo "- Fixture version: \`${FIXTURE_VERSION:-unresolved}\`"
|
|
echo "- Result: \`${{ job.status }}\`"
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
claw563-mirror-load:
|
|
needs: deploy-test
|
|
if: >-
|
|
github.event_name == 'pull_request' &&
|
|
github.event.pull_request.head.ref == 'pe/claw-563-skills-sh-mirror-10k' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-mirror-load')
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 180
|
|
environment:
|
|
name: Test
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
|
|
- uses: ./.github/actions/setup-bun
|
|
|
|
- name: Load and prove the authenticated leaderboard mirror foundation
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
DEPLOY_SHA: ${{ needs.deploy-test.outputs.deploy_sha }}
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: |
|
|
set -euo pipefail
|
|
operator_token=""
|
|
cleanup() {
|
|
set +e
|
|
bunx convex run --no-push skillsShMirror:configureInternal \
|
|
'{
|
|
"actor":"CLAW-563 Test workflow",
|
|
"reason":"CLAW-563 proof cleanup",
|
|
"confirm":"enable-skills-sh-mirror-test",
|
|
"enabled":false,
|
|
"maxRowsPerRun":50000,
|
|
"maxRowsPerBatch":50,
|
|
"maxDetailBytes":65536
|
|
}' > claw563-control-disabled.json 2>&1
|
|
disable_exit=$?
|
|
bunx convex run --no-push devSeed:seedCliRoleHelpFixtures '{}' >/dev/null
|
|
token_rotation_exit=$?
|
|
if [[ -n "$operator_token" ]]; then
|
|
revoked_status="$(
|
|
curl \
|
|
--silent \
|
|
--output /dev/null \
|
|
--write-out '%{http_code}' \
|
|
--header "Authorization: Bearer $operator_token" \
|
|
https://academic-chihuahua-392.convex.site/api/v1/operator/skills-sh/catalog-test
|
|
)"
|
|
else
|
|
revoked_status="not-created"
|
|
fi
|
|
jq -n \
|
|
--argjson disableExit "$disable_exit" \
|
|
--argjson tokenRotationExit "$token_rotation_exit" \
|
|
--arg revokedStatus "$revoked_status" \
|
|
'{
|
|
disableExit:$disableExit,
|
|
tokenRotationExit:$tokenRotationExit,
|
|
revokedStatus:$revokedStatus
|
|
}' > claw563-cleanup.json
|
|
set -e
|
|
[[
|
|
"$disable_exit" -eq 0 &&
|
|
"$token_rotation_exit" -eq 0 &&
|
|
"$revoked_status" == "401"
|
|
]]
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
deployment_json="$(bunx convex run --no-push appMeta:getDeploymentInfo)"
|
|
build_sha="$(jq -r '.appBuildSha // empty' <<<"$deployment_json")"
|
|
if [[ "$build_sha" != "$DEPLOY_SHA" ]]; then
|
|
echo "::error::Unexpected Convex Test build SHA: $build_sha"
|
|
exit 1
|
|
fi
|
|
|
|
token_seed="$(bunx convex run --no-push devSeed:seedCliRoleHelpFixtures '{}')"
|
|
operator_token="$(jq -r '.admin.token // empty' <<<"$token_seed")"
|
|
token_seed=""
|
|
if [[ -z "$operator_token" ]]; then
|
|
echo "::error::Test admin fixture token is missing"
|
|
exit 1
|
|
fi
|
|
echo "::add-mask::$operator_token"
|
|
|
|
export CLAWHUB_TEST_MIRROR_GATE_URL="$TEST_SITE_URL/ops/skills-sh/mirror-test"
|
|
export CLAWHUB_TEST_OPERATOR_TOKEN="$operator_token"
|
|
bun run skills-sh:prove-mirror > claw563-proof-output.json
|
|
|
|
curl \
|
|
--fail-with-body \
|
|
--silent \
|
|
--show-error \
|
|
--request POST \
|
|
--header "Authorization: Bearer $operator_token" \
|
|
--header "Content-Type: application/json" \
|
|
--header "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" \
|
|
--data '{"operation":"read","externalId":"patrick-erichsen/skills/html"}' \
|
|
"$CLAWHUB_TEST_MIRROR_GATE_URL" > claw563-controlled-entry.json
|
|
jq -e '
|
|
.digest.externalId == "patrick-erichsen/skills/html" and
|
|
.digest.sourceType == "github" and
|
|
.digest.owner == "patrick-erichsen" and
|
|
.digest.repo == "skills" and
|
|
.digest.githubPath == "skills/html" and
|
|
.digest.githubCommit == "050daba89f6b6636470add5cb300aac46a412cf8" and
|
|
.digest.sourceContentHash == "a47adb2c1ac33c088f664b5187971b63d2b958a7b9f01516d26005ca941a108f" and
|
|
.digest.active == true and
|
|
.digest.publicVisible == false and
|
|
.digest.installable == false
|
|
' claw563-controlled-entry.json >/dev/null
|
|
|
|
curl \
|
|
--fail-with-body \
|
|
--silent \
|
|
--show-error \
|
|
--request POST \
|
|
--header "Authorization: Bearer $operator_token" \
|
|
--header "Content-Type: application/json" \
|
|
--header "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" \
|
|
--data '{"operation":"read","externalId":"steipete/clawdis/discrawl"}' \
|
|
"$CLAWHUB_TEST_MIRROR_GATE_URL" > claw563-discrawl-entry.json
|
|
jq -e '
|
|
.digest.externalId == "steipete/clawdis/discrawl" and
|
|
.digest.sourceType == "github" and
|
|
.digest.owner == "steipete" and
|
|
.digest.repo == "clawdis" and
|
|
.digest.githubPath == ".agents/skills/discrawl" and
|
|
.digest.githubCommit == "690ed564419291ca6e832dc69b53061300075b62" and
|
|
.digest.sourceContentHash == "4d3c90262b309ee9ee0ef2f83397fc2a68e8c7d098a8a960fdcbf8908f077f10" and
|
|
.digest.active == true and
|
|
.digest.publicVisible == false and
|
|
.digest.installable == false
|
|
' claw563-discrawl-entry.json >/dev/null
|
|
|
|
jq -n \
|
|
--arg sourceSha "$DEPLOY_SHA" \
|
|
--arg deploymentUrl "$TEST_SITE_URL" \
|
|
'{
|
|
sourceSha:$sourceSha,
|
|
deploymentUrl:$deploymentUrl,
|
|
convexDeployment:"academic-chihuahua-392"
|
|
}' > claw563-deployment.json
|
|
|
|
cleanup
|
|
trap - EXIT
|
|
jq -e '
|
|
.disableExit == 0 and
|
|
.tokenRotationExit == 0 and
|
|
.revokedStatus == "401"
|
|
' claw563-cleanup.json >/dev/null
|
|
|
|
- name: Upload permanent Test mirror proof
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: claw563-mirror-proof
|
|
if-no-files-found: warn
|
|
path: |
|
|
proof/claw-563/skills-sh-mirror-test-proof.json
|
|
claw563-proof-output.json
|
|
claw563-controlled-entry.json
|
|
claw563-discrawl-entry.json
|
|
claw563-control-disabled.json
|
|
claw563-cleanup.json
|
|
claw563-deployment.json
|
|
|
|
claw589-trending-load:
|
|
needs: deploy-test
|
|
if: >-
|
|
github.event_name == 'pull_request' &&
|
|
github.event.pull_request.head.ref == 'pe/claw-589-trending-rank-overlay' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-trending-load')
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 180
|
|
environment:
|
|
name: Test
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
|
|
- uses: ./.github/actions/setup-bun
|
|
|
|
- name: Observe and prove the authenticated skills.sh Trending overlay
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
DEPLOY_SHA: ${{ needs.deploy-test.outputs.deploy_sha }}
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: |
|
|
set -euo pipefail
|
|
operator_token=""
|
|
export CLAWHUB_TEST_MIRROR_GATE_URL="$TEST_SITE_URL/ops/skills-sh/mirror-test"
|
|
cleanup() {
|
|
set +e
|
|
owned_run="$(jq -r '.runId // empty' proof/claw-589/active-run.json 2>/dev/null)"
|
|
active_run=""
|
|
discard_exit=0
|
|
if [[ -n "$operator_token" && -n "$owned_run" ]]; then
|
|
active_run="$(
|
|
curl \
|
|
--fail-with-body \
|
|
--silent \
|
|
--show-error \
|
|
--request POST \
|
|
--header "Authorization: Bearer $operator_token" \
|
|
--header "Content-Type: application/json" \
|
|
--header "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" \
|
|
--data '{"operation":"status"}' \
|
|
"$CLAWHUB_TEST_MIRROR_GATE_URL" 2>/dev/null |
|
|
jq -r --arg ownedRun "$owned_run" '.runs[]? | select(.runId == $ownedRun and (.status == "running" or .status == "paused" or .status == "reconciling")) | .runId' |
|
|
head -n 1
|
|
)"
|
|
if [[ -n "$active_run" ]]; then
|
|
jq -n \
|
|
--arg runId "$active_run" \
|
|
'{operation:"discard",runId:$runId,reason:"CLAW-589 fail-closed cleanup"}' |
|
|
curl \
|
|
--fail-with-body \
|
|
--silent \
|
|
--show-error \
|
|
--request POST \
|
|
--header "Authorization: Bearer $operator_token" \
|
|
--header "Content-Type: application/json" \
|
|
--header "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" \
|
|
--data-binary @- \
|
|
"$CLAWHUB_TEST_MIRROR_GATE_URL" > claw589-discarded-run.json 2>&1
|
|
discard_exit=$?
|
|
fi
|
|
fi
|
|
bunx convex run --no-push skillsShMirror:configureInternal \
|
|
'{
|
|
"actor":"CLAW-589 Test workflow",
|
|
"reason":"CLAW-589 proof cleanup",
|
|
"confirm":"enable-skills-sh-mirror-test",
|
|
"enabled":false,
|
|
"maxRowsPerRun":50000,
|
|
"maxRowsPerBatch":50,
|
|
"maxDetailBytes":65536
|
|
}' > claw589-control-disabled.json 2>&1
|
|
disable_exit=$?
|
|
bunx convex run --no-push devSeed:seedCliRoleHelpFixtures '{}' >/dev/null
|
|
token_rotation_exit=$?
|
|
if [[ -n "$operator_token" ]]; then
|
|
revoked_status="$(
|
|
curl \
|
|
--silent \
|
|
--output /dev/null \
|
|
--write-out '%{http_code}' \
|
|
--header "Authorization: Bearer $operator_token" \
|
|
https://academic-chihuahua-392.convex.site/api/v1/operator/skills-sh/catalog-test
|
|
)"
|
|
else
|
|
revoked_status="not-created"
|
|
fi
|
|
jq -n \
|
|
--arg activeRun "$active_run" \
|
|
--arg ownedRun "$owned_run" \
|
|
--argjson discardExit "$discard_exit" \
|
|
--argjson disableExit "$disable_exit" \
|
|
--argjson tokenRotationExit "$token_rotation_exit" \
|
|
--arg revokedStatus "$revoked_status" \
|
|
'{
|
|
activeRun:$activeRun,
|
|
ownedRun:$ownedRun,
|
|
discardExit:$discardExit,
|
|
disableExit:$disableExit,
|
|
tokenRotationExit:$tokenRotationExit,
|
|
revokedStatus:$revokedStatus
|
|
}' > claw589-cleanup.json
|
|
set -e
|
|
[[
|
|
"$discard_exit" -eq 0 &&
|
|
"$disable_exit" -eq 0 &&
|
|
"$token_rotation_exit" -eq 0 &&
|
|
"$revoked_status" == "401"
|
|
]]
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
deployment_json="$(bunx convex run --no-push appMeta:getDeploymentInfo)"
|
|
build_sha="$(jq -r '.appBuildSha // empty' <<<"$deployment_json")"
|
|
if [[ "$build_sha" != "$DEPLOY_SHA" ]]; then
|
|
echo "::error::Unexpected Convex Test build SHA: $build_sha"
|
|
exit 1
|
|
fi
|
|
|
|
token_seed="$(bunx convex run --no-push devSeed:seedCliRoleHelpFixtures '{}')"
|
|
operator_token="$(jq -r '.admin.token // empty' <<<"$token_seed")"
|
|
token_seed=""
|
|
if [[ -z "$operator_token" ]]; then
|
|
echo "::error::Test admin fixture token is missing"
|
|
exit 1
|
|
fi
|
|
echo "::add-mask::$operator_token"
|
|
export CLAWHUB_TEST_OPERATOR_TOKEN="$operator_token"
|
|
bun run skills-sh:prove-trending > claw589-proof-output.json
|
|
|
|
jq -e '
|
|
.target.environment == "permanent Test" and
|
|
.target.productionWrites == 0 and
|
|
.source.view == "trending" and
|
|
.source.total > 0 and
|
|
.source.requestCount > 0 and
|
|
.source.durationMs >= 0 and
|
|
.source.countContract.trending24hInstalls == null and
|
|
.live.run.counts.observed == .source.total and
|
|
.replay.run.counts.trendingUpdated == 0 and
|
|
.stale.run.counts.trendingUpdated == 0 and
|
|
.hydration.maximumRowsPerRun == 50 and
|
|
.hydration.withinBound == true and
|
|
.isolation.unchanged == true
|
|
' proof/claw-589/skills-sh-trending-test-proof.json >/dev/null
|
|
|
|
jq -n \
|
|
--arg sourceSha "$DEPLOY_SHA" \
|
|
--arg deploymentUrl "$TEST_SITE_URL" \
|
|
'{
|
|
sourceSha:$sourceSha,
|
|
deploymentUrl:$deploymentUrl,
|
|
convexDeployment:"academic-chihuahua-392"
|
|
}' > claw589-deployment.json
|
|
|
|
cleanup
|
|
trap - EXIT
|
|
jq -e '
|
|
.discardExit == 0 and
|
|
.disableExit == 0 and
|
|
.tokenRotationExit == 0 and
|
|
.revokedStatus == "401"
|
|
' claw589-cleanup.json >/dev/null
|
|
|
|
- name: Upload permanent Test Trending proof
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: claw589-trending-proof
|
|
if-no-files-found: warn
|
|
path: |
|
|
proof/claw-589/skills-sh-trending-test-proof.json
|
|
proof/claw-589/active-run.json
|
|
claw589-proof-output.json
|
|
claw589-control-disabled.json
|
|
claw589-cleanup.json
|
|
claw589-deployment.json
|
|
claw589-discarded-run.json
|
|
|
|
claw577-search-proof:
|
|
needs: deploy-test
|
|
if: >-
|
|
(github.event_name == 'pull_request' &&
|
|
github.event.pull_request.head.ref == 'pe/claw-577-canonical-mixed-search' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-search-load')) ||
|
|
(github.event_name == 'workflow_dispatch' &&
|
|
github.ref == 'refs/heads/pe/claw-577-canonical-mixed-search' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-577-to-permanent-test' &&
|
|
inputs.expected_sha == needs.deploy-test.outputs.deploy_sha)
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
environment:
|
|
name: Test
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
ref: >-
|
|
${{
|
|
github.event_name == 'pull_request' && github.event.pull_request.head.sha ||
|
|
inputs.expected_sha
|
|
}}
|
|
|
|
- uses: ./.github/actions/setup-bun
|
|
|
|
- name: Prove canonical search order and cost in permanent Test
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
DEPLOY_SHA: ${{ needs.deploy-test.outputs.deploy_sha }}
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: |
|
|
set -euo pipefail
|
|
confirm=manage-claw-577-canonical-search-test-fixture
|
|
mkdir -p proof/claw-577
|
|
printf '{}\n' > proof/claw-577/active-fixture.json
|
|
cleanup() {
|
|
set +e
|
|
digest_id="$(jq -r '.digestId // empty' proof/claw-577/active-fixture.json 2>/dev/null)"
|
|
run_id="$(jq -r '.runId // empty' proof/claw-577/active-fixture.json 2>/dev/null)"
|
|
recovery_exit=0
|
|
cleanup_exit=0
|
|
if [[ -z "$digest_id" || -z "$run_id" ]]; then
|
|
bunx convex run --no-push \
|
|
searchTestFixtures:readCanonicalSearchTestFixture \
|
|
"{\"confirm\":\"$confirm\"}" > claw577-cleanup-recovery.json 2>&1
|
|
recovery_exit=$?
|
|
if [[ "$recovery_exit" -eq 0 ]]; then
|
|
digest_id="$(jq -r '.digestId // empty' claw577-cleanup-recovery.json)"
|
|
run_id="$(jq -r '.runId // empty' claw577-cleanup-recovery.json)"
|
|
fi
|
|
else
|
|
jq -n '{skipped:true,reason:"active fixture IDs were recorded"}' \
|
|
> claw577-cleanup-recovery.json
|
|
fi
|
|
if [[ -n "$digest_id" && -n "$run_id" ]]; then
|
|
cleanup_args="$(
|
|
jq -cn \
|
|
--arg confirm "$confirm" \
|
|
--arg digestId "$digest_id" \
|
|
--arg runId "$run_id" \
|
|
'{confirm:$confirm,digestId:$digestId,runId:$runId}'
|
|
)"
|
|
bunx convex run --no-push \
|
|
searchTestFixtures:cleanupCanonicalSearchTestFixture \
|
|
"$cleanup_args" > claw577-cleanup.json 2>&1
|
|
cleanup_exit=$?
|
|
else
|
|
jq -n '{ok:true,removed:false,skipped:true}' > claw577-cleanup.json
|
|
if [[ "$recovery_exit" -ne 0 ]]; then
|
|
cleanup_exit="$recovery_exit"
|
|
fi
|
|
fi
|
|
bunx convex run --no-push \
|
|
searchTestFixtures:readCanonicalSearchTestFixture \
|
|
"{\"confirm\":\"$confirm\"}" > claw577-cleanup-readback.json 2>&1
|
|
readback_exit=$?
|
|
jq -n \
|
|
--argjson cleanupExit "$cleanup_exit" \
|
|
--argjson recoveryExit "$recovery_exit" \
|
|
--argjson readbackExit "$readback_exit" \
|
|
'{cleanupExit:$cleanupExit,recoveryExit:$recoveryExit,readbackExit:$readbackExit}' \
|
|
> claw577-cleanup-status.json
|
|
set -e
|
|
[[ "$cleanup_exit" -eq 0 && "$recovery_exit" -eq 0 && "$readback_exit" -eq 0 ]]
|
|
jq -e '.present == false' claw577-cleanup-readback.json >/dev/null
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
[[ "$(git rev-parse HEAD)" == "$DEPLOY_SHA" ]]
|
|
bunx convex run --no-push appMeta:getDeploymentInfo '{}' > claw577-deployment-readback.json
|
|
jq -e --arg sha "$DEPLOY_SHA" '.appBuildSha == $sha' claw577-deployment-readback.json
|
|
bunx convex run --no-push \
|
|
searchTestFixtures:readCanonicalSearchTestFixture \
|
|
"{\"confirm\":\"$confirm\"}" > claw577-fixture-before.json
|
|
jq -e '.present == false' claw577-fixture-before.json >/dev/null
|
|
|
|
bunx convex run --no-push \
|
|
searchTestFixtures:seedCanonicalSearchTestFixture \
|
|
"{\"confirm\":\"$confirm\"}" > proof/claw-577/active-fixture.json
|
|
jq -e '
|
|
.ok == true and
|
|
.created == true and
|
|
(.digestId | type == "string") and
|
|
(.runId | type == "string")
|
|
' proof/claw-577/active-fixture.json >/dev/null
|
|
|
|
bun run search:prove-test > claw577-proof-output.json
|
|
jq -e --arg sha "$DEPLOY_SHA" '
|
|
.target.environment == "permanent Test" and
|
|
.target.deploySha == $sha and
|
|
.target.productionWrites == 0 and
|
|
.target.schedulesCreated == 0 and
|
|
.target.scansPlanned == 0 and
|
|
.target.scansAdmitted == 0 and
|
|
.target.claimsCreated == 0 and
|
|
.fixture.lifetimeInstalls == 9000000 and
|
|
.fixture.rankingWeight == 0 and
|
|
.contract.samplesPerSurface >= 3 and
|
|
(.cases | length) == 4
|
|
' proof/claw-577/canonical-search-test-proof.json >/dev/null
|
|
|
|
jq -n \
|
|
--arg sourceSha "$DEPLOY_SHA" \
|
|
--arg deploymentUrl "$TEST_SITE_URL" \
|
|
'{
|
|
sourceSha:$sourceSha,
|
|
deploymentUrl:$deploymentUrl,
|
|
convexDeployment:"academic-chihuahua-392"
|
|
}' > claw577-deployment.json
|
|
|
|
cleanup
|
|
trap - EXIT
|
|
jq -e '
|
|
.cleanupExit == 0 and
|
|
.recoveryExit == 0 and
|
|
.readbackExit == 0
|
|
' claw577-cleanup-status.json >/dev/null
|
|
|
|
- name: Upload permanent Test canonical search proof
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: claw577-search-proof
|
|
if-no-files-found: error
|
|
path: |
|
|
proof/claw-577/canonical-search-test-proof.json
|
|
proof/claw-577/active-fixture.json
|
|
claw577-proof-output.json
|
|
claw577-fixture-before.json
|
|
claw577-cleanup.json
|
|
claw577-cleanup-recovery.json
|
|
claw577-cleanup-readback.json
|
|
claw577-cleanup-status.json
|
|
claw577-deployment-readback.json
|
|
claw577-deployment.json
|
|
|
|
claw583-external-catalog-proof:
|
|
needs: deploy-test
|
|
if: >-
|
|
(github.event_name == 'pull_request' &&
|
|
github.event.pull_request.head.ref == 'pe/claw-583-mirrored-search-journey' &&
|
|
contains(github.event.pull_request.labels.*.name, 'test-external-catalog')) ||
|
|
(github.event_name == 'workflow_dispatch' &&
|
|
github.ref == 'refs/heads/pe/claw-583-mirrored-search-journey' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-583-to-permanent-test' &&
|
|
inputs.expected_sha == needs.deploy-test.outputs.deploy_sha)
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
environment:
|
|
name: Test
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
ref: >-
|
|
${{
|
|
github.event_name == 'pull_request' && github.event.pull_request.head.sha ||
|
|
inputs.expected_sha
|
|
}}
|
|
|
|
- uses: ./.github/actions/setup-bun
|
|
|
|
- name: Install Playwright browser
|
|
run: bunx playwright install --with-deps chromium
|
|
|
|
- name: Prove external search, detail, install, verify, and cleanup in permanent Test
|
|
env:
|
|
CLAWHUB_E2E_SKILLS_SH_EXTERNAL: "1"
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
DEPLOY_SHA: ${{ needs.deploy-test.outputs.deploy_sha }}
|
|
PLAYWRIGHT_BASE_URL: ${{ vars.SITE_URL }}
|
|
PLAYWRIGHT_WORKERS: "1"
|
|
TEST_CONVEX_SITE_URL: ${{ vars.VITE_CONVEX_SITE_URL }}
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: |
|
|
set -euo pipefail
|
|
confirm=manage-claw-583-external-catalog-test-fixture
|
|
mkdir -p proof/claw-583
|
|
printf '{}\n' > proof/claw-583/active-fixture.json
|
|
cleanup() {
|
|
set +e
|
|
bunx convex run --no-push \
|
|
skillsShPublicTestFixtures:readControlledExternalSkill \
|
|
"{\"confirm\":\"$confirm\"}" > claw583-cleanup-recovery.json 2>&1
|
|
recovery_exit=$?
|
|
digest_id="$(jq -r '.digestId // empty' claw583-cleanup-recovery.json 2>/dev/null)"
|
|
snapshot_id="$(jq -r '.sourceSnapshotId // empty' claw583-cleanup-recovery.json 2>/dev/null)"
|
|
cleanup_args="$(
|
|
jq -cn \
|
|
--arg confirm "$confirm" \
|
|
--arg digestId "$digest_id" \
|
|
--arg sourceSnapshotId "$snapshot_id" \
|
|
'{confirm:$confirm}
|
|
+ (if $digestId == "" then {} else {digestId:$digestId} end)
|
|
+ (if $sourceSnapshotId == "" then {} else {sourceSnapshotId:$sourceSnapshotId} end)'
|
|
)"
|
|
bunx convex run --no-push \
|
|
skillsShPublicTestFixtures:deactivateControlledExternalSkill \
|
|
"$cleanup_args" > claw583-cleanup.json 2>&1
|
|
cleanup_exit=$?
|
|
bunx convex run --no-push \
|
|
skillsShPublicTestFixtures:readControlledExternalSkill \
|
|
"{\"confirm\":\"$confirm\"}" > claw583-cleanup-readback.json 2>&1
|
|
readback_exit=$?
|
|
jq -n \
|
|
--argjson cleanupExit "$cleanup_exit" \
|
|
--argjson recoveryExit "$recovery_exit" \
|
|
--argjson readbackExit "$readback_exit" \
|
|
'{cleanupExit:$cleanupExit,recoveryExit:$recoveryExit,readbackExit:$readbackExit}' \
|
|
> claw583-cleanup-status.json
|
|
set -e
|
|
[[ "$cleanup_exit" -eq 0 && "$recovery_exit" -eq 0 && "$readback_exit" -eq 0 ]]
|
|
jq -e '.publicVisible == false and .installable == false' \
|
|
claw583-cleanup-readback.json >/dev/null
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
[[ "$(git rev-parse HEAD)" == "$DEPLOY_SHA" ]]
|
|
bunx convex run --no-push appMeta:getDeploymentInfo '{}' > claw583-deployment-readback.json
|
|
jq -e --arg sha "$DEPLOY_SHA" '.appBuildSha == $sha' claw583-deployment-readback.json
|
|
bunx convex run --no-push \
|
|
skillsShPublicTestFixtures:prepareControlledExternalSkill \
|
|
"{\"confirm\":\"$confirm\"}" > claw583-fixture-preparation.json
|
|
jq -e '
|
|
.ok == true and
|
|
.contentHash == "a47adb2c1ac33c088f664b5187971b63d2b958a7b9f01516d26005ca941a108f" and
|
|
.scansPlanned == 0 and
|
|
.scansAdmitted == 0
|
|
' claw583-fixture-preparation.json >/dev/null
|
|
bunx convex run --no-push \
|
|
skillsShPublicTestFixtures:readControlledExternalSkill \
|
|
"{\"confirm\":\"$confirm\"}" > claw583-fixture-before.json
|
|
jq -e '
|
|
.externalId == "patrick-erichsen/skills/html" and
|
|
.publicVisible == false and
|
|
.installable == false and
|
|
.scansPlanned == 0 and
|
|
.scansAdmitted == 0
|
|
' claw583-fixture-before.json >/dev/null
|
|
|
|
bunx convex run --no-push \
|
|
skillsShPublicTestFixtures:activateControlledExternalSkill \
|
|
"{\"confirm\":\"$confirm\"}" > proof/claw-583/active-fixture.json
|
|
jq -e '
|
|
.ok == true and
|
|
(.digestId | type == "string") and
|
|
(.detailId | type == "string") and
|
|
(.sourceSnapshotId | type == "string") and
|
|
.scansPlanned == 0 and
|
|
.scansAdmitted == 0
|
|
' proof/claw-583/active-fixture.json >/dev/null
|
|
bunx convex run --no-push \
|
|
skillsShPublicTestFixtures:readControlledExternalSkill \
|
|
"{\"confirm\":\"$confirm\"}" > claw583-fixture-active.json
|
|
jq -e '
|
|
.publicVisible == true and
|
|
.installable == true and
|
|
.repo == "patrick-erichsen/skills" and
|
|
.path == "skills/html" and
|
|
.commit == "050daba89f6b6636470add5cb300aac46a412cf8" and
|
|
.contentHash == "a47adb2c1ac33c088f664b5187971b63d2b958a7b9f01516d26005ca941a108f" and
|
|
.scansPlanned == 0 and
|
|
.scansAdmitted == 0
|
|
' claw583-fixture-active.json >/dev/null
|
|
|
|
bunx convex run --no-push search:searchSkills \
|
|
'{"query":"skills-sh:patrick-erichsen/skills/html","limit":10}' \
|
|
> claw583-search.json
|
|
jq -e '
|
|
map(select(.id == "skills-sh:patrick-erichsen/skills/html")) as $matches |
|
|
($matches | length) == 1 and
|
|
$matches[0].canonicalUrl == "/skills-sh/patrick-erichsen/skills/html" and
|
|
$matches[0].install.reference == "skills-sh:patrick-erichsen/skills/html"
|
|
' claw583-search.json >/dev/null
|
|
|
|
curl --fail-with-body --silent --show-error \
|
|
"$TEST_CONVEX_SITE_URL/api/v1/skills-sh/patrick-erichsen/skills/html" \
|
|
> claw583-detail.json
|
|
jq -e '
|
|
.reference == "skills-sh:patrick-erichsen/skills/html" and
|
|
.githubPath == "skills/html" and
|
|
.githubCommit == "050daba89f6b6636470add5cb300aac46a412cf8" and
|
|
.sourceContentHash == "a47adb2c1ac33c088f664b5187971b63d2b958a7b9f01516d26005ca941a108f" and
|
|
(.content.markdown | length) > 0
|
|
' claw583-detail.json >/dev/null
|
|
|
|
curl --fail-with-body --silent --show-error \
|
|
"$TEST_CONVEX_SITE_URL/api/v1/skills-sh/patrick-erichsen/skills/html/install" \
|
|
> claw583-install.json
|
|
jq -e '
|
|
.ok == true and
|
|
.slug == "skills-sh:patrick-erichsen/skills/html" and
|
|
.installKind == "github" and
|
|
.github.repo == "patrick-erichsen/skills" and
|
|
.github.path == "skills/html" and
|
|
.github.commit == "050daba89f6b6636470add5cb300aac46a412cf8" and
|
|
.github.contentHash == "a47adb2c1ac33c088f664b5187971b63d2b958a7b9f01516d26005ca941a108f" and
|
|
.provenance.source == "skills.sh" and
|
|
.provenance.reference == "skills-sh:patrick-erichsen/skills/html" and
|
|
.trust.clawhubScan == "unscanned" and
|
|
.trust.label == "Not scanned by ClawHub" and
|
|
.canonicalRef == null
|
|
' claw583-install.json >/dev/null
|
|
|
|
curl --fail-with-body --silent --show-error \
|
|
"$TEST_CONVEX_SITE_URL/api/v1/skills/html/verify?reference=skills-sh%3Apatrick-erichsen%2Fskills%2Fhtml" \
|
|
> claw583-verify.json
|
|
jq -e '
|
|
.ok == false and
|
|
.decision == "fail" and
|
|
(.reasons | index("Not scanned by ClawHub")) != null and
|
|
.provenance.source == "skills.sh" and
|
|
.provenance.reference == "skills-sh:patrick-erichsen/skills/html" and
|
|
.security.clawhubScan == "unscanned" and
|
|
.security.label == "Not scanned by ClawHub"
|
|
' claw583-verify.json >/dev/null
|
|
|
|
bunx playwright test --project=chromium e2e/skills-sh-external.pw.test.ts
|
|
|
|
jq -n \
|
|
--arg sourceSha "$DEPLOY_SHA" \
|
|
--arg deploymentUrl "$TEST_SITE_URL" \
|
|
--arg convexSiteUrl "$TEST_CONVEX_SITE_URL" \
|
|
'{
|
|
sourceSha:$sourceSha,
|
|
deploymentUrl:$deploymentUrl,
|
|
convexSiteUrl:$convexSiteUrl,
|
|
convexDeployment:"academic-chihuahua-392",
|
|
productionWrites:0,
|
|
schedulesCreated:0,
|
|
scansPlanned:0,
|
|
scansAdmitted:0,
|
|
claimsCreated:0
|
|
}' > claw583-deployment.json
|
|
|
|
cleanup
|
|
trap - EXIT
|
|
jq -e '
|
|
.cleanupExit == 0 and
|
|
.recoveryExit == 0 and
|
|
.readbackExit == 0
|
|
' claw583-cleanup-status.json >/dev/null
|
|
|
|
- name: Upload permanent Test external catalog proof
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: claw583-external-catalog-proof
|
|
if-no-files-found: error
|
|
path: |
|
|
proof/claw-583/active-fixture.json
|
|
proof/claw-583/external-flow.webm
|
|
proof/claw-583/external-search.png
|
|
proof/claw-583/external-detail.png
|
|
claw583-fixture-before.json
|
|
claw583-fixture-active.json
|
|
claw583-search.json
|
|
claw583-detail.json
|
|
claw583-install.json
|
|
claw583-verify.json
|
|
claw583-cleanup.json
|
|
claw583-cleanup-recovery.json
|
|
claw583-cleanup-readback.json
|
|
claw583-cleanup-status.json
|
|
claw583-deployment-readback.json
|
|
claw583-deployment.json
|
|
|
|
claw590-canonical-trending-proof:
|
|
needs: deploy-test
|
|
if: >-
|
|
github.event_name == 'workflow_dispatch' &&
|
|
github.ref == 'refs/heads/pe/claw-590-trending-snapshot' &&
|
|
inputs.branch_test_confirm == 'deploy-claw-590-to-permanent-test' &&
|
|
inputs.expected_sha == needs.deploy-test.outputs.deploy_sha
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
environment:
|
|
name: Test
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ inputs.expected_sha }}
|
|
|
|
- uses: ./.github/actions/setup-bun
|
|
|
|
- name: Prove canonical Trending materialization and API in permanent Test
|
|
env:
|
|
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
|
|
DEPLOY_SHA: ${{ needs.deploy-test.outputs.deploy_sha }}
|
|
TEST_SITE_URL: ${{ vars.SITE_URL }}
|
|
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
|
|
run: |
|
|
set -euo pipefail
|
|
confirm=manage-claw-590-canonical-trending-test-proof
|
|
snapshot_id="claw-590-proof-$DEPLOY_SHA"
|
|
mkdir -p proof/claw-590
|
|
printf '{"armed":false}\n' > proof/claw-590/active-snapshot.json
|
|
cleanup() {
|
|
set +e
|
|
armed="$(jq -r '.armed // false' proof/claw-590/active-snapshot.json 2>/dev/null)"
|
|
active_snapshot_id="$(jq -r '.snapshotId // empty' proof/claw-590/active-snapshot.json 2>/dev/null)"
|
|
cleanup_exit=0
|
|
if [[ "$armed" == true && -n "$active_snapshot_id" ]]; then
|
|
cleanup_args="$(
|
|
jq -cn \
|
|
--arg confirm "$confirm" \
|
|
--arg snapshotId "$active_snapshot_id" \
|
|
'{confirm:$confirm,snapshotId:$snapshotId}'
|
|
)"
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:cleanupCanonicalTrendingProof \
|
|
"$cleanup_args" > claw590-cleanup.json 2>&1
|
|
cleanup_exit=$?
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:readCanonicalTrendingProof \
|
|
"$cleanup_args" > claw590-cleanup-readback.json 2>&1
|
|
readback_exit=$?
|
|
else
|
|
jq -n '{ok:true,skipped:true}' > claw590-cleanup.json
|
|
jq -n '{present:false,skipped:true}' > claw590-cleanup-readback.json
|
|
readback_exit=0
|
|
fi
|
|
snapshot_removed=false
|
|
if [[ "$cleanup_exit" -eq 0 && "$readback_exit" -eq 0 ]] && \
|
|
jq -e '.present == false' claw590-cleanup-readback.json >/dev/null; then
|
|
snapshot_removed=true
|
|
fi
|
|
source_args="$(jq -cn --arg confirm "$confirm" '{confirm:$confirm}')"
|
|
if [[ "$snapshot_removed" == true ]]; then
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:cleanupCanonicalTrendingSourceFixture \
|
|
"$source_args" > claw590-source-cleanup.json 2>&1
|
|
source_cleanup_exit=$?
|
|
else
|
|
jq -n \
|
|
'{ok:false,skipped:true,reason:"snapshot cleanup incomplete; source retained"}' \
|
|
> claw590-source-cleanup.json
|
|
source_cleanup_exit=0
|
|
fi
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:readCanonicalTrendingSourceFixture \
|
|
"$source_args" > claw590-source-cleanup-readback.json 2>&1
|
|
source_readback_exit=$?
|
|
jq -n \
|
|
--argjson cleanupExit "$cleanup_exit" \
|
|
--argjson readbackExit "$readback_exit" \
|
|
--argjson sourceCleanupExit "$source_cleanup_exit" \
|
|
--argjson sourceReadbackExit "$source_readback_exit" \
|
|
'{
|
|
cleanupExit:$cleanupExit,
|
|
readbackExit:$readbackExit,
|
|
sourceCleanupExit:$sourceCleanupExit,
|
|
sourceReadbackExit:$sourceReadbackExit
|
|
}' \
|
|
> claw590-cleanup-status.json
|
|
set -e
|
|
[[ \
|
|
"$cleanup_exit" -eq 0 && \
|
|
"$readback_exit" -eq 0 && \
|
|
"$source_cleanup_exit" -eq 0 && \
|
|
"$source_readback_exit" -eq 0 \
|
|
]]
|
|
jq -e '.present == false' claw590-cleanup-readback.json >/dev/null
|
|
jq -e '.present == false' claw590-source-cleanup-readback.json >/dev/null
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
[[ "$(git rev-parse HEAD)" == "$DEPLOY_SHA" ]]
|
|
bunx convex run --no-push appMeta:getDeploymentInfo '{}' > claw590-deployment-readback.json
|
|
jq -e --arg sha "$DEPLOY_SHA" '.appBuildSha == $sha' claw590-deployment-readback.json
|
|
proof_args="$(
|
|
jq -cn \
|
|
--arg confirm "$confirm" \
|
|
--arg snapshotId "$snapshot_id" \
|
|
'{confirm:$confirm,snapshotId:$snapshotId}'
|
|
)"
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:readCanonicalTrendingProof \
|
|
"$proof_args" > claw590-before.json
|
|
if jq -e '.present == true' claw590-before.json >/dev/null; then
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:cleanupCanonicalTrendingProof \
|
|
"$proof_args" > claw590-recovery.json
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:readCanonicalTrendingProof \
|
|
"$proof_args" > claw590-recovery-readback.json
|
|
jq -e '.present == false' claw590-recovery-readback.json >/dev/null
|
|
else
|
|
jq -n '{ok:true,skipped:true}' > claw590-recovery.json
|
|
cp claw590-before.json claw590-recovery-readback.json
|
|
fi
|
|
jq -e '.present == false' claw590-recovery-readback.json >/dev/null
|
|
|
|
source_args="$(jq -cn --arg confirm "$confirm" '{confirm:$confirm}')"
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:readCanonicalTrendingSourceFixture \
|
|
"$source_args" > claw590-source-before.json
|
|
if jq -e '.present == true' claw590-source-before.json >/dev/null; then
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:cleanupCanonicalTrendingSourceFixture \
|
|
"$source_args" > claw590-source-recovery.json
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:readCanonicalTrendingSourceFixture \
|
|
"$source_args" > claw590-source-recovery-readback.json
|
|
jq -e '.present == false' claw590-source-recovery-readback.json >/dev/null
|
|
else
|
|
jq -n '{ok:true,skipped:true}' > claw590-source-recovery.json
|
|
cp claw590-source-before.json claw590-source-recovery-readback.json
|
|
fi
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:seedCanonicalTrendingSourceFixture \
|
|
"$source_args" > claw590-source-seed.json
|
|
bunx convex run --no-push \
|
|
canonicalTrendingTestFixtures:readCanonicalTrendingSourceFixture \
|
|
"$source_args" > claw590-source-active.json
|
|
jq -e '
|
|
.present == true and
|
|
.nativeCount == 12 and
|
|
.nativePublisherCount == 6 and
|
|
.externalCount == 8 and
|
|
.scansPlanned == 0 and
|
|
.scansAdmitted == 0
|
|
' claw590-source-active.json >/dev/null
|
|
|
|
bun run trending:prove-test > claw590-proof-output.json
|
|
jq -e '
|
|
.target.environment == "permanent Test" and
|
|
.target.deploySha == env.DEPLOY_SHA and
|
|
.materialization.snapshotId == ("claw-590-proof-" + env.DEPLOY_SHA) and
|
|
.materialization.totalItems >= 20 and
|
|
.materialization.operations.documentsRead > 0 and
|
|
.materialization.operations.documentsWritten > 0 and
|
|
.materialization.operations.functionCalls > 0 and
|
|
.assertions.laneCounts["clawhub-trending"] == 8 and
|
|
.assertions.laneCounts["clawhub-rising"] == 4 and
|
|
.assertions.laneCounts["skills-sh-trending"] == 8 and
|
|
.assertions.maximumPublisherCount <= 2 and
|
|
.assertions.stableSnapshot == true and
|
|
.assertions.stableCursor == true and
|
|
.assertions.stableOrder == true and
|
|
.assertions.completePagination == true and
|
|
.assertions.skillsShTrending24hInstalls == null
|
|
' proof/claw-590/canonical-trending-test-proof.json >/dev/null
|
|
|
|
cleanup
|
|
trap - EXIT
|
|
jq -e '
|
|
.cleanupExit == 0 and
|
|
.readbackExit == 0 and
|
|
.sourceCleanupExit == 0 and
|
|
.sourceReadbackExit == 0
|
|
' claw590-cleanup-status.json >/dev/null
|
|
jq -e '.present == false' claw590-cleanup-readback.json >/dev/null
|
|
jq -e '.present == false' claw590-source-cleanup-readback.json >/dev/null
|
|
|
|
- name: Upload permanent Test canonical Trending proof
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: claw590-canonical-trending-proof
|
|
if-no-files-found: error
|
|
path: |
|
|
proof/claw-590/canonical-trending-test-proof.json
|
|
proof/claw-590/active-snapshot.json
|
|
claw590-proof-output.json
|
|
claw590-before.json
|
|
claw590-recovery.json
|
|
claw590-recovery-readback.json
|
|
claw590-cleanup.json
|
|
claw590-cleanup-readback.json
|
|
claw590-cleanup-status.json
|
|
claw590-deployment-readback.json
|
|
claw590-source-before.json
|
|
claw590-source-recovery.json
|
|
claw590-source-recovery-readback.json
|
|
claw590-source-seed.json
|
|
claw590-source-active.json
|
|
claw590-source-cleanup.json
|
|
claw590-source-cleanup-readback.json
|