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
87 changes: 42 additions & 45 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Generated from operatorstack/intelligence-flow.
# Generated by labkit (python -m labkit gen). Do not edit by hand.
# Edit labs/<lab>/publish.config.json and regenerate; drift fails `labkit doctor`.
# Install into operatorstack/boatstack at .github/workflows/sync-upstream.yml (bootstrap step).
name: Sync from Intelligence Flow

on:
schedule:
- cron: "17 */6 * * *"
- cron: "2 */6 * * *"
workflow_dispatch:
inputs:
source_commit:
Expand All @@ -23,7 +25,7 @@ jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Create repository automation token
- name: Create publisher token
id: app-token
uses: actions/create-github-app-token@v3
with:
Expand All @@ -38,7 +40,7 @@ jobs:
- name: Check out Boatstack
uses: actions/checkout@v4
with:
path: boatstack-repo
path: public-repo
token: ${{ steps.app-token.outputs.token }}
- name: Check out Intelligence Flow
uses: actions/checkout@v4
Expand All @@ -48,20 +50,28 @@ jobs:
fetch-depth: 0
path: intelligence-flow
token: ${{ steps.app-token.outputs.token }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install labkit
shell: bash
run: python3 -m pip install --quiet ./intelligence-flow/labkit
- name: Generate projection
id: generate
shell: bash
run: |
source_commit="$(git -C intelligence-flow log -1 --format=%H -- labs/12-product-engineering-loop)"
current_commit="$(jq -r '.source.commit // empty' boatstack-repo/UPSTREAM.json)"
current_commit="$(jq -r '.source.commit // empty' public-repo/UPSTREAM.json 2>/dev/null || echo '')"
if [[ -n "$current_commit" ]] &&
! git -C intelligence-flow merge-base --is-ancestor "$current_commit" "$source_commit"; then
echo "Ignoring stale projection request $source_commit; Boatstack already records $current_commit."
echo "Ignoring stale request; Boatstack already records $current_commit."
echo "stale=true" >> "$GITHUB_OUTPUT"
exit 0
fi
python3 intelligence-flow/labs/12-product-engineering-loop/scripts/build_boatstack.py \
--repo boatstack-repo \
python3 -m labkit project \
--config intelligence-flow/labs/12-product-engineering-loop/publish.config.json \
--repo public-repo \
--source-commit "$source_commit" \
--write
echo "source_commit=$source_commit" >> "$GITHUB_OUTPUT"
Expand All @@ -73,62 +83,49 @@ jobs:
SOURCE_COMMIT: ${{ steps.generate.outputs.source_commit }}
shell: bash
run: |
cd boatstack-repo
cd public-repo
if [[ -z "$(git status --porcelain)" ]]; then
echo "Boatstack already matches Intelligence Flow."
exit 0
fi
git add -A
rewritten_notes=()
while IFS= read -r note; do
rewritten_notes+=("$note")
done < <(git diff --cached --name-only --diff-filter=MD --no-renames -- \
'release-notes/*.md')
if (( ${#rewritten_notes[@]} > 0 )); then
rewritten=()
while IFS= read -r note; do rewritten+=("$note"); done < <(
git diff --cached --name-only --diff-filter=MD --no-renames -- 'release-notes/*.md')
if (( ${#rewritten[@]} > 0 )); then
echo "BLOCKED: Boatstack release notes are append-only:" >&2
printf ' %s\n' "${rewritten_notes[@]}" >&2
printf ' %s\n' "${rewritten[@]}" >&2
exit 1
fi
added_notes=()
while IFS= read -r note; do
added_notes+=("$note")
done < <(git diff --cached --name-only --diff-filter=A --no-renames -- \
'release-notes/*.md' | LC_ALL=C sort)
if (( ${#added_notes[@]} == 0 )); then
echo "BLOCKED: projected Boatstack changes require a release message." >&2
added=()
while IFS= read -r note; do added+=("$note"); done < <(
git diff --cached --name-only --diff-filter=A --no-renames -- 'release-notes/*.md' | LC_ALL=C sort)
if (( ${#added[@]} == 0 )); then
echo "BLOCKED: projected changes require a release note in release-notes/." >&2
exit 1
fi
body_file="$(mktemp)"
{
echo "## What this sync releases"
echo
for note in "${added_notes[@]}"; do
cat "$note"
echo
done
echo "<details>"
echo "<summary>Projection provenance</summary>"
echo
echo "## What this sync releases"; echo
for note in "${added[@]}"; do cat "$note"; echo; done
echo "<details><summary>Projection provenance</summary>"; echo
echo "Generated from \`operatorstack/intelligence-flow@$SOURCE_COMMIT\`."
echo "Review provenance, tests, examples, and context-cost changes before merging."
echo
echo "Review provenance, tests, and examples before merging."; echo
echo "</details>"
} > "$body_file"
short="${SOURCE_COMMIT:0:12}"
branch="sync/intelligence-flow-$short"
existing="$(gh pr list --head "$branch" --state open --json url --jq '.[0].url')"
if [[ -n "$existing" ]]; then
echo "Upstream PR already open: $existing"
exit 0
fi
git config user.name "${{ steps.app-token.outputs.app-slug }}[bot]"
git config user.email "${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com"
git switch -c "$branch"
git commit -m "Sync Boatstack from Intelligence Flow Labs @ $short"
git push --set-upstream origin "$branch"
pr_url="$(gh pr create \
--base main \
--head "$branch" \
--title "Sync Boatstack from Intelligence Flow Labs @ $short" \
--body-file "$body_file")"
echo "Opened generated PR: $pr_url"
git push --force --set-upstream origin "$branch"
if [[ -z "$existing" ]]; then
pr_url="$(gh pr create --base main --head "$branch" \
--title "Sync Boatstack from Intelligence Flow Labs @ $short" \
--body-file "$body_file")"
echo "Opened generated PR: $pr_url"
else
echo "Updated existing PR: $existing"
fi
Loading