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
2 changes: 1 addition & 1 deletion .github/scripts/sync-template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ if [ -f "$template_root/.github/template.yml" ]; then
source_runtime_repository="$(awk -F': ' '/^runtime_repository:/ {print $2; exit}' "$template_root/.github/template.yml")"
fi
[ -n "$source_runtime_repository" ] || source_runtime_repository="0xPlayerOne/code-foundry"
for file in .github/workflows/ci.yml .github/workflows/test.yml .github/workflows/security.yml .github/workflows/codeql.yml; do
for file in .github/workflows/ci.yml .github/workflows/test.yml .github/workflows/security.yml .github/workflows/codeql.yml .github/workflows/draft-pr.yml .github/workflows/release-pr.yml; do
[ -f "$file" ] || continue
if grep -qF "$source_runtime_repository" "$file" && [ "$source_runtime_repository" != "$runtime_repository" ]; then
changed=$((changed + 1))
Expand Down
45 changes: 4 additions & 41 deletions .github/workflows/draft-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,8 @@ permissions:
contents: read
pull-requests: write

env:
GH_TOKEN: ${{ github.token }}

jobs:
create-draft-pr:
name: Create
runs-on: ubuntu-slim
timeout-minutes: 10
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Check
id: check-pr
run: |
BRANCH="${{ github.ref_name }}"
EXISTING=$(gh pr list --limit 1 --base staging --head "$BRANCH" --state open --json number,title 2>/dev/null | jq 'length')
echo "existing=$EXISTING" >> "$GITHUB_OUTPUT"

- name: Create
if: steps.check-pr.outputs.existing == '0'
run: |
BRANCH="${{ github.ref_name }}"
gh pr create \
--base staging \
--head "$BRANCH" \
--draft \
--title "[WIP] $BRANCH" \
--body "Draft PR created automatically by CI.

This PR is a draft and should not be merged until CI passes and a reviewer (or the Daily Review agent) marks it ready.

**CI Status:** Pending — this workflow triggered on push to \`$BRANCH\`."

- name: Mark ready
if: steps.check-pr.outputs.existing == '0'
run: |
BRANCH="${{ github.ref_name }}"
PR_NUMBER=$(gh pr list --limit 1 --base staging --head "$BRANCH" --state open --json number 2>/dev/null | jq '.[0].number')
if [ -n "$PR_NUMBER" ]; then
gh pr ready "$PR_NUMBER"
fi
draft-pr:
name: Draft PR
uses: 0xPlayerOne/code-foundry/.github/workflows/reusable-draft-pr.yml@v0.19.0
secrets: inherit
80 changes: 4 additions & 76 deletions .github/workflows/release-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,80 +8,8 @@ permissions:
contents: read
pull-requests: write

env:
GH_TOKEN: ${{ github.token }}

jobs:
create-release-pr:
name: Create
runs-on: ubuntu-slim
timeout-minutes: 10
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Check
id: check-pr
run: |
set -euo pipefail
EXISTING=$(gh pr list \
--repo "$GITHUB_REPOSITORY" \
--limit 1 \
--base main \
--head staging \
--state open \
--json number | jq 'length')
echo "existing=$EXISTING" >> "$GITHUB_OUTPUT"

- name: Create
if: steps.check-pr.outputs.existing == '0'
run: |
DATE=$(date +%Y-%m-%d)
BODY_FILE="$RUNNER_TEMP/release-pr.md"
COMPARE_URL="repos/${GITHUB_REPOSITORY}/compare/main...staging"
COMPARE_FILE="$RUNNER_TEMP/release-compare.json"
gh api "$COMPARE_URL?per_page=100" > "$COMPARE_FILE"
TOTAL_COMMITS=$(jq -r '.total_commits // 0' "$COMPARE_FILE")
if [ "$TOTAL_COMMITS" -gt 100 ]; then
LAST_PAGE=$(( (TOTAL_COMMITS + 99) / 100 ))
gh api "$COMPARE_URL?per_page=100&page=$LAST_PAGE" > "$COMPARE_FILE"
fi
COMMITS=$(jq -r '.commits[] | "- \(.commit.message | split("\\n")[0]) (\(.sha[0:7]))"' "$COMPARE_FILE")
if [ -z "$COMMITS" ]; then
COMMITS='- No commits found since main.'
fi

if [ "$TOTAL_COMMITS" -eq 1 ]; then
CHANGE_LABEL=change
else
CHANGE_LABEL=changes
fi

cat > "$BODY_FILE" <<EOF
## Environment promotion

Promote the validated \`staging\` environment into \`main\`.
This is a deployment-promotion PR, not the version-release PR.

- **Source:** \`staging\`
- **Target:** \`main\`
- **Changes:** $TOTAL_COMMITS $CHANGE_LABEL
- **Created:** $DATE

### Commit summary

$COMMITS

### Validation

- Required CI, test, security, and CodeQL checks must pass before merge.
- Merge with **rebase** to preserve the linear Conventional Commit history.
- After merge, Release Please opens a separate versioned release PR with the changelog.
EOF

gh pr create \
--repo "$GITHUB_REPOSITORY" \
--base main \
--head staging \
--title "Promote staging -> main ($DATE)" \
--body-file "$BODY_FILE"
release-pr:
name: Release PR
uses: 0xPlayerOne/code-foundry/.github/workflows/reusable-release-pr.yml@v0.19.0
secrets: inherit
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ example, initializing from `NiftyLeague/template-repo` selects that fork's
runtime without extra flags. Use `--runtime-repository OWNER/REPO` (or
`REPO_FOUNDRY_RUNTIME_REPOSITORY`) only when you want to override it. The
selected repository is saved in `.github/template.yml` and rendered into the
small CI, Test, Security, and CodeQL wrappers automatically.
small CI, Test, Security, CodeQL, Draft PR, and Release PR wrappers
automatically.

Normal synchronization imports only the local hook, agent-facing command,
profile/release, initializer, doctor, ownership, and protection entrypoints.
Expand All @@ -62,9 +63,8 @@ release metadata, optional npm publication, provenance, and token/trusted
publishing fallback.

The promotion runtimes for Draft PR and Release PR are maintained in the same
versioned repository. They are introduced before their consumer wrappers move
to a release tag, avoiding a bootstrap cycle when a new runtime version is
being published.
versioned repository and are released before their short consumer callers move
to a new tag, avoiding a bootstrap cycle.

Initialization defaults to AGPL for new repositories. Synchronization defaults
to `--license preserve`, so an existing repository's license is never replaced
Expand Down