|
| 1 | +name: Sync Repos |
| 2 | + |
| 3 | +on: |
| 4 | + schedule: |
| 5 | + - cron: '0 */6 * * *' |
| 6 | + workflow_dispatch: |
| 7 | + |
| 8 | +concurrency: |
| 9 | + group: add-repo |
| 10 | + cancel-in-progress: false |
| 11 | + |
| 12 | +permissions: |
| 13 | + contents: write |
| 14 | + |
| 15 | +jobs: |
| 16 | + sync: |
| 17 | + runs-on: ubuntu-latest |
| 18 | + steps: |
| 19 | + - uses: actions/checkout@v4 |
| 20 | + with: |
| 21 | + # BOT_TOKEN (PAT with 'repo' and 'workflow' scopes) is required so that |
| 22 | + # the push triggers the build-index.yml workflow. The default GITHUB_TOKEN |
| 23 | + # cannot trigger downstream workflow runs due to GitHub's security model. |
| 24 | + # To create: Settings → Secrets and variables → Actions → New secret named BOT_TOKEN. |
| 25 | + token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }} |
| 26 | + |
| 27 | + - name: Install yq |
| 28 | + run: | |
| 29 | + sudo wget -qO /usr/local/bin/yq \ |
| 30 | + https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 |
| 31 | + sudo chmod +x /usr/local/bin/yq |
| 32 | +
|
| 33 | + - name: Sync repos with arch-docs |
| 34 | + id: sync |
| 35 | + env: |
| 36 | + GH_TOKEN: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }} |
| 37 | + run: | |
| 38 | + set -euo pipefail |
| 39 | + ADDED=0 |
| 40 | +
|
| 41 | + # Fetch all org repos, one JSON object per line |
| 42 | + gh api --paginate \ |
| 43 | + "orgs/supermodeltools/repos?per_page=100&type=all" \ |
| 44 | + --jq '.[] | @json' > /tmp/repos.ndjson |
| 45 | +
|
| 46 | + while IFS= read -r repo_json; do |
| 47 | + REPO_NAME=$(echo "$repo_json" | jq -r '.name') |
| 48 | + IS_FORK=$(echo "$repo_json" | jq -r '.fork') |
| 49 | + DESCRIPTION=$(echo "$repo_json" | jq -r '.description // ""') |
| 50 | + LANGUAGE=$(echo "$repo_json" | jq -r '.language // ""') |
| 51 | + PARENT=$(echo "$repo_json" | jq -r '.parent.full_name // ""') |
| 52 | +
|
| 53 | + # Skip this repository itself |
| 54 | + if [ "$REPO_NAME" = "supermodeltools.github.io" ]; then |
| 55 | + continue |
| 56 | + fi |
| 57 | +
|
| 58 | + # Skip if already listed in repos.yaml |
| 59 | + if grep -qE "^\s+name: ${REPO_NAME}$" repos.yaml; then |
| 60 | + continue |
| 61 | + fi |
| 62 | +
|
| 63 | + # Check for arch-docs workflow — skip if not present |
| 64 | + if ! gh api "repos/supermodeltools/${REPO_NAME}/contents/.github/workflows/arch-docs.yml" \ |
| 65 | + >/dev/null 2>&1; then |
| 66 | + continue |
| 67 | + fi |
| 68 | +
|
| 69 | + # Map language to pill_class |
| 70 | + case "$LANGUAGE" in |
| 71 | + JavaScript|TypeScript) PILL_CLASS="pill-blue" ;; |
| 72 | + Python) PILL_CLASS="pill-green" ;; |
| 73 | + Go|Rust|C|"C++") PILL_CLASS="pill-accent" ;; |
| 74 | + Java|Kotlin|Scala|Ruby|Swift) PILL_CLASS="pill-orange" ;; |
| 75 | + Shell|HCL) PILL_CLASS="pill-green" ;; |
| 76 | + *) PILL_CLASS="" ;; |
| 77 | + esac |
| 78 | +
|
| 79 | + # Map language to pill label (Shell/HCL → DevOps) |
| 80 | + case "$LANGUAGE" in |
| 81 | + Shell|HCL) PILL="DevOps" ;; |
| 82 | + "") PILL="" ;; |
| 83 | + *) PILL="$LANGUAGE" ;; |
| 84 | + esac |
| 85 | +
|
| 86 | + echo "Adding: ${REPO_NAME} (fork=${IS_FORK}, lang=${LANGUAGE})" |
| 87 | +
|
| 88 | + if [ "$IS_FORK" = "true" ]; then |
| 89 | + # Append to Community category (index 1) |
| 90 | + REPO_NAME="$REPO_NAME" \ |
| 91 | + DESCRIPTION="$DESCRIPTION" \ |
| 92 | + PILL="$PILL" \ |
| 93 | + PILL_CLASS="$PILL_CLASS" \ |
| 94 | + UPSTREAM="$PARENT" \ |
| 95 | + yq -i '.categories[1].repos += [{ |
| 96 | + "name": env(REPO_NAME), |
| 97 | + "upstream": env(UPSTREAM), |
| 98 | + "description": env(DESCRIPTION), |
| 99 | + "pill": env(PILL), |
| 100 | + "pill_class": env(PILL_CLASS) |
| 101 | + }]' repos.yaml |
| 102 | + else |
| 103 | + # Append to Supermodel Open Source category (index 0) |
| 104 | + REPO_NAME="$REPO_NAME" \ |
| 105 | + DESCRIPTION="$DESCRIPTION" \ |
| 106 | + PILL="$PILL" \ |
| 107 | + PILL_CLASS="$PILL_CLASS" \ |
| 108 | + yq -i '.categories[0].repos += [{ |
| 109 | + "name": env(REPO_NAME), |
| 110 | + "description": env(DESCRIPTION), |
| 111 | + "pill": env(PILL), |
| 112 | + "pill_class": env(PILL_CLASS) |
| 113 | + }]' repos.yaml |
| 114 | + fi |
| 115 | +
|
| 116 | + ADDED=$((ADDED + 1)) |
| 117 | + done < /tmp/repos.ndjson |
| 118 | +
|
| 119 | + echo "added=${ADDED}" >> "$GITHUB_OUTPUT" |
| 120 | + echo "Sync complete: ${ADDED} repo(s) added" |
| 121 | +
|
| 122 | + - name: Commit and push |
| 123 | + if: steps.sync.outputs.added != '0' |
| 124 | + run: | |
| 125 | + git config user.name "supermodel-bot" |
| 126 | + git config user.email "bot@supermodeltools.com" |
| 127 | + git add repos.yaml |
| 128 | + git commit -m "Sync ${{ steps.sync.outputs.added }} repo(s) discovered with arch-docs" |
| 129 | + git push |
0 commit comments