Skip to content

feat(ci): add upstream-sync workflow with deterministic conflict rules#25

Merged
bdruth merged 2 commits into
flexfrom
feat/upstream-sync-workflow
May 19, 2026
Merged

feat(ci): add upstream-sync workflow with deterministic conflict rules#25
bdruth merged 2 commits into
flexfrom
feat/upstream-sync-workflow

Conversation

@bdruth
Copy link
Copy Markdown

@bdruth bdruth commented May 19, 2026

Summary

PR B of the flex-CI-setup plan. Adds the upstream-sync GitHub Actions workflow and rewrites README_FLEXION.md's Option A to match what's shipped.

What this does

.github/workflows/upstream-sync.yml runs daily on a schedule and watches for new upstream v*.*.* release tags. On no-new-release days, it exits cleanly.

When it sees a new tag:

  1. Picks the target (latest upstream v*.*.*, or an explicit target_tag input on manual runs)
  2. Determines flex's current base via git describe --tags --abbrev=0 flex
  3. Exits clean if flex is already on the target (unless force: true)
  4. Refuses to sync backward unless force: true
  5. Creates upstream-sync/<target>-YYYYMMDD-HHMMSS, rebases onto the target tag with deterministic per-file rules:
    • Binary files (*.png, *.ico, *.wasm) → --ours
    • Lock files (package-lock.json, uv.lock) → --theirs
    • Flexion-unique paths (functions/, static/static/providers/, README_FLEXION.md) → --ours
    • Shared source files → conflict markers stay in the committed content; the human resolves them in the PR
  6. Opens a PR with a markdown conflict-resolution log — draft if manual review is needed, ready-for-review otherwise

Why a tag-driven schedule (vs HEAD-driven manual dispatch)

Upstream's main branch evolves with every commit, but flex tracks releases (v0.9.5, etc.) and the ECR tagging + CDK pinning already work this way. Syncing against main HEAD would create churn from every upstream commit; syncing against release tags matches how everything else is versioned.

Triggers

  • schedule:0 9 * * * (daily 09:00 UTC)
  • workflow_dispatch: — manual escape hatch with optional target_tag and force inputs

Concurrency

group: upstream-sync, cancel-in-progress: false — only one sync runs at a time, no in-flight cancellation.

Required prerequisites (already complete)

  • SYNC_PAT repo secret — fine-grained PAT, Contents/Pull-requests/Workflows write, SSO-authorized for flexion
  • flex is the default branch — workflows must register on the default branch to be dispatchable and scheduled

Test plan

After merge:

  • Manual dispatch (no inputs): trigger via Actions tab or gh workflow run upstream-sync.yml. Expect: workflow detects flex is already on v0.9.5, emits the "Up to date" notice, and exits.
  • First scheduled run at 09:00 UTC the day after merge. Same expected outcome until upstream cuts v0.9.6.
  • First real sync: when upstream tags v0.9.6+, the scheduled run opens a PR. Verify the conflict-resolution log is sensible and the rebase target is correct.

Files changed

  • .github/workflows/upstream-sync.yml — new
  • README_FLEXION.md — Option A rewritten for the schedule + tag model

bdruth added 2 commits May 18, 2026 22:27
PR B of the flex-CI-setup plan. Adds .github/workflows/upstream-sync.yml
and rewrites README_FLEXION.md Option A to match the actually-shipped
behavior (no Bedrock).

The workflow:
- workflow_dispatch only, inputs: dry_run (default true) and target_ref
  (default refs/heads/main → upstream/main)
- Detects drift via `git rev-list flex..upstream/main`
- On dry_run, reports drift count and exits
- On real run, creates upstream-sync/YYYYMMDD-HHMMSS, rebases, applies
  per-file rules:
    * *.png|*.ico|*.wasm → --ours
    * package-lock.json|uv.lock → --theirs
    * functions/**|static/static/providers/**|README_FLEXION.md → --ours
    * everything else → conflict markers stay in the committed content
- Accumulates a conflict-resolution log as markdown
- Opens a PR (draft if manual review is needed, ready otherwise) with
  the log + HITL checklist + list of files containing markers

Uses SYNC_PAT for both checkout and push because GITHUB_TOKEN can't push
branches that touch .github/workflows/.

No Bedrock or other LLM dependencies. Future upgrade path: insert an
LLM-assisted resolver as a step BEFORE the "leave markers" fallback,
without changing surrounding plumbing.
Replaces the "rebase against upstream/main HEAD" model with a daily
schedule that watches for new upstream v*.*.* release tags. On no-new-
release days, the workflow exits cleanly without opening a PR.

Why: upstream's main branch evolves with every commit, but flex tracks
releases (v0.9.5, etc.). Syncing against main HEAD would create churn
from every upstream commit; syncing against release tags matches how the
ECR tagging and CDK pinning already work.

Changes:
- Triggers: on.schedule (daily 09:00 UTC) + on.workflow_dispatch
- workflow_dispatch inputs replaced:
    - dry_run (boolean)              → removed
    - target_ref (string, default refs/heads/main) → removed
    - target_tag (string, optional)  → new; blank = auto-detect latest v*.*.*
    - force (boolean, default false) → new; bypass "already on target" check
- Detection:
    - target tag: explicit input, or `git tag -l 'v[0-9]*.[0-9]*.[0-9]*'
      --sort=-version:refname | head -n 1` (pre-releases excluded)
    - current base: `git describe --tags --abbrev=0 flex`
- Safety: refuses to sync backward (target older than base) without force
- Concurrency group "upstream-sync", no cancel-in-progress
- Throwaway branch name now includes the target tag for traceability
- PR body now references "Publish flex image to ECR" as the followup step

Also rewrites README_FLEXION.md Option A to describe the new model.
Copy link
Copy Markdown
Author

@bdruth bdruth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed

@bdruth bdruth merged commit 0bb2a3d into flex May 19, 2026
@bdruth bdruth deleted the feat/upstream-sync-workflow branch May 19, 2026 03:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant