mirror of
https://github.com/temporalio/skill-temporal-developer.git
synced 2026-09-14 13:52:58 +08:00
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:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user