Skip to content
Merged
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
61 changes: 52 additions & 9 deletions .github/workflows/sync-skills.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ jobs:
GH_TOKEN: ${{ secrets.SKILLS_SYNC_PAT }}
run: |
set -euo pipefail
truncate -s 0 /tmp/synced-products.txt
truncate -s 0 /tmp/synced-components.txt
truncate -s 0 /tmp/failed-components.txt

# Configure git to use the token via credential helper
# so it never appears in clone URLs or error output
Expand All @@ -63,6 +64,7 @@ jobs:
"https://github.com/${repo}.git" \
"$tmp_dir" -b "$ref" 2>/dev/null; then
echo " ⚠ Clone failed for $repo — skipping"
echo "- **$name** ($repo): clone failed" >> /tmp/failed-components.txt
continue
fi

Expand All @@ -89,38 +91,51 @@ jobs:
echo " ✓ $path → skills/$catalog_dir/"
else
echo " ⚠ $path empty or missing — skipping to preserve existing catalog"
echo "- **$name** ($repo): \`$path\` empty or missing" >> /tmp/failed-components.txt
fi
done

$synced && echo "- $name" >> /tmp/synced-products.txt
$synced && echo "- $name" >> /tmp/synced-components.txt
echo ""
done

rm -rf .tmp

- name: Fail if nothing synced
run: |
if [ ! -s /tmp/synced-products.txt ]; then
echo "::error::All product checkouts failed — no skills were synced"
if [ ! -s /tmp/synced-components.txt ]; then
echo "::error::All component checkouts failed — no skills were synced"
exit 1
fi

- name: Build sync summary
id: summary
run: |
products=$(cat /tmp/synced-products.txt | tr '\n' ',' | sed 's/- //g;s/,$//')
echo "title=chore: sync skills ($products)" >> "$GITHUB_OUTPUT"
synced=$(cat /tmp/synced-components.txt | tr '\n' ',' | sed 's/- //g;s/,$//')
echo "title=chore: sync skills ($synced)" >> "$GITHUB_OUTPUT"
{
echo 'body<<EOFBODY'
echo "## Automated skills sync"
echo ""
echo "Products synced:"
cat /tmp/synced-products.txt
echo "**Components synced:**"
cat /tmp/synced-components.txt
if [ -s /tmp/failed-components.txt ]; then
echo ""
echo "**Components that failed to sync:**"
cat /tmp/failed-components.txt
fi
echo ""
echo "Triggered by: \`${{ github.event_name }}\`"
echo 'EOFBODY'
} >> "$GITHUB_OUTPUT"

# Surface failed count for downstream steps
if [ -s /tmp/failed-components.txt ]; then
echo "has_failures=true" >> "$GITHUB_OUTPUT"
else
echo "has_failures=false" >> "$GITHUB_OUTPUT"
fi

- name: Create pull request
uses: peter-evans/create-pull-request@v6
with:
Expand All @@ -130,7 +145,35 @@ jobs:
body: ${{ steps.summary.outputs.body }}
delete-branch: true

- name: Open issue on failure
- name: Open issue for failed components
if: steps.summary.outputs.has_failures == 'true'
continue-on-error: true
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const failed = fs.readFileSync('/tmp/failed-components.txt', 'utf8').trim();
const title = `Skills sync: some components failed — ${new Date().toISOString().slice(0, 10)}`;
const body = [
`The [sync-skills workflow](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) completed but some components failed to sync.`,
``,
`**Failed components:**`,
failed,
``,
`**Run:** ${context.runId}`,
`**Trigger:** \`${context.eventName}\``,
``,
`This usually means the skill path in \`components.yml\` doesn't match the actual directory in the source repo (e.g. symlink, renamed, or removed).`
].join('\n');
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title,
body,
labels: ['sync-failure']
});

- name: Open issue on total failure
if: failure()
continue-on-error: true
uses: actions/github-script@v7
Expand Down