Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions deliverables/ci-workflow-sha-pin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# CI Workflow SHA-Pin + YAML Repair

The repo's org ruleset requires every GitHub Actions `uses:` reference to be pinned to a
**full 40-character commit SHA**. On `main`, 68 references across 9 workflows were still on
moving tags (`@v4`, `@v5`, `@main`, ...), which fails every job at "Set up job" — and four
workflows did not parse as YAML at all.

The Fig GitHub App lacks the **`workflows`** scope for this repo, so it cannot push changes
under `.github/workflows/` directly. This deliverable carries the verified fix so it can be
applied in one step.

## What was changed

**1. Pinned 68 action references across 9 workflows** to full commit SHAs, resolved from the
upstream tags via the GitHub API and **verified reachable** (23 distinct action@sha pairs,
all HTTP 200 on `github.com/<owner>/<repo>/commit/<sha>`). Each pinned line keeps a trailing
`# vN` comment for readability.

| Workflow | refs pinned |
|---|---|
| build-compress-all-platforms.yml | 29 |
| ci.yml | 13 |
| live-task.yml | 7 |
| static.yml | 4 |
| test-and-coverage.yaml | 4 |
| Auto-Index-Sync.yml | 3 |
| secret-scan.yml | 3 |
| test-suite.yml | 3 |
| dependabot-automerge.yml | 2 |

**2. Repaired 4 workflows whose YAML did not parse on `main`** (pre-existing, not caused by
pinning — confirmed by validating the `HEAD` versions):

- `secret-scan.yml` — `workflow_dispatch;` -> `workflow_dispatch:`
- `dependabot-automerge.yml` — removed 87 lines of appended markdown docs that followed the workflow
- `test-suite.yml` — extracted the YAML body from the markdown code fence it was wrapped in
- `Auto-Index-Sync.yml` — replaced an indentation-breaking single-quoted heredoc with `printf`

No workflow **logic** was changed.

## How to apply

### Option A - apply the patch (recommended)

```bash
git checkout main && git pull
git checkout -b fix/sha-pin-and-yaml-repair
git apply deliverables/ci-workflow-sha-pin/sha-pin-and-yaml-repair.patch
python -c "import yaml,glob;[yaml.safe_load(open(f)) for f in glob.glob('.github/workflows/*.y*ml')];print('all workflows parse')"
git add .github/workflows && git commit -m "fix(ci): pin all actions to full SHAs and repair broken workflow YAML"
git push -u origin fix/sha-pin-and-yaml-repair
```

### Option B - copy the fixed files

```bash
cp deliverables/ci-workflow-sha-pin/fixed-workflows/*.y*ml .github/workflows/
```

## Verification

Every claim above was checked:

- **YAML**: all 10 root workflows parse with `yaml.safe_load` (0 failures).
- **SHAs**: all 23 distinct `action@sha` pairs return HTTP 200 from their upstream repo — none are
fabricated, which matters because a prior attempt shipped SHAs that did not exist.
- **Unpinned refs remaining in root workflows**: only `.github/workflows/github-actions-autodebug-autorerun`,
which has **no `.yml`/`.yaml` extension** so GitHub never runs it, and references
`ZyntroAI/ai-codefix-action@v1` — **a repository that does not exist**. Left untouched
deliberately; it is inert.

## Scripts (reproducible)

- `scripts/resolve_shas_api.py` — resolves real SHAs for each tag via the GitHub API
- `scripts/pin_workflows.py` — rewrites `uses:` refs to pinned SHAs (idempotent)
- `scripts/repair_workflows.py` — repairs the four broken YAML files
- `scripts/verify_shas.py` — asserts every pinned SHA exists upstream

## Known limitation

The Fig App cannot push `.github/workflows/` changes for this repo. If applying via a PR,
either use the user's own credentials, or grant the app the `workflows` scope.
102 changes: 102 additions & 0 deletions deliverables/ci-workflow-sha-pin/fixed-workflows/Auto-Index-Sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Auto Index Sync
# ⏰ Triggers — Push, Nightly Schedule, Manual
on:
push:
branches:
- main
paths:
- "docs/**"
- ".github/workflows/auto-index-sync.yml"
schedule:
- cron: "0 2 * * *" # Daily at 02:00 UTC → 09:00 ICT
workflow_dispatch:
inputs:
dry_run:
description: "Preview only — skip push/commit"
required: false
default: false
type: boolean

# 🔒 Permissions — Minimal required
permissions:
contents: write # needed for checkout + commit/push

jobs:
# ─────────────────────────────────────────────────────
# Job 1: Index Repository Documentation
# ─────────────────────────────────────────────────────
index-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Extract metadata from docs
run: |
python scripts/extract_metadata.py docs/ > repo_index.json

- name: Push index to Algolia
env:
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }}
run: |
python scripts/push_index.py repo_index.json

# ─────────────────────────────────────────────────────
# Job 2: Sync External Docs (OpenClaw)
# ─────────────────────────────────────────────────────
sync-external-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Crawl & parse OpenClaw docs
run: |
curl -sL --max-time 30 https://docs.openclaw.ai > openclaw.html
python scripts/parse_docs.py openclaw.html > openclaw_index.json

- name: Push external docs index
run: |
python scripts/push_index.py openclaw_index.json

# ─────────────────────────────────────────────────────
# Job 3: Audit Affiliate Policy & Commit Changes
# ─────────────────────────────────────────────────────
audit-policies:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Fetch affiliate terms
run: |
curl -sL --max-time 30 https://www.upcomers.com/policies/affiliate-terms-conditions > affiliate.html

- name: Verify parse script exists
run: |
if [ ! -f scripts/parse_docs.py ]; then
echo "⚠️ scripts/parse_docs.py missing — creating placeholder"
mkdir -p scripts
printf '%s\n' '#!/usr/bin/env python3' 'import sys' 'print("# Policy Snapshot\n")' 'print("Source:", sys.argv[1])' > scripts/parse_docs.py
chmod +x scripts/parse_docs.py
fi

- name: Parse policy & generate diff
run: |
python scripts/parse_docs.py affiliate.html > policy_diff.md
cat policy_diff.md

- name: Commit & push changes
if: ${{ inputs.dry_run == false }}
run: |
git config user.name "index-bot"
git config user.email "bot@example.com"
git add affiliate.html policy_diff.md
# Skip commit if no changes
if git diff --staged --quiet; then
echo "✅ No policy changes detected — nothing to commit"
exit 0
fi
git commit -m "chore: update affiliate policy snapshot [skip ci]"
git push
Loading
Loading