|
| 1 | +# CI Maintainer Notes |
| 2 | + |
| 3 | +Operational steps that a `gramps-project/addons-source` maintainer |
| 4 | +needs to handle once PR 820 (and the branch-neutral follow-up) lands. |
| 5 | +The pipeline is otherwise self-driving — this document is only about |
| 6 | +the rough edges. |
| 7 | + |
| 8 | +For day-to-day addon-release maintenance see [MAINTAINERS.md](../MAINTAINERS.md); |
| 9 | +for the contributor-facing summary of what a green CI check means on |
| 10 | +an unreleased branch see [CONTRIBUTING.md](../CONTRIBUTING.md#work-towards-a-merge). |
| 11 | + |
| 12 | +## Contents |
| 13 | + |
| 14 | +1. [One-time setup when the PR first merges](#one-time-setup-when-the-pr-first-merges) |
| 15 | +2. [Creating a new maintenance branch](#creating-a-new-maintenance-branch) |
| 16 | +3. [When a Gramps minor release lands on PyPI](#when-a-gramps-minor-release-lands-on-pypi) |
| 17 | +4. [Diagnostic log markers](#diagnostic-log-markers) |
| 18 | +5. [Optional future-proofing knobs](#optional-future-proofing-knobs) |
| 19 | + |
| 20 | +## One-time setup when the PR first merges |
| 21 | + |
| 22 | +### 1. Make the `gramps-ci` GHCR package public |
| 23 | + |
| 24 | +`docker-build.yml` pushes images to |
| 25 | +`ghcr.io/gramps-project/addons-source/gramps-ci:<suffix>` using the |
| 26 | +workflow's `GITHUB_TOKEN`. GHCR creates the package as **private** the |
| 27 | +first time. Same-repo CI keeps working (token covers own packages), |
| 28 | +but **fork PRs cannot pull the image** because their `GITHUB_TOKEN` |
| 29 | +has no read access to private packages in `gramps-project`. Fork-PR |
| 30 | +container jobs would fail at "Initialize containers" with an |
| 31 | +authentication error. |
| 32 | + |
| 33 | +Fix once, immediately after the first `Build Docker Images` run |
| 34 | +finishes: |
| 35 | + |
| 36 | +1. Go to <https://github.com/orgs/gramps-project/packages/container/addons-source%2Fgramps-ci/settings> |
| 37 | +2. Under "Danger Zone" → "Change visibility" → set to **Public** |
| 38 | + |
| 39 | +Every existing and future `gramps-ci:<suffix>` tag inherits public |
| 40 | +visibility from this single setting. |
| 41 | + |
| 42 | +### 2. Expect the first-push race on `maintenance/gramps60` |
| 43 | + |
| 44 | +The first push event after merge fires both workflows in parallel: |
| 45 | + |
| 46 | +- `Build Docker Images` builds and pushes `gramps-ci:gramps60` |
| 47 | + (~5 min cold). |
| 48 | +- `CI` runs `setup` (~2 s), then its container jobs try to pull the |
| 49 | + image. |
| 50 | + |
| 51 | +Because both start on the same push, the CI container jobs race the |
| 52 | +image push and may fail at "Initialize containers" the first time. |
| 53 | +This race only happens once per branch: |
| 54 | + |
| 55 | +1. Wait for `Build Docker Images` to complete. |
| 56 | +2. Open the failed CI run → click "Re-run failed jobs". |
| 57 | +3. Subsequent pushes find the image already in GHCR — no race. |
| 58 | + |
| 59 | +This is also explained in the header comment of `ci.yml`. |
| 60 | + |
| 61 | +## Creating a new maintenance branch |
| 62 | + |
| 63 | +When a new Gramps minor series goes into development and addons need |
| 64 | +a corresponding branch (e.g. `maintenance/gramps62` once 6.2 opens): |
| 65 | + |
| 66 | +``` |
| 67 | +git branch maintenance/gramps62 maintenance/gramps61 |
| 68 | +git push origin maintenance/gramps62 |
| 69 | +``` |
| 70 | + |
| 71 | +No workflow edits required. The workflows derive everything from |
| 72 | +`github.ref_name`. The first push fires the same race described |
| 73 | +above — re-run the failed CI jobs once `Build Docker Images` |
| 74 | +finishes. |
| 75 | + |
| 76 | +The setup job's regex (`gramps[0-9][0-9]`) requires a two-digit |
| 77 | +suffix. When Gramps 10.0 opens this regex needs updating in two |
| 78 | +places (`ci.yml` setup job and `docker-build.yml` params step). |
| 79 | + |
| 80 | +## When a Gramps minor release lands on PyPI |
| 81 | + |
| 82 | +The hybrid Dockerfile auto-detects PyPI availability: |
| 83 | + |
| 84 | +- `pip install "gramps==X.Y.*"` succeeds → image installs the tagged |
| 85 | + PyPI release (`::notice::` log line). |
| 86 | +- pip reports "No matching distribution found" → image falls back to a |
| 87 | + SHA-pinned `git clone` of `gramps-project/gramps@maintenance/grampsNN` |
| 88 | + at the SHA captured by `docker-build.yml`'s params step |
| 89 | + (`::warning::` log line). |
| 90 | + |
| 91 | +When `gramps==6.1.0` is finally published to PyPI, the next image |
| 92 | +rebuild on `maintenance/gramps61` silently switches from "git tip" to |
| 93 | +"PyPI release" — no maintainer action needed. |
| 94 | + |
| 95 | +To **immediately** rebuild against the new PyPI release without |
| 96 | +waiting for the next push: |
| 97 | + |
| 98 | +1. Open the `Build Docker Images` workflow in the Actions tab. |
| 99 | +2. "Run workflow" → select `maintenance/grampsNN` → Run. |
| 100 | + |
| 101 | +The `::notice::` line in the build log confirms the switch. |
| 102 | + |
| 103 | +## Diagnostic log markers |
| 104 | + |
| 105 | +When investigating a CI failure, the install-step output in |
| 106 | +`Build Docker Images` carries these annotations: |
| 107 | + |
| 108 | +| Annotation | Meaning | |
| 109 | +| --- | --- | |
| 110 | +| `::notice::installed gramps==X.Y.* from PyPI` | Released-path install. CI is testing against a tagged release. | |
| 111 | +| `::warning::no gramps==X.Y.* on PyPI; installing from gramps-project/gramps@maintenance/grampsNN at <sha>` | Unreleased-branch fallback. CI is testing against the upstream branch tip at `<sha>`. Visible to contributors via the CONTRIBUTING.md note. | |
| 112 | +| `::error::no gramps==X.Y.* on PyPI and GRAMPS_FALLBACK_SHA is unset` | `git ls-remote` in `docker-build.yml`'s params step returned no SHA for `maintenance/grampsNN` on `gramps-project/gramps`. The matching upstream branch is missing, or the addons-source branch is misnamed. | |
| 113 | +| `::error::pip install gramps failed (non-version reason)` | pip failed for a network/registry reason, not because the version is missing. Captured stderr is dumped after the line. The build does **not** fall back to git in this case — by design, so a transient PyPI hiccup cannot silently flip a released branch into "git tip" mode. | |
| 114 | + |
| 115 | +Other useful entry points: |
| 116 | + |
| 117 | +- `ci.yml` setup job log shows the derived `branch_suffix` and |
| 118 | + `ci_image`. A failure here means the branch name doesn't match |
| 119 | + `maintenance/gramps[0-9][0-9]`. |
| 120 | +- `docker-build.yml` params step log shows the captured |
| 121 | + `fallback_sha`. An empty value means upstream `gramps-project/gramps` |
| 122 | + has no matching maintenance branch (warning issued; image build will |
| 123 | + fail iff the fallback is needed). |
| 124 | + |
| 125 | +## Optional future-proofing knobs |
| 126 | + |
| 127 | +Not needed today; record here in case they ever come up. |
| 128 | + |
| 129 | +### Upstream gramps repo URL |
| 130 | + |
| 131 | +The Dockerfile hardcodes `https://github.com/gramps-project/gramps.git` |
| 132 | +as the fallback source. If the project ever reorgs or renames, this |
| 133 | +URL must change in one place (`.github/docker/gramps-ci/Dockerfile`). |
| 134 | +It could be parameterised as a build arg (`ARG GRAMPS_UPSTREAM_REPO`) |
| 135 | +with the current URL as default, but a hardcoded value keeps the |
| 136 | +Dockerfile simpler and a rename is a sufficiently large event that |
| 137 | +editing one string is not the bottleneck. |
| 138 | + |
| 139 | +### GHCR tag retention |
| 140 | + |
| 141 | +`docker-build.yml` pushes both a moving `gramps-ci:<suffix>` tag (e.g. |
| 142 | +`gramps60`) and a per-commit `gramps-ci:<suffix>-<short-sha>` tag. |
| 143 | +The moving tag is always overwritten; the SHA tags accumulate over |
| 144 | +time. Set a retention policy on the GHCR package settings page if |
| 145 | +the count becomes inconvenient — the moving tags are what CI consumes. |
0 commit comments