From d69ce1c388f6017e4b1f51104f6f5cb644c98f13 Mon Sep 17 00:00:00 2001 From: littlecodedragon <253116839+littlecodedragon@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:12:13 +0200 Subject: [PATCH] ci(upstream): track fork drift with check script and weekly workflow Add check-upstream.sh, generated status artifacts, merge guide, and a scheduled Forgejo job to refresh upstream sync visibility. Co-authored-by: Cursor --- .forgejo/workflows/upstream_status.yml | 100 +++++++++++++ README.md | 4 + UPSTREAM_STATUS.md | 48 ++++++ docs/upstream-status.json | 16 ++ docs/upstream-sync.md | 102 +++++++++++++ scripts/check-upstream.sh | 196 +++++++++++++++++++++++++ 6 files changed, 466 insertions(+) create mode 100644 .forgejo/workflows/upstream_status.yml create mode 100644 UPSTREAM_STATUS.md create mode 100644 docs/upstream-status.json create mode 100644 docs/upstream-sync.md create mode 100755 scripts/check-upstream.sh diff --git a/.forgejo/workflows/upstream_status.yml b/.forgejo/workflows/upstream_status.yml new file mode 100644 index 000000000..2cf8e3ca4 --- /dev/null +++ b/.forgejo/workflows/upstream_status.yml @@ -0,0 +1,100 @@ +name: Upstream sync status +# Lightweight job: fetch upstream from GitHub, write status files, optional issue. + +on: + schedule: + - cron: '0 6 * * 1' + workflow_dispatch: + +permissions: + contents: write + issues: write + +concurrency: + group: upstream-status + cancel-in-progress: true + +jobs: + check: + runs-on: ubuntu-latest + steps: + - name: Checkout and check upstream + shell: bash + env: + FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BEHIND_WARN: '10' + run: | + set -euo pipefail + rm -rf .git + git init . + origin_url="${GITHUB_SERVER_URL#https://}" + origin_url="${origin_url#http://}" + git remote add origin "https://x-access-token:${FORGEJO_TOKEN}@${origin_url}/${GITHUB_REPOSITORY}.git" + git -c http.sslVerify=false fetch --prune origin "${GITHUB_REF_NAME}" + git checkout --force FETCH_HEAD + git remote add upstream https://github.com/komikku-app/komikku.git + chmod +x scripts/check-upstream.sh + ./scripts/check-upstream.sh --write + behind="$(python3 -c 'import json; print(json.load(open("docs/upstream-status.json"))["behind"])')" + ahead="$(python3 -c 'import json; print(json.load(open("docs/upstream-status.json"))["ahead"])')" + status="$(python3 -c 'import json; print(json.load(open("docs/upstream-status.json"))["status"])')" + echo "BEHIND=$behind" >> "$GITHUB_ENV" + echo "AHEAD=$ahead" >> "$GITHUB_ENV" + echo "STATUS=$status" >> "$GITHUB_ENV" + + - name: Commit status files + shell: bash + env: + FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + git config user.name "forgejo-actions[bot]" + git config user.email "forgejo-actions[bot]@users.noreply.local" + git add UPSTREAM_STATUS.md docs/upstream-status.json + if git diff --staged --quiet; then + echo "No upstream status changes." + exit 0 + fi + git commit -m "chore(ci): update upstream sync status" + origin_url="${GITHUB_SERVER_URL#https://}" + origin_url="${origin_url#http://}" + git push "https://x-access-token:${FORGEJO_TOKEN}@${origin_url}/${GITHUB_REPOSITORY}.git" "HEAD:${GITHUB_REF_NAME}" + + - name: Open issue when far behind + if: env.STATUS == 'behind' + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + title="Upstream sync: ${BEHIND} commits behind komikku-app/komikku" + body=$(cat < diff --git a/UPSTREAM_STATUS.md b/UPSTREAM_STATUS.md new file mode 100644 index 000000000..a25c134d1 --- /dev/null +++ b/UPSTREAM_STATUS.md @@ -0,0 +1,48 @@ +# Upstream sync status + +> Auto-generated by [`scripts/check-upstream.sh`](scripts/check-upstream.sh). Last check: **2026-07-10 07:56 UTC**. + +| | | +|---|---| +| Status | 🔴 **Behind upstream** | +| Behind upstream | **73** commits on [`upstream/master`](https://github.com/komikku-app/komikku.git) | +| Ahead of upstream | **66** fork-only commits on `main` | +| Merge base | `bdf81596e9` | +| Fork HEAD | `b299a9ce81` | +| Upstream HEAD | `87a173929b` | + +## Action recommended + +This fork is **73 commits behind** [komikku-app/komikku](https://github.com/komikku-app/komikku.git). Consider merging upstream soon. + +See [docs/upstream-sync.md](docs/upstream-sync.md) for the manual sync procedure. + +## Recent upstream commits not in fork + +``` +87a173929b Adapt network implementation for TachiyomiX 1.6 (mihonapp/mihon#3248) +4ae732a17b fix(deps): Matching coroutines version +eb84ab8439 Ensure old extension store is removed if index url changes (mihonapp/mihon#3408) +5e809fefd4 Add auto migration support from legacy extension store index (mihonapp/mihon#3398) +1763d947df chore(sync): migrate sync preference keys (#1747) +ce6a0ea7fa fix(extension-store): Migrate to extension store during restore/sync legacy backup (#1746) +da57b3db07 Change the term "Obsolete" to "Orphaned" for extensions (mihonapp/mihon#3383) +da7ee11bb3 Change extension repo to extension store and add support for newer extension index format (#1744) +21c1b85796 Add informative error for unapproved MAL titles (mihonapp/mihon#3155) +0f556ea9b5 Address bundleOf deprecation (mihonapp/mihon#3073) +``` + +## Recent fork-only commits + +``` +b299a9ce81 docs(reading-eta): document unified limits, long chapters, and settings +f178a79195 feat(reading-eta): unify library and reader limits; make caps tunable +e0f4262407 ci(forgejo): verify signed APKs with unzip + aapt before upload +6316b85a09 fix(release): tolerate Forgejo null body/assets in release JSON +f91af6fc72 ci(forgejo): shorten release notes to since-last-tag + cap +c15d280cb4 feat(eta): cross-manga page-rate priors for reading time left +07019175d1 fix(eta): tame reading-time estimates (idle + cumulative history) +9ce3f0ba29 ci(forgejo): group release notes by prefix and fork vs merges +7fab10c8ef CI: build release JSON with jq --rawfile (avoid ARG_MAX on large bodies +e89f342881 CI: fix release step env — multiline COMMIT_LOGS broke act_runner +``` diff --git a/docs/upstream-status.json b/docs/upstream-status.json new file mode 100644 index 000000000..66c60738a --- /dev/null +++ b/docs/upstream-status.json @@ -0,0 +1,16 @@ +{ + "schemaVersion": 1, + "checked_at": "2026-07-10 07:56 UTC", + "status": "behind", + "status_label": "Behind upstream", + "behind": 73, + "ahead": 66, + "fork_branch": "main", + "upstream_remote": "upstream", + "upstream_branch": "master", + "upstream_url": "https://github.com/komikku-app/komikku.git", + "merge_base": "bdf81596e9040eee0c3a4c32d81a05e13049ec71", + "fork_head": "b299a9ce8163d1692526d72413c81dd7fd38ab47", + "upstream_head": "87a173929bd3355e4ad2b66b6025de49c9feeaf5", + "behind_warn": 10 +} \ No newline at end of file diff --git a/docs/upstream-sync.md b/docs/upstream-sync.md new file mode 100644 index 000000000..1123c5d6f --- /dev/null +++ b/docs/upstream-sync.md @@ -0,0 +1,102 @@ +# Syncing with upstream (komikku-app/komikku) + +This Forgejo fork tracks [komikku-app/komikku](https://github.com/komikku-app/komikku) on GitHub. + +| Remote | URL | Branch | +|--------|-----|--------| +| `origin` | Your Forgejo instance | `main` | +| `upstream` | `https://github.com/komikku-app/komikku.git` | `master` | + +Current divergence is recorded in [UPSTREAM_STATUS.md](../UPSTREAM_STATUS.md) (updated weekly by Forgejo Actions). + +## Quick check + +```sh +./scripts/check-upstream.sh +``` + +Write refreshed status files: + +```sh +./scripts/check-upstream.sh --write +``` + +JSON only: + +```sh +./scripts/check-upstream.sh --json +``` + +## One-time setup + +If `upstream` is missing: + +```sh +git remote add upstream https://github.com/komikku-app/komikku.git +git fetch upstream +``` + +## Merge upstream into the fork + +1. Commit or stash local work. +2. Update refs and inspect divergence: + + ```sh + git fetch upstream + git fetch origin + ./scripts/check-upstream.sh + git log --oneline main..upstream/master # incoming upstream commits + git log --oneline upstream/master..main # fork-only commits + ``` + +3. Merge (recommended for shared `main`): + + ```sh + git checkout main + git merge upstream/master + ``` + + Resolve conflicts, then: + + ```sh + git add -A + git commit # if merge was not auto-committed + ``` + +4. Push to Forgejo (never force-push `main` unless you intend to): + + ```sh + git push origin main + ``` + +## Expected conflict areas + +Merges often conflict where the fork diverged from upstream: + +- `.github/workflows/*.yml` — upstream GitHub Actions vs fork Forgejo release workflow +- `README.md` — fork-specific Forgejo / Obtainium notes +- `i18n-kmk/.../de/strings.xml` — parallel translation edits +- `data/src/main/sqldelight/tachiyomi/migrations/46.sqm` — schema migration numbering + +Keep fork-specific CI in `.forgejo/workflows/` and upstream CI in `.github/workflows/`; resolve workflow conflicts by keeping both sides where possible. + +## Rebase alternative + +For a linear history on a private branch (not `main`): + +```sh +git checkout -b sync/upstream-$(date +%Y%m%d) +git rebase upstream/master +``` + +Then test, merge the sync branch into `main`, and push. + +## Automation + +Workflow: [`.forgejo/workflows/upstream_status.yml`](../.forgejo/workflows/upstream_status.yml) + +- Runs every Monday 06:00 UTC and on manual dispatch +- Updates `UPSTREAM_STATUS.md` and `docs/upstream-status.json` +- Opens or updates a single `upstream-sync` issue when more than 10 commits behind + +On a private Forgejo host, dynamic shields.io badges cannot read your repo; use `UPSTREAM_STATUS.md` or the JSON file instead. diff --git a/scripts/check-upstream.sh b/scripts/check-upstream.sh new file mode 100755 index 000000000..a31544e3c --- /dev/null +++ b/scripts/check-upstream.sh @@ -0,0 +1,196 @@ +#!/usr/bin/env bash +# Compare this fork against upstream and optionally write UPSTREAM_STATUS.md. +set -euo pipefail + +UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}" +UPSTREAM_URL="${UPSTREAM_URL:-https://github.com/komikku-app/komikku.git}" +UPSTREAM_BRANCH="${UPSTREAM_BRANCH:-master}" +FORK_BRANCH="${FORK_BRANCH:-main}" +BEHIND_WARN="${BEHIND_WARN:-10}" +OUTPUT_MD="${OUTPUT_MD:-UPSTREAM_STATUS.md}" +OUTPUT_JSON="${OUTPUT_JSON:-docs/upstream-status.json}" +FETCH="${FETCH:-1}" +WRITE="${WRITE:-0}" + +usage() { + cat <<'EOF' +Usage: scripts/check-upstream.sh [options] + +Options: + --no-fetch Skip git fetch upstream + --write Write UPSTREAM_STATUS.md and docs/upstream-status.json + --json Print JSON status to stdout + -h, --help Show this help + +Environment: + UPSTREAM_REMOTE Git remote name (default: upstream) + UPSTREAM_BRANCH Upstream branch (default: master) + FORK_BRANCH Local fork branch (default: main) + BEHIND_WARN Warn when behind by this many commits (default: 10) +EOF +} + +print_json=0 +while [[ $# -gt 0 ]]; do + case "$1" in + --no-fetch) FETCH=0 ;; + --write) WRITE=1 ;; + --json) print_json=1 ;; + -h|--help) usage; exit 0 ;; + *) echo "Unknown option: $1" >&2; usage >&2; exit 2 ;; + esac + shift +done + +repo_root="$(git rev-parse --show-toplevel)" +cd "$repo_root" + +if ! git rev-parse --verify "$FORK_BRANCH" >/dev/null 2>&1; then + echo "Fork branch not found: $FORK_BRANCH" >&2 + exit 1 +fi + +if ! git remote get-url "$UPSTREAM_REMOTE" >/dev/null 2>&1; then + echo "Adding upstream remote: $UPSTREAM_REMOTE -> $UPSTREAM_URL" >&2 + git remote add "$UPSTREAM_REMOTE" "$UPSTREAM_URL" +fi + +if [[ "$FETCH" == "1" ]]; then + git fetch "$UPSTREAM_REMOTE" "$UPSTREAM_BRANCH" --prune +fi + +upstream_ref="$UPSTREAM_REMOTE/$UPSTREAM_BRANCH" +if ! git rev-parse --verify "$upstream_ref" >/dev/null 2>&1; then + echo "Upstream ref not found: $upstream_ref" >&2 + exit 1 +fi + +merge_base="$(git merge-base "$FORK_BRANCH" "$upstream_ref")" +behind="$(git rev-list --count "$FORK_BRANCH".."$upstream_ref")" +ahead="$(git rev-list --count "$upstream_ref".."$FORK_BRANCH")" +fork_head="$(git rev-parse --short "$FORK_BRANCH")" +upstream_head="$(git rev-parse --short "$upstream_ref")" +checked_at="$(date -u +"%Y-%m-%d %H:%M UTC")" + +if [[ "$behind" -eq 0 ]]; then + status="up_to_date" + status_label="Up to date" + status_emoji="✅" +elif [[ "$behind" -le "$BEHIND_WARN" ]]; then + status="slightly_behind" + status_label="Slightly behind" + status_emoji="🟡" +else + status="behind" + status_label="Behind upstream" + status_emoji="🔴" +fi + +upstream_sample="$(git log --oneline "$FORK_BRANCH".."$upstream_ref" -10)" +fork_sample="$(git log --oneline "$upstream_ref".."$FORK_BRANCH" -10)" + +if [[ "$print_json" == "1" ]]; then + python3 - < Auto-generated by [\`scripts/check-upstream.sh\`](scripts/check-upstream.sh). Last check: **$checked_at**. + +| | | +|---|---| +| Status | $status_emoji **$status_label** | +| Behind upstream | **$behind** commits on [\`$UPSTREAM_REMOTE/$UPSTREAM_BRANCH\`]($UPSTREAM_URL) | +| Ahead of upstream | **$ahead** fork-only commits on \`$FORK_BRANCH\` | +| Merge base | \`$(git rev-parse --short "$merge_base")\` | +| Fork HEAD | \`$fork_head\` | +| Upstream HEAD | \`$upstream_head\` | + +EOF + + if [[ "$behind" -gt 0 ]]; then + cat <"$OUTPUT_MD" + +echo "Wrote $OUTPUT_MD and $OUTPUT_JSON"