Use shared package-and-sync reusable workflow (#253)

* Use shared package-and-sync reusable workflow

Replace the inline package/sync workflow with a thin caller of the shared
temporalio/skill-ci reusable workflow (pinned to v1). This also corrects the
codex plugin target path, which was stale (plugins/temporal-developer/... →
plugins/temporal/... as used by the shared workflow and present in the repo).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Pin shared workflow to @v1 tag instead of SHA

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add one-click bump dispatch input to release workflow

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Donald Pinckney
2026-07-05 20:15:05 +08:00
committed by GitHub
parent e7b111cd7c
commit 4f7b14626c
+19 -230
View File
@@ -1,10 +1,7 @@
# ABOUTME: Packages the skill on every push to main (as a ZIP artifact) and, if the version in SKILL.md
# ABOUTME: has been bumped, creates a GitHub Release and syncs the skill contents to three plugin repos
# ABOUTME: (cursor-temporal-plugin, codex-temporal-plugin, claude-temporal-plugin) via PRs.
# ABOUTME: Required secrets (used only by the sync job for cross-repo PRs):
# ABOUTME: SKILL_T_DEV_APP_ID — the GitHub App's ID
# ABOUTME: SKILL_T_DEV_KEY — the GitHub App's private key
# ABOUTME: The app must be installed on the three plugin repos with Contents (write) and Pull Requests (write).
# ABOUTME: Packages this skill and syncs it to the plugin repos on version bumps.
# ABOUTME: All logic lives in the shared reusable workflow at temporalio/skill-ci; this is just the caller.
# ABOUTME: Release two ways: (1) run this manually and pick a bump, or (2) edit SKILL.md's version and push.
# ABOUTME: Secrets SKILL_T_DEV_APP_ID / SKILL_T_DEV_KEY / RELEASE_SSH_KEY are inherited (see skill-ci README).
name: Package and Sync Skill
@@ -12,230 +9,22 @@ on:
push:
branches: [main]
workflow_dispatch:
inputs:
bump:
description: "Version bump for a one-click release"
type: choice
required: true
default: patch
options: [patch, minor, major]
jobs:
package:
runs-on: ubuntu-latest
package-and-sync:
uses: temporalio/skill-ci/.github/workflows/package-and-sync.yml@v1
permissions:
contents: write
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
released: ${{ steps.tag_check.outputs.exists == 'false' }}
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
- name: Read version from SKILL.md
id: version
run: |
version=$(grep '^version:' SKILL.md | sed 's/version:[[:space:]]*//')
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "tag=v$version" >> "$GITHUB_OUTPUT"
- name: Check if tag exists
id: tag_check
run: |
if git rev-parse "refs/tags/${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
- name: Package skill
run: |
zip -r temporal-developer-skill.zip \
SKILL.md \
references/ \
-x '*.DS_Store'
- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: temporal-developer-skill
path: temporal-developer-skill.zip
- name: Create release
if: steps.tag_check.outputs.exists == 'false'
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
tag_name: ${{ steps.version.outputs.tag }}
name: ${{ steps.version.outputs.tag }}
files: temporal-developer-skill.zip
generate_release_notes: true
sync:
needs: package
if: needs.package.outputs.released == 'true' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
# contents: write is required by the POST /releases/generate-notes endpoint,
# even though it only returns text and doesn't actually write anything.
contents: write
strategy:
fail-fast: false
matrix:
include:
- repo: temporalio/cursor-temporal-plugin
target_path: skills/temporal-developer
- repo: temporalio/codex-temporal-plugin
target_path: plugins/temporal-developer/skills/temporal-developer
- repo: temporalio/claude-temporal-plugin
target_path: skills/temporal-developer
steps:
- name: Generate token from GitHub App
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.SKILL_T_DEV_APP_ID }}
private-key: ${{ secrets.SKILL_T_DEV_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout source
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
- name: Checkout target repo
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: ${{ matrix.repo }}
token: ${{ steps.app-token.outputs.token }}
path: target-repo
- name: Sync skill contents
working-directory: target-repo
run: |
BRANCH="sync/temporal-developer-skill"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Create or reset the sync branch based on current main.
# -B ensures the branch always starts from main's tip, even if a
# stale remote branch exists from a previously merged PR.
git checkout -B "$BRANCH" origin/main
# Remove old contents and copy current
rm -rf "${{ matrix.target_path }}/SKILL.md" \
"${{ matrix.target_path }}/references"
cp ../SKILL.md "${{ matrix.target_path }}/"
cp -r ../references "${{ matrix.target_path }}/"
# Check for changes against main
git add "${{ matrix.target_path }}"
if git diff --cached --quiet; then
echo "no_changes=true" >> "$GITHUB_ENV"
echo "No changes to sync"
else
echo "no_changes=false" >> "$GITHUB_ENV"
version="${{ needs.package.outputs.tag }}"
git commit -m "sync temporal-developer skill ${version} from source repo"
git push --force origin "$BRANCH"
fi
- name: Build changelog
if: env.no_changes == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
current_tag="${{ needs.package.outputs.tag }}"
# Determine the base for the changelog: the version currently on the
# target repo's main branch. This represents what was last merged, so
# the changelog spans every release since then — correctly accumulating
# unmerged versions if a prior sync PR is still open.
#
# Read the old SKILL.md from git (it's been overwritten on disk by the
# sync step) via `git show origin/main:...`.
target_version=$(git -C target-repo show "origin/main:${{ matrix.target_path }}/SKILL.md" 2>/dev/null \
| grep '^version:' | sed 's/version:[[:space:]]*//' || echo "")
if [ -n "$target_version" ]; then
base_tag="v${target_version}"
else
base_tag=""
fi
# The target repo's recorded version may not correspond to an
# actual tag in this source repo (e.g. the target was last
# updated from a different repo, or a tag was never published
# for that version). If the tag doesn't exist locally, find the
# most recent tag that's an ancestor of HEAD and predates the
# current tag; if nothing matches, leave base_tag empty so the
# fallback path runs.
if [ -n "$base_tag" ] && ! git rev-parse --verify --quiet "refs/tags/${base_tag}" >/dev/null; then
echo "Base tag ${base_tag} does not exist in this repo; searching for closest preceding tag"
fallback_tag=$(git tag --sort=-v:refname | awk -v cur="$current_tag" '$0 != cur' | head -1 || true)
if [ -n "$fallback_tag" ]; then
echo "Using ${fallback_tag} as base tag instead"
base_tag="$fallback_tag"
else
base_tag=""
fi
fi
# Prefer GitHub's auto-generated notes for the range (nicely formatted
# with PR links and contributors). Fall back to git log if unavailable.
echo "Base tag: ${base_tag:-<none>} / Current tag: ${current_tag}"
if [ -n "$base_tag" ]; then
if notes=$(gh api \
--method POST \
"/repos/${{ github.repository }}/releases/generate-notes" \
-f tag_name="${current_tag}" \
-f previous_tag_name="${base_tag}" \
--jq '.body') && [ -n "$notes" ]; then
echo "Using auto-generated release notes"
echo "$notes" > /tmp/changelog.md
else
echo "generate-notes API call failed or empty; falling back to git log"
git log --oneline "${base_tag}..HEAD" > /tmp/changelog.md \
|| git log --oneline -20 > /tmp/changelog.md
fi
else
echo "No base tag found; using last 20 commits"
git log --oneline -20 > /tmp/changelog.md
fi
- name: Create or update PR
if: env.no_changes == 'false'
working-directory: target-repo
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
BRANCH="sync/temporal-developer-skill"
version="${{ needs.package.outputs.tag }}"
changelog=$(cat /tmp/changelog.md)
# Check if a PR already exists from this branch
existing_pr=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number')
if [ -n "$existing_pr" ]; then
echo "PR #${existing_pr} already exists — updated by the force-push"
gh pr edit "$existing_pr" \
--title "Sync temporal-developer skill ${version}" \
--body "Automated sync of the temporal-developer skill ${version} from [skill-temporal-developer](https://github.com/${{ github.repository }}).
This PR was updated automatically by the [sync workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).
## Changelog
${changelog}"
gh pr comment "$existing_pr" --body "Updated to ${version} from [skill-temporal-developer](https://github.com/${{ github.repository }})."
pr_url=$(gh pr view "$existing_pr" --json url --jq '.url')
echo "### ${{ matrix.repo }}" >> "$GITHUB_STEP_SUMMARY"
echo "Updated [PR #${existing_pr}](${pr_url})" >> "$GITHUB_STEP_SUMMARY"
else
pr_url=$(gh pr create \
--title "Sync temporal-developer skill ${version}" \
--body "Automated sync of the temporal-developer skill ${version} from [skill-temporal-developer](https://github.com/${{ github.repository }}).
This PR was created automatically by the [sync workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).
## Changelog
${changelog}")
echo "### ${{ matrix.repo }}" >> "$GITHUB_STEP_SUMMARY"
echo "Created ${pr_url}" >> "$GITHUB_STEP_SUMMARY"
fi
secrets: inherit
with:
# On workflow_dispatch this is the chosen bump; empty on push events.
bump: ${{ inputs.bump }}
# Override the whitelist only if this skill has extra paths to include:
# includes: "SKILL.md agents references scripts"