Skip to content

fix(ci): drop yarn cache until yarn.lock exists - #4

Open
Erpflow-dev wants to merge 15 commits into
mainfrom
fix/ci-yarn-cache
Open

Erpflow-dev wants to merge 15 commits into
mainfrom
fix/ci-yarn-cache

Conversation

@Erpflow-dev

Copy link
Copy Markdown
Owner

actions/setup-node@v4 with cache: yarn requires a yarn.lock file at repo root for cache key computation. We don't have one yet — the Vue project doesn't land until T-005 or T-068. setup-node errors out before any bench setup runs, killing both matrix legs in 20s and 41s respectively.

Disable the cache directive temporarily; setup-node still runs so node is available for bench asset hooks. Re-enable when yarn.lock exists at repo root.

Closes the post-T-001 main-is-red state.

Erpflow-dev and others added 15 commits May 1, 2026 11:11
actions/setup-node@v4 with cache: yarn requires a yarn.lock file at
repo root for cache key computation. We don't have one yet — the
Vue project doesn't land until T-005 or T-068. setup-node errors
out before any bench setup runs, killing both matrix legs in 20s
and 41s respectively.

Disable the cache directive temporarily; setup-node still runs so
node is available for bench asset hooks. Re-enable when yarn.lock
exists at repo root.

Closes the post-T-001 main-is-red state.
bench init fails on Python 3.11.15 with:
    File "<unknown>", line 93
        type ConfType = _dict[str, Any]
             ^^^^^^^^
    SyntaxError: invalid syntax

PEP 695 `type X = Y` statement requires Python 3.12+. The frappe
version-16 branch has adopted this syntax. Bumping the project's
Python floor across all configuration and dev-floor documentation
to match.

Changes (atomic — all describe the same upstream constraint):
- .github/workflows/ci.yml: lint and test jobs both use 3.12
  (kept in sync to avoid drift between linting and execution)
- pyproject.toml: requires-python = ">=3.12", target-version =
  "py312", dropped 3.11 PyPI classifier
- .pre-commit-config.yaml: pyupgrade --py312-plus to keep
  auto-rewrites consistent with the new floor
- CLAUDE.md, CLAUDE_CODE_SETUP.md, .claude/project.md: dev-floor
  statements updated from 3.11+ to 3.12+

Files NOT touched: README.md, SPEC.md, BUILD_TICKETS.md,
INTEGRATIONS.md, THEMES.md, DESIGN_SYSTEM.md, DECISIONS.md,
PROJECT_STATE.md, CHANGELOG.md — verified via grep, no Python
version references in any of them.

This unblocks PR #4's main-is-red state. Lint will continue to
pass; test legs should now get past bench init and either go
green or surface the next downstream failure.
Frappe v16.17.0 pins requires-python = ">=3.14,<3.15" — the previous
3.12 floor was wrong (PEP 695 was the wrong reason; the real constraint
is whatever frappe/version-16 declares). uv resolves frappe==16.17.0
and rejects the install with "the current Python version (3.12.13) does
not satisfy Python>=3.14,<3.15", failing both matrix legs at the
"Installing frappe" step of bench init.

Bump CI's setup-python to 3.14 (lint + test) and align pyproject's
requires-python and classifier. ruff target-version stays at py312 —
ruff 0.4.10 doesn't recognize py314 yet; that's a separate upgrade.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI was tracking unstable upstream HEAD on five apps (frappe, ERPNext,
Education, buzz, payments) via branch refs. Today this caused two
cascading breaks:

  1. frappe==16.17.0 (2026-04-28) raised requires-python to >=3.14,<3.15.
     Our Python 3.12 floor failed at "uv pip install -e frappe". Fixed
     in 615d53c by bumping Python to 3.14.

  2. With Python 3.14 working, the next layer surfaced: frappe v16's
     package.json declares engines.node ">=24". Node 20 failed
     "yarn install --check-files" inside bench init.

Pin all five apps to fixed refs so the next upstream constraint change
doesn't break us. Verified via gh api against frappe/version-16 history
that the Python 3.14 + Node 24 floors have existed since v16.0.0-rc.1
(2025-12-23) — these aren't recent tightenings, they're non-negotiable
for any v16 install. So 615d53c stays and we also bump Node to 24.

Pins:
  frappe        v16.16.0  cbde93c3  2026-04-21  (last release before
                                                 the 16.17.x release-storm)
  ERPNext       v16.16.0  4d5c665e  2026-04-28
  Education     v16.0.1   ab3794da  2026-04-07
  buzz          3d77434b  2026-04-20  (main HEAD; no tags exist)
  payments      3cebd942  2026-03-13  (develop HEAD; no tags exist)

All peer-app frappe-dependency declarations verified compatible with
frappe v16.16.0.

To bump these refs in the future: change deliberately in ci.yml, verify
CI before merge. Re-evaluate quarterly or when a new v16 feature is
needed.

This is the structural fix that supersedes the tactical patches in
this branch (yarn-cache-fix, Python 3.12-attempt, Python 3.14-bump).
Future v16 floor or peer-app changes won't break CI — only deliberate
pin updates will.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bench get-app clones with --origin upstream, so the post-install
reset must fetch from `upstream` not `origin`. Caught by CI on
f903e52: the v16.16.0 pin works, the reset step doesn't.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
GitHub's smart-HTTP protocol doesn't advertise arbitrary SHAs as
fetchable refs, so `git fetch --depth 1 upstream <sha>` fails with
"couldn't find remote ref <sha>". Fetch all available history
instead — small cost at these repo sizes, and resilient to repos
growing later.

Caught by CI on 0d9935f.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two T-001 issues blocking PR #4 from going green at install-app alumni:

1. buzz/__init__.py at our pinned SHA (3d77434b, 2026-04-20) calls
   `toggle_test_mode(True)` at import time when CI=true. GitHub Actions
   sets CI=true on every job, so bench's command discovery imports
   buzz and fails with `AttributeError: flags` (frappe.local.flags
   isn't initialized at that point).

   Bug introduced in buzz commit 16ef2563 (2026-02-02, "refactor: use
   frappe's toogle_test_mode for enabling testing"). Re-pin buzz to
   5118a99d (2026-02-01), the commit just before the refactor — that
   version gates on FRAPPE_IN_TEST (which we don't set) and uses a
   simpler frappe.in_test attribute set, so no side effects in bench
   command discovery. Verified buzz's pyproject.toml is identical
   between 5118a99d and 3d77434b — zero dependency drift from re-pin.

2. The "Link alumni app into bench" step mv's the source into apps/
   but doesn't pip install it. Then `bench install-app alumni` fails
   with `ModuleNotFoundError: No module named 'alumni'` because the
   alumni package isn't importable on bench's Python env.

   Add an explicit `./env/bin/pip install -e apps/alumni` step after
   the mv. Mirrors what `bench get-app <local-path>` does internally
   for local sources; alumni's only runtime dep is frappe>=16.0.0
   which is already installed.

Both issues caught by CI on 23ab8b2.

Upstream issue draft saved at docs/upstream-issues/buzz-toggle-test-mode.md
to file against BuildWithHussain/buzz after this PR merges.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…issue surfaced

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Continuation of yesterday's "drop --depth flag" fix (which was
correct for current-HEAD pins but insufficient for far-back pins).

The --depth 1 clone bench get-app does means the local pack only
contains HEAD. Plain `git fetch upstream` fetches new commits since
the shallow point but doesn't deepen — so any pin SHA outside the
initial pack stays unreachable. This bit us when buzz was re-pinned
from 3d77434b (current-HEAD, shallow-pack hit) to 5118a99d (3 months
upstream of HEAD, shallow-pack miss).

Fix: replace `git fetch upstream` with `git fetch --unshallow upstream`
on both buzz and payments. --unshallow deepens to full history
regardless of pin distance from HEAD. Verified locally:
  - buzz: 641 lifetime commits, full fetch ~1.5s
  - payments: 348 lifetime commits, full fetch ~1.3s

Also caught: the existing payments reset has been a silent no-op since
f903e52 because bench's --depth 1 clone of payments lands directly
on 3cebd942 (still HEAD of frappe/payments). Apply the deepening fix
to both apps now so payments doesn't break the next time payments
HEAD moves past our pin.

ERPNext and Education unchanged — they use tag-pinning via bench
get-app --branch <tag>, which lands directly on the tagged commit
with no fetch+reset dance involved.

Caught by CI on 26e8c20.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bench install-app reads frappe-bench/sites/apps.txt to validate the
app is known to the bench. The previous mv + pip install pattern
registered the Python package but never wrote apps.txt — only
bench get-app does that.

Replace the mv + pip install with `bench get-app ./apps/alumni`,
which handles both pip install and apps.txt registration (and any
future v16 bookkeeping that gets added). Mirrors what production
installs do via `bench get-app <url>`; the local-path form skips
the clone.

Caught by CI on 97fc374 (8th iteration of PR #4 hardening).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bench get-app with a local path expects the source to be outside
frappe-bench/apps/ and clones/copies it in. Pre-creating apps/alumni
via mv made bench prompt [y/N] for overwrite, which CI's closed
stdin can't answer.

Drop the manual mv. Run bench get-app from frappe-bench/ pointing
at ../apps/alumni — bench does the right thing.

Caught by CI on 995f934 (9th iteration of PR #4 hardening).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…orrow

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bench get-app passes the URL/path verbatim to `git clone`, but runs
it with cwd=<bench_root>/apps/ (bench/app.py:203-206). So a relative
path like ../apps/alumni from the step's working-directory frappe-bench/
resolves to frappe-bench/apps/../apps/alumni = frappe-bench/apps/alumni,
which doesn't exist — the source is at \$GITHUB_WORKSPACE/apps/alumni.

Pass an absolute path (\$GITHUB_WORKSPACE/apps/alumni) to bypass bench's
relative-resolution quirk. git clone of an absolute local path is a
well-trodden pattern and uses hardlinks (fastest local-clone path).

Caught by CI on 742bab3 (10th and final iteration of PR #4 hardening).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Frappe v16 declares pypika and gunicorn as git+https URL deps in
its own pyproject.toml. uv (per uv #1808, closed wontfix as
intentional design) refuses to follow URL deps in transitive
packages — only direct deps. Our `frappe>=16.0.0` declaration in
alumni/pyproject.toml triggered uv's transitive resolution of
frappe → pypika URL → exit code 167.

Every Frappe app in the ecosystem follows the convention: do NOT
declare frappe as a pip dep. Frappe is installed and managed by
bench during `bench init`. Apps that respect this convention
(buzz, payments, ERPNext, Education) install cleanly via bench
get-app; apps that re-declare frappe trip the uv policy.

Following the convention. Removing the declaration.

Caught by CI on e60e6e9 (11th and final iteration of PR #4
hardening). Investigation in this branch's history captures the
discovery: VPS install would hit the same issue (the v16 install
runbook hasn't yet reached an alumni install step, so the issue
was latent everywhere alumni installs).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant