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
80 changes: 80 additions & 0 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Boatstack-owned control plane.
name: Publish verified Boatstack release

on:
workflow_run:
workflows: ["Verify Boatstack distribution"]
types: [completed]

permissions:
contents: read

concurrency:
group: auto-release-boatstack
cancel-in-progress: false

jobs:
release:
if: >-
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main'
runs-on: ubuntu-latest
steps:
- name: Create repository automation token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ vars.BOATSTACK_APP_CLIENT_ID }}
private-key: ${{ secrets.BOATSTACK_APP_PRIVATE_KEY }}
owner: operatorstack
repositories: boatstack
permission-contents: write
- uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- uses: actions/setup-go@v5
with:
go-version-file: boatstack/go.mod
cache-dependency-path: boatstack/go.mod
- name: Detect release-bearing projection
id: classify
shell: bash
run: |
if [[ ! -f boatstack/release.go ]]; then
echo "The release classifier is not projected yet; no tag will be created."
echo "release_required=false" >> "$GITHUB_OUTPUT"
exit 0
fi
latest_tag="$(git describe --tags --abbrev=0 --match 'v[0-9]*' 2>/dev/null || true)"
if [[ -z "$latest_tag" ]]; then
echo "BLOCKED: automatic patch releases require an existing stable tag." >&2
exit 1
fi
classification="$(cd boatstack && go run ./cmd/boatstack-helper \
release-classify --repo .. --base "$latest_tag" --head HEAD)"
printf '%s\n' "$classification" >> "$GITHUB_OUTPUT"
echo "latest_tag=$latest_tag" >> "$GITHUB_OUTPUT"
- name: Create next verified patch tag
if: steps.classify.outputs.release_required == 'true'
env:
APP_SLUG: ${{ steps.app-token.outputs.app-slug }}
LATEST_TAG: ${{ steps.classify.outputs.latest_tag }}
shell: bash
run: |
next_tag="$(cd boatstack && go run ./cmd/boatstack-helper \
next-patch --version "$LATEST_TAG")"
if git rev-parse --verify --quiet "refs/tags/$next_tag"; then
echo "BLOCKED: tag already exists: $next_tag" >&2
exit 1
fi
git config user.name "${APP_SLUG}[bot]"
git config user.email "${APP_SLUG}[bot]@users.noreply.github.com"
git tag -a "$next_tag" -m "Boatstack $next_tag"
git push origin "$next_tag"
echo "Published verified release tag $next_tag."
- name: Report documentation-only sync
if: steps.classify.outputs.release_required != 'true'
run: echo "Boatstack content is current; this merge does not require new binaries."
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,43 @@ jobs:
$errors | ForEach-Object { Write-Error $_ }
exit 1
}

auto-merge-sync:
if: >-
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository &&
startsWith(github.head_ref, 'sync/intelligence-flow-')
needs: test
runs-on: ubuntu-latest
steps:
- name: Create repository automation token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ vars.BOATSTACK_APP_CLIENT_ID }}
private-key: ${{ secrets.BOATSTACK_APP_PRIVATE_KEY }}
owner: operatorstack
repositories: boatstack
permission-contents: write
permission-pull-requests: write
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Verify generated projection provenance
env:
APP_SLUG: ${{ steps.app-token.outputs.app-slug }}
HEAD_BRANCH: ${{ github.head_ref }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
shell: bash
run: |
source_repo="$(jq -r '.source.repo' UPSTREAM.json)"
source_commit="$(jq -r '.source.commit' UPSTREAM.json)"
short="${source_commit:0:12}"
[[ "$PR_AUTHOR" == "${APP_SLUG}[bot]" ]]
[[ "$source_repo" == "operatorstack/intelligence-flow" ]]
[[ "$HEAD_BRANCH" == "sync/intelligence-flow-$short" ]]
- name: Merge verified generated PR
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: gh pr merge "$PR_URL" --squash
42 changes: 36 additions & 6 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ on:
schedule:
- cron: "17 */6 * * *"
workflow_dispatch:
inputs:
source_commit:
description: Exact Intelligence Flow commit to project (defaults to main)
required: false
type: string

permissions:
contents: write
Expand All @@ -18,29 +23,53 @@ jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Create repository automation token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ vars.BOATSTACK_APP_CLIENT_ID }}
private-key: ${{ secrets.BOATSTACK_APP_PRIVATE_KEY }}
owner: operatorstack
repositories: |
intelligence-flow
boatstack
permission-contents: write
permission-pull-requests: write
- name: Check out Boatstack
uses: actions/checkout@v4
with:
path: boatstack-repo
token: ${{ steps.app-token.outputs.token }}
- name: Check out Intelligence Flow
uses: actions/checkout@v4
with:
repository: operatorstack/intelligence-flow
ref: main
ref: ${{ inputs.source_commit || 'main' }}
fetch-depth: 0
path: intelligence-flow
token: ${{ steps.app-token.outputs.token }}
- name: Generate projection
id: generate
shell: bash
run: |
source_commit="$(git -C intelligence-flow log -1 --format=%H -- examples/12-product-engineering-loop)"
current_commit="$(jq -r '.source.commit // empty' boatstack-repo/UPSTREAM.json)"
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 "stale=true" >> "$GITHUB_OUTPUT"
exit 0
fi
python3 intelligence-flow/examples/12-product-engineering-loop/scripts/build_boatstack.py \
--repo boatstack-repo \
--source-commit "$source_commit" \
--write
echo "source_commit=$source_commit" >> "$GITHUB_OUTPUT"
echo "stale=false" >> "$GITHUB_OUTPUT"
- name: Open generated pull request
if: steps.generate.outputs.stale != 'true'
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
SOURCE_COMMIT: ${{ steps.generate.outputs.source_commit }}
shell: bash
run: |
Expand Down Expand Up @@ -92,13 +121,14 @@ jobs:
echo "Upstream PR already open: $existing"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
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 $short"
git push --set-upstream origin "$branch"
gh pr create \
pr_url="$(gh pr create \
--base main \
--head "$branch" \
--title "Sync Boatstack from Intelligence Flow $short" \
--body-file "$body_file"
--body-file "$body_file")"
echo "Opened generated PR: $pr_url"
Loading