Skip to content

Commit 10dc5d7

Browse files
committed
fix(ADFA-6269): publish addons against CodeOnTheGo's plugin-api-latest release
Publish addons built every addon against the jars committed in libs/, which only change when someone runs Update libs. Vector-Search adopted EmbeddingBackend (#104) after the last refresh, so the release path failed with an unresolved reference while PR CI and local builds looked fine. The workflow now downloads plugin-api.jar and gradle-plugin.jar from the plugin-api-latest release, checks them against its checksums.txt, and takes PLUGIN_LIBS_REVISION from the release's target commit instead of parsing libs/ commit subjects. It fails if the release is republished mid-download, since CoGo recreates that tag on every run.
1 parent 4fdef5d commit 10dc5d7

2 files changed

Lines changed: 22 additions & 30 deletions

File tree

‎.github/workflows/publish-addons.yml‎

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,41 +51,33 @@ jobs:
5151
- name: Check names and metadata
5252
run: uv run --directory tools/addons addons --root "$GITHUB_WORKSPACE" check
5353

54-
- name: Resolve the libs revision
54+
- name: Fetch plugin-api-latest from CodeOnTheGo
5555
id: libs
5656
env:
5757
GH_TOKEN: ${{ github.token }}
58+
COGO_REPO: appdevforall/CodeOnTheGo
59+
COGO_RELEASE: plugin-api-latest
5860
run: |
59-
# This workflow builds the addons itself instead of going through
60-
# scripts/update-libs.sh, so nothing here knows which CodeOnTheGo commit
61-
# produced libs/. "Update libs from CodeOnTheGo" records it in the subject
62-
# of the commit it pushes, so the newest libs/ commit that names one wins.
63-
# Ordinary commits touch libs/ too (a missing jar, a pipeline change), and
64-
# keying on the single most recent one would let any of them block the whole
65-
# release path until someone dispatched Update libs, which also bumps the
66-
# toolchain as a side effect. Only "none of the recent ones names a sha"
67-
# fails the run: these are the artifacts the gallery serves, and an empty
68-
# export makes the builder omit the key and verify-provenance.sh skip its
69-
# check, so the pairing would be lost on a green run. The subject is
70-
# hand-writable, so the sha is validated rather than taken on trust, and
71-
# capped at the 12 characters update-libs.sh records, so the two forms of
72-
# one commit compare by prefix (subjects written before the --short=12
73-
# change carry 9).
74-
subjects="$(gh api "repos/${GITHUB_REPOSITORY}/commits?path=libs/&sha=${GITHUB_SHA}&per_page=50" --jq '.[].commit.message | split("\n")[0]')"
75-
revision=""
76-
while IFS= read -r subject; do
77-
candidate="${subject##*CodeOnTheGo@}"
78-
if [[ "$subject" == *CodeOnTheGo@* && "$candidate" =~ ^[0-9a-f]{7,40}$ ]]; then
79-
revision="${candidate:0:12}"
80-
break
81-
fi
82-
done <<< "$subjects"
83-
if [ -z "$revision" ]; then
84-
echo "No recent commit touching libs/ names a CodeOnTheGo revision." >&2
85-
echo "One of them must carry 'CodeOnTheGo@<sha>' in its subject." >&2
61+
set -euo pipefail
62+
target() { gh release view "$COGO_RELEASE" -R "$COGO_REPO" --json targetCommitish -q .targetCommitish; }
63+
before="$(target)"
64+
if ! [[ "$before" =~ ^[0-9a-f]{40}$ ]]; then
65+
echo "$COGO_RELEASE targets '$before', not a commit sha." >&2
66+
exit 1
67+
fi
68+
fetched="$(mktemp -d)"
69+
gh release download "$COGO_RELEASE" -R "$COGO_REPO" -D "$fetched" \
70+
-p plugin-api.jar -p gradle-plugin.jar -p checksums.txt
71+
( cd "$fetched" && sha256sum --check --strict checksums.txt )
72+
after="$(target)"
73+
if [ "$before" != "$after" ]; then
74+
echo "$COGO_RELEASE was republished during the download ($before -> $after). Re-run." >&2
8675
exit 1
8776
fi
77+
cp "$fetched/plugin-api.jar" "$fetched/gradle-plugin.jar" libs/
78+
revision="${before:0:12}"
8879
echo "revision=$revision" >> "$GITHUB_OUTPUT"
80+
echo "Building against $COGO_REPO@$revision ($COGO_RELEASE)." >> "$GITHUB_STEP_SUMMARY"
8981
9082
- name: Build, package, and stage
9183
id: stage

‎CLAUDE.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ The script clones CoGo into `.cache/CodeOnTheGo/` on first run, rebuilds both ja
4444

4545
There is also **one shared Gradle wrapper at the repo root** (`gradlew` + `gradle/wrapper/`). New plugins should use it — build them with `cd plugins/<Addon> && ../../gradlew assemblePlugin` rather than bundling a per-plugin `gradlew`/`gradle/wrapper/` copy. (`Flutter-Templates` and the five `AI-*` addons follow this; most older plugins still carry their own local wrapper and can be migrated opportunistically.)
4646

47-
An addon under `plugins/` references the shared jars as `../../libs/*.jar`. **Always use the repo-root `libs/` jars and the repo-root Gradle wrapper — never bundle per-plugin copies.** A plugin that ships its own `libs/plugin-api.jar` / `libs/gradle-plugin.jar` (e.g. copied from another plugin) can drift out of sync with the rest of the repo; point `build.gradle.kts` (`compileOnly`) and `settings.gradle.kts` (buildscript `classpath`) at `../../libs/*.jar` and delete any local `libs/`. The root `plugin-api.jar` already carries the full API surface (including `IdeTemplateService`/`CgtTemplateBuilder`), so newer sub-APIs do not justify a local copy. **A plugin folder is not standalone in isolation** — copy the root `libs/` along if you move one elsewhere. When CoGo's API changes, refresh via the script above or the **Update libs from CodeOnTheGo** GitHub Action (which commits the refreshed jars and cuts a release). Publishing addons is a separate workflow, **Publish addons**, which uploads to Cloudflare R2.
47+
An addon under `plugins/` references the shared jars as `../../libs/*.jar`. **Always use the repo-root `libs/` jars and the repo-root Gradle wrapper — never bundle per-plugin copies.** A plugin that ships its own `libs/plugin-api.jar` / `libs/gradle-plugin.jar` (e.g. copied from another plugin) can drift out of sync with the rest of the repo; point `build.gradle.kts` (`compileOnly`) and `settings.gradle.kts` (buildscript `classpath`) at `../../libs/*.jar` and delete any local `libs/`. The root `plugin-api.jar` already carries the full API surface (including `IdeTemplateService`/`CgtTemplateBuilder`), so newer sub-APIs do not justify a local copy. **A plugin folder is not standalone in isolation** — copy the root `libs/` along if you move one elsewhere. When CoGo's API changes, refresh via the script above or the **Update libs from CodeOnTheGo** GitHub Action (which commits the refreshed jars and cuts a release). Publishing addons is a separate workflow, **Publish addons**, which uploads to Cloudflare R2. It does **not** build against the committed `libs/`: it overwrites both jars with the assets of CoGo's [`plugin-api-latest`](https://github.com/appdevforall/CodeOnTheGo/releases/tag/plugin-api-latest) release (cut by hand with CoGo's **Release plugin-api** workflow, from CoGo `main`) after checking them against its `checksums.txt`. So a plugin that adopts a new API publishes once that API is in a `plugin-api-latest` release, whether or not `libs/` has been refreshed. PR CI and local builds still use the committed `libs/`, which **Update libs** fills from CoGo `stage`, so an API that is on `stage` but not yet released passes PR CI and fails **Publish addons**.
4848

4949
### Credentials: use the host's `KeystoreSecretStore`, never your own crypto
5050

@@ -118,7 +118,7 @@ unzip -p <plugin>/build/plugin/<name>.cgp assets/cgp-build.properties
118118

119119
`+dirty` has one systemic cause worth designing against: **a build-time download must land on a gitignored path.** A `downloadAssets` task that overwrites a git-tracked file (`ndk-installer` shipped a committed placeholder `ndk-cmake.tar.xz` until it was untracked) dirties the plugin directory on every build, so every artifact it ever produces records `+dirty` and no build of that plugin is traceable to a clean commit. Both download plugins now fetch onto ignored paths (`plugins/NDK-Installer/.gitignore`, `plugins/AI-Literacy-Course/.gitignore`); keep it that way when adding a new one.
120120

121-
`libs_revision` records which CoGo commit produced the jars the plugin was compiled against. The builder cannot see that checkout, so each build path exports `PLUGIN_LIBS_REVISION` first: `scripts/update-libs.sh` from the CodeOnTheGo checkout it just built, and **Publish addons** from the subject of the most recent commit touching `libs/` that names one (ordinary commits touch it too, so it scans back rather than reading only the newest). Compare two artifacts' `libs_revision` by prefix, not equality: subjects written before `--short=12` carry a 9-character sha. Note that under **Update libs from CodeOnTheGo** the plugin's own `revision` is the commit *before* the `chore: update libs` commit, because plugins are built before that commit is created; `libs_revision` is what pins the pairing.
121+
`libs_revision` records which CoGo commit produced the jars the plugin was compiled against. The builder cannot see that checkout, so each build path exports `PLUGIN_LIBS_REVISION` first: `scripts/update-libs.sh` from the CodeOnTheGo checkout it just built, and **Publish addons** from the target commit of the `plugin-api-latest` release it downloaded. Compare two artifacts' `libs_revision` by prefix, not equality: `.cgp`s published before that change took theirs from a commit subject, and some of those carry a 9-character sha. Note that under **Update libs from CodeOnTheGo** the plugin's own `revision` is the commit *before* the `chore: update libs` commit, because plugins are built before that commit is created; `libs_revision` is what pins the pairing.
122122

123123
`scripts/verify-provenance.sh` asserts the record after each `assemblePlugin`: a `.cgp` missing `assets/cgp-build.properties`, missing any required key, or disagreeing with the exported `PLUGIN_LIBS_REVISION` fails the run. `revision=unknown`, `+dirty` and `timestamp_source=wall-clock` warn instead — all three are legitimate off-CI (no `.git`, no `git` binary). All three workflows call it — **Build plugin artifacts** and **Update libs from CodeOnTheGo** through `scripts/update-libs.sh`, **Publish addons** directly, since it builds the addons itself. The last one is the one that matters most: those are the artifacts users install from the gallery.
124124

0 commit comments

Comments
 (0)