Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/check-toolchain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ on:

permissions:
contents: read
# the libs/ guard below reads the pull request's changed file list
pull-requests: read

jobs:
check-toolchain:
Expand All @@ -29,6 +31,30 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

# libs/ holds build outputs, not source. Only the "Update libs from
# CodeOnTheGo" workflow may change them. It builds the jars on JDK 17,
# which is the JDK every runner here uses, so what it commits always
# loads. A laptop on JDK 21 emits class file version 65 instead, and a
# JDK 17 runner reads only up to 61 -- that is what broke "Publish
# addons" after #87 shipped hand-built jars. That workflow pushes
# straight to main with an admin PAT and bypasses the main ruleset, so
# this check never sees it.
- name: Refuse hand-built libs/ jars
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ github.token }}
PR: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
changed="$(gh api --paginate \
"repos/${GITHUB_REPOSITORY}/pulls/${PR}/files" \
-q '.[].filename' | grep '^libs/' || true)"
if [ -n "$changed" ]; then
printf '%s\n' "$changed"
echo "::error::A pull request must not change libs/. Run the 'Update libs from CodeOnTheGo' workflow instead -- it builds the jars on the JDK the runners use."
exit 1
fi

- name: Check toolchain versions
run: ./scripts/check-toolchain.sh

Expand Down
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Build every plugin from scratch (after rebuilding libs):

The script clones CoGo into `.cache/CodeOnTheGo/` on first run, rebuilds both jars, copies them into `libs/`, then runs `assemblePlugin` for every example. It auto-detects examples by scanning for `build.gradle.kts` files that apply `com.itsaky.androidide.plugins.build`.

**Never commit the jars this script writes.** Run it locally only to test a CoGo change before it lands; throw the `libs/` diff away afterwards (`git restore libs/`). `libs/` on `main` may only be changed by the **Update libs from CodeOnTheGo** workflow, which builds on JDK 17 — the JDK every runner and every other workflow here uses. A laptop on JDK 21 writes class file version 65 into `gradle-plugin.jar`; a JDK 17 runner reads only up to 61, so `assemblePlugin` dies with `UnsupportedClassVersionError` in CI while it still works on the laptop that produced it. PR #87 shipped such a jar and broke **Publish addons**. `Check toolchain` now fails any pull request that touches `libs/`.

`local.properties` must contain `sdk.dir=...`. The committed `local.properties` at the repo root is harmless leftover; each plugin needs its own.

## Git workflow
Expand All @@ -44,7 +46,7 @@ The script clones CoGo into `.cache/CodeOnTheGo/` on first run, rebuilds both ja

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-template` follows this; most older plugins still carry their own local wrapper and can be migrated opportunistically.)

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.
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 with the **Update libs from CodeOnTheGo** GitHub Action (which commits the refreshed jars and cuts a release) — never by committing what `scripts/update-libs.sh` writes on your own machine, for the reason given above. Publishing addons is a separate workflow, **Publish addons**, which uploads to Cloudflare R2.

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

Expand Down
1 change: 1 addition & 0 deletions libs/GUARD_TEST.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scratch
Loading