Repository navigation
Sync screenpipe fork #24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Sync screenpipe fork | |
| # Keeps AnkushMalaker/screenpipe's two custom branches rebased, in order: | |
| # | |
| # custom/linux-timeline-stability -> upstream screenpipe/screenpipe main | |
| # chronicle -> custom/linux-timeline-stability | |
| # | |
| # `chronicle` is the branch Chronicle actually consumes (it adds | |
| # /search?dedupe and /app-runs on top of the base branch's capture fixes), so | |
| # syncing only the base would leave the consumed branch to rot behind upstream. | |
| # | |
| # The two run as one matrix with max-parallel 1 so the stacked branch rebases | |
| # onto a base that was already pushed. If that ordering ever slipped, the | |
| # stacked rebase would simply find nothing to do and the next run would catch | |
| # up — it self-heals rather than corrupting anything. | |
| # | |
| # This lives in chronicle rather than in the fork itself for two reasons: | |
| # `schedule` only fires from a repo's default branch, so hosting it in the fork | |
| # would permanently diverge that fork's main from upstream; and GitHub disables | |
| # scheduled workflows in forked repositories, which would stop the sync | |
| # silently. | |
| on: | |
| schedule: | |
| # 04:00 UTC daily — well clear of the local build window. | |
| - cron: "0 4 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| push: | |
| # Compared against the string 'false' as well as boolean false at the | |
| # use site: `gh workflow run -f push=false` sends the *string* "false", | |
| # and a non-empty string is truthy in GitHub expressions, so a naive | |
| # `if: inputs.push` would force-push when asked not to. Use -F (capital) | |
| # to send a real boolean, but the guard does not rely on that. | |
| description: "Push the rebased branch to the fork" | |
| type: boolean | |
| default: true | |
| permissions: | |
| contents: read | |
| issues: write | |
| env: | |
| FORK: AnkushMalaker/screenpipe | |
| UPSTREAM: https://github.com/screenpipe/screenpipe | |
| jobs: | |
| rebase: | |
| name: Rebase ${{ matrix.branch }} onto ${{ matrix.onto }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| # Sequential, base first: `chronicle` is stacked on the base branch and | |
| # must rebase onto the version this run just pushed. | |
| max-parallel: 1 | |
| # The stacked branch is still worth attempting if the base conflicted — | |
| # it just rebases onto the unchanged base and no-ops. | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - branch: custom/linux-timeline-stability | |
| onto: upstream/main | |
| - branch: chronicle | |
| onto: origin/custom/linux-timeline-stability | |
| steps: | |
| - name: Check out the fork's custom branch | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ env.FORK }} | |
| ref: ${{ matrix.branch }} | |
| # Full history: a rebase needs the merge base with its target, which a | |
| # shallow clone does not have. | |
| fetch-depth: 0 | |
| token: ${{ secrets.SCREENPIPE_FORK_TOKEN }} | |
| persist-credentials: true | |
| - name: Fetch the rebase target | |
| run: | | |
| git remote add upstream "$UPSTREAM" | |
| # Only main: upstream carries hundreds of agent/* branches. | |
| git fetch --no-tags upstream main | |
| # The stacked branch rebases onto a sibling branch of the fork, which | |
| # a single-ref checkout does not bring down. | |
| git fetch --no-tags origin custom/linux-timeline-stability | |
| - name: Report divergence | |
| id: diverge | |
| env: | |
| ONTO: ${{ matrix.onto }} | |
| run: | | |
| base=$(git merge-base HEAD "$ONTO") | |
| behind=$(git rev-list --count "$base".."$ONTO") | |
| ours=$(git rev-list --count "$base"..HEAD) | |
| echo "behind=$behind" >>"$GITHUB_OUTPUT" | |
| echo "ours=$ours" >>"$GITHUB_OUTPUT" | |
| echo "$behind new commit(s) on $ONTO; $ours local commit(s) on top" | |
| - name: Rebase | |
| id: rebase | |
| if: steps.diverge.outputs.behind != '0' | |
| env: | |
| ONTO: ${{ matrix.onto }} | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| if git rebase "$ONTO"; then | |
| echo "clean=true" >>"$GITHUB_OUTPUT" | |
| else | |
| git rebase --abort || true | |
| echo "clean=false" >>"$GITHUB_OUTPUT" | |
| echo "::warning::rebase hit conflicts; leaving the fork untouched" | |
| fi | |
| - name: Push rebased branch | |
| if: | | |
| steps.rebase.outputs.clean == 'true' && | |
| (github.event_name == 'schedule' || | |
| (inputs.push && inputs.push != 'false')) | |
| env: | |
| BRANCH: ${{ matrix.branch }} | |
| run: | | |
| # --force-with-lease, never plain --force: the rebase rewrote history, | |
| # but this still refuses if the branch moved since checkout (e.g. a | |
| # local push landed while this job was running). | |
| git push --force-with-lease origin "HEAD:$BRANCH" | |
| - name: Open an issue on conflict | |
| if: steps.rebase.outputs.clean == 'false' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| BEHIND: ${{ steps.diverge.outputs.behind }} | |
| BRANCH: ${{ matrix.branch }} | |
| ONTO: ${{ matrix.onto }} | |
| run: | | |
| title="screenpipe fork: $BRANCH needs manual conflict resolution" | |
| # Reuse one open issue rather than filing a new one every night. | |
| existing=$(gh issue list --repo "$GITHUB_REPOSITORY" \ | |
| --state open --search "$title in:title" --json number --jq '.[0].number') | |
| body=$(printf '%s\n' \ | |
| "\`$BRANCH\` no longer rebases cleanly onto \`$ONTO\` ($BEHIND commits behind)." \ | |
| "" \ | |
| "The fork was left untouched. Resolve it locally:" \ | |
| "" \ | |
| '```' \ | |
| "cd untracked/screenpipe && SYNC_BRANCH=$BRANCH ./sync-fork.sh" \ | |
| "# fix conflicts, then: git add <files> && git rebase --continue" \ | |
| "SYNC_BRANCH=$BRANCH ./sync-fork.sh --push" \ | |
| '```' \ | |
| "" \ | |
| "Run: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID") | |
| if [ -n "$existing" ]; then | |
| gh issue comment "$existing" --repo "$GITHUB_REPOSITORY" --body "$body" | |
| else | |
| gh issue create --repo "$GITHUB_REPOSITORY" --title "$title" --body "$body" | |
| fi |