Skip to content

Wire in agent skelton (#421) #284

Wire in agent skelton (#421)

Wire in agent skelton (#421) #284

name: Split app-studio provider
# Publishes providers/app-studio from this monorepo to the standalone,
# read-only mirror at faroshq/provider-app-studio, preserving git history.
#
# Uses splitsh-lite (https://github.com/splitsh/lite) which is deterministic:
# the same source always splits to the same commit sha1s, so pushes normally
# fast-forward. Runs on every push to main (mirrors the branch); workflow_dispatch
# is provided for the initial seed / manual re-sync. It also runs on PRs that touch the split
# surface, but those only validate (install + split) — the deploy-key and push
# steps are gated to non-PR events, so a PR never writes to the mirror.
#
# This mirror is SOURCE ONLY: it tracks `main`, and does NOT receive release
# tags. Provider images and charts are built+published from the monorepo by
# provider-release.yaml (on a `providers/app-studio/vX.Y.Z` tag), stamped with
# the provider's own version. Pushing the tag here too would make the mirror
# rebuild the same image/chart and collide on the published tag.
#
# Required secret: APP_STUDIO_DEPLOY_KEY
# An SSH private key whose public half is added as a *write* deploy key on
# faroshq/provider-app-studio. (A deploy key is scoped to one repo, so this is
# a distinct key from the other provider mirrors.)
on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- 'providers/app-studio/**'
- '.github/workflows/split-app-studio.yaml'
workflow_dispatch:
permissions:
contents: read
# Serialize splits per ref so two runs never race on the same push to the
# mirror. Do not cancel in-progress runs: a half-completed push is worse than
# waiting.
concurrency:
group: split-app-studio-${{ github.ref }}
cancel-in-progress: false
env:
PREFIX: providers/app-studio
TARGET_REPO: git@github.com:faroshq/provider-app-studio.git
TARGET_BRANCH: main
SPLITSH_VERSION: v1.0.1
jobs:
split:
runs-on: ubuntu-latest
steps:
- name: Checkout (full history)
uses: actions/checkout@v4
with:
# splitsh-lite needs the complete history to compute the split.
fetch-depth: 0
- name: Install splitsh-lite
run: |
set -euo pipefail
mkdir -p "$HOME/.local/bin"
# The v1.0.1 tarball stores the binary as ./splitsh-lite (leading
# ./), so GNU tar won't match a bare `splitsh-lite` member name.
curl -fsSL "https://github.com/splitsh/lite/releases/download/${SPLITSH_VERSION}/lite_linux_amd64.tar.gz" \
| tar -xz -C "$HOME/.local/bin" ./splitsh-lite
chmod +x "$HOME/.local/bin/splitsh-lite"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Set up SSH deploy key
if: github.event_name != 'pull_request'
run: |
set -euo pipefail
mkdir -p ~/.ssh
chmod 700 ~/.ssh
install -m 600 /dev/null ~/.ssh/id_split
echo "${{ secrets.APP_STUDIO_DEPLOY_KEY }}" > ~/.ssh/id_split
ssh-keyscan -t rsa,ecdsa,ed25519 github.com >> ~/.ssh/known_hosts 2>/dev/null
cat > ~/.ssh/config <<'EOF'
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_split
IdentitiesOnly yes
EOF
chmod 600 ~/.ssh/config
- name: Compute split
run: |
set -euo pipefail
# Deterministic split of the provider subtree. The resulting commit
# objects are written into the local object store, so they can be
# pushed directly by sha. Runs on every event (incl. PRs) so it
# validates the install + split end-to-end without publishing.
#
# --origin takes a git REF, not a raw commit hash; HEAD is the
# checked-out commit (the pushed tip, or the PR merge commit) and
# resolves cleanly where a bare ${GITHUB_SHA} does not. Capture via a
# file so splitsh-lite's own output isn't swallowed by $(...) on error.
splitsh-lite --prefix="${PREFIX}" --origin=HEAD | tee /tmp/split-sha
SHA="$(tail -n1 /tmp/split-sha)"
[ -n "${SHA}" ] || { echo "split produced no sha"; exit 1; }
echo "Split sha: ${SHA}"
echo "SPLIT_SHA=${SHA}" >> "$GITHUB_ENV"
- name: Push to mirror
if: github.event_name != 'pull_request'
run: |
set -euo pipefail
SHA="${SPLIT_SHA}"
git remote add mirror "${TARGET_REPO}"
echo "Publishing branch ${TARGET_BRANCH} -> ${TARGET_REPO}"
# --force keeps the mirror a faithful reflection even if monorepo
# history is ever rewritten. The mirror is read-only, so there are
# no downstream commits to clobber.
git push --force mirror "${SHA}:refs/heads/${TARGET_BRANCH}"