Skip to content

ci(release): drop emulated arm64 build and fix the inert layer cache - #4

Merged
patrickdundas merged 1 commit into
mainfrom
ci/faster-release
Jul 29, 2026
Merged

ci(release): drop emulated arm64 build and fix the inert layer cache#4
patrickdundas merged 1 commit into
mainfrom
ci/faster-release

Conversation

@patrickdundas

Copy link
Copy Markdown
Owner

The Docker build step was 989s of an 18m25s release run; every other step totalled ~90s. Two causes.

arm64 was emulated for nobody

The only deploy target for this fork is the yams VM, which is x86_64. Building linux/arm64 under QEMU roughly doubled the work to produce an image nothing pulls, and emulated builds run several times slower than native. Dropped to linux/amd64 and removed the now-pointless QEMU setup step. Both trivially restorable if an ARM host ever needs this.

The layer cache never hit — upstream bug

cache-to:   scope=buildx-<version>        # writes here
cache-from: scope=buildx-amd64, buildx-arm64   # reads here

The scopes could never match, so no release read a cache entry another release had written. Every build was cold, and each left behind a version-scoped entry nothing would ever read again. Now reads and writes the same scope.

The cache bug affects upstream's own releases too and is worth offering back. The arm64 removal is fork-specific and should not be.

🤖 Generated with Claude Code

The Docker build step was 989s of an 18m25s release run. Every other step in
the job totalled about 90s, so it is the only thing worth optimising.

Two causes, both addressed here.

arm64 was emulated for nobody. The only deploy target for this fork is the
yams VM, which is x86_64. Building linux/arm64 under QEMU roughly doubled the
work to produce an image that nothing pulls, and emulated builds run several
times slower than native. Dropped to linux/amd64 and removed the now-pointless
QEMU setup step. Both are easy to restore if an ARM host ever needs this.

The GitHub Actions layer cache never hit. cache-to wrote to scope
`buildx-<version>` while cache-from read `buildx-amd64` and `buildx-arm64`, so
the scopes could never match: no release read a cache entry that another
release had written. Every build was cold, and each one left behind a
version-scoped entry that nothing would ever read again. Read and write the
same scope now.

The cache bug is upstream's and affects their releases too - worth offering
back. The arm64 removal is fork-specific and should not be.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Knip Code Analysis

Found 8 total issues

Category Count
Unused Dependencies 1
Unused Dev Dependencies 3
Unused Exports 4
View details

Run pnpm knip locally to see the full report.

Use pnpm knip:filter pattern to filter results by file path.


Use /** @public */ JSDoc tags to mark intentionally exported symbols.

@github-actions

Copy link
Copy Markdown

🚫 Security audit failed

Critical Failures

Check File Details
External fetch calls have timeouts src/lib/adapters/btn.ts:69 fetch() call without a timeout signal — add signal: AbortSignal.timeout(ms)

Warnings

Check File Details
No swallowed errors in catch blocks src/lib/adapters/iptorrents.ts:108 catch block swallows error without logging or re-throwing
No swallowed errors in catch blocks src/lib/adapters/iptorrents.ts:114 catch block swallows error without logging or re-throwing
No swallowed errors in catch blocks src/lib/adapters/iptorrents.ts:175 catch block swallows error without logging or re-throwing
No swallowed errors in catch blocks src/lib/adapters/iptorrents.ts:181 catch block swallows error without logging or re-throwing

Passed (36/38)

  • ✅ Auth enforcement on protected routes (per-handler)
  • ✅ No dangerous functions (eval, innerHTML, etc.)
  • ✅ No hardcoded secrets in source
  • ✅ Security headers in next.config.ts
  • ✅ Cookie security (httpOnly, sameSite, secure)
  • ✅ No sensitive fields in API responses
  • ✅ No .env files committed to repo
  • ✅ No raw SQL in API routes
  • ✅ No fetch/redirect with unvalidated URLs in routes
  • ✅ Timing-safe comparison for secret values
  • ✅ No raw SQL migration files (schema-first only)
  • ✅ Docker container runs as non-root user
  • ✅ Public routes match proxy allowlist
  • ✅ File delete operations have path traversal defense
  • ✅ Password hashing uses Argon2 (not SHA-256/bcrypt)
  • ✅ Encrypted columns written via encrypt()
  • ✅ TOTP 2FA flow integrity
  • ✅ Emergency lockdown flow integrity
  • ✅ Scrub & delete (nuke) flow integrity
  • ✅ Backup restore flow integrity
  • ✅ Login flow integrity
  • ✅ Auth result checked before proceeding
  • ✅ Backup password inputs bounded before key derivation
  • ✅ Webhook delivery fetch uses redirect: "error"
  • ✅ SESSION_SECRET minimum-length guard in auth/crypto modules
  • ✅ Notification URL validators include SSRF protection
  • ✅ Dockerfile does not COPY sensitive files
  • ✅ No secret env vars in client components
  • ✅ Adapter Cookie headers guard against injection
  • ✅ Adapter files do not log credential values
  • ✅ No console.log in API routes
  • ✅ No TODO/FIXME in security-critical files
  • ✅ JSON.parse wrapped in try-catch
  • ✅ Request body size validation on upload routes
  • ✅ BigInt fields use string serialization
  • ✅ No raw error messages in API responses

Summary: 36/38 checks passed
1 critical failure(s)
— 1 warning(s)

See scripts/security-audit.ts for check definitions and SECURITY.md for the full security architecture.

@patrickdundas
patrickdundas merged commit bc23f89 into main Jul 29, 2026
5 of 6 checks passed
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