chore(ci): migrate workflows to gitea + consolidate keystore secret
flutter / analyze-test-build (push) Failing after 2s
test-go / test (push) Successful in 33s
android / Build + lint + test (push) Failing after 41s
test-web / test (push) Successful in 41s
android / Build signed release APK (push) Has been skipped
test-go / integration (push) Successful in 11m16s
flutter / analyze-test-build (push) Failing after 2s
test-go / test (push) Successful in 33s
android / Build + lint + test (push) Failing after 41s
test-web / test (push) Successful in 41s
android / Build signed release APK (push) Has been skipped
test-go / integration (push) Successful in 11m16s
- rename .forgejo/workflows/ to .gitea/workflows/ (git mv preserves history); Gitea Actions reads either path, but the directory now matches the active platform - collapse ANDROID_STORE_PASSWORD + ANDROID_KEY_PASSWORD into a single ANDROID_KEYSTORE_PASSWORD secret (PKCS12 keystores require the two passwords to be identical, so the duplication carried no information); build.gradle.kts still reads two env vars to stay format-agnostic, both now sourced from the same secret in CI - ignore android/*.keystore, android/*.keystore.*, android/*.jks, android/keystore.properties so the regenerated signing material never reaches a remote on accident - update prose references from Forgejo to Gitea in CLAUDE.md and the docs; the historical "migrated from Forgejo" note in CLAUDE.md is kept intentionally; forgejo/upload-artifact@v3 action refs are left untouched (canonical artifact action, resolves cleanly under Gitea Actions) Operator side: ANDROID_KEY_ALIAS, ANDROID_KEYSTORE_PASSWORD, and ANDROID_KEYSTORE_B64 secrets registered in Gitea before this lands.
This commit is contained in:
@@ -11,7 +11,7 @@ on:
|
||||
tags: ['v*']
|
||||
paths:
|
||||
- 'android/**'
|
||||
- '.forgejo/workflows/android.yml'
|
||||
- '.gitea/workflows/android.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
@@ -96,9 +96,12 @@ jobs:
|
||||
working-directory: android
|
||||
|
||||
env:
|
||||
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
|
||||
# PKCS12 keystores collapse store + key password into a single
|
||||
# value, so both env vars map to one secret. build.gradle still
|
||||
# reads them separately to stay format-agnostic.
|
||||
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
||||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -18,7 +18,7 @@ on:
|
||||
- 'web/src/lib/styles/tokens.json'
|
||||
- 'web/src/lib/styles/error-copy.json'
|
||||
- 'web/static/placeholders/album-fallback.svg'
|
||||
- '.forgejo/workflows/flutter.yml'
|
||||
- '.gitea/workflows/flutter.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
@@ -26,7 +26,7 @@ on:
|
||||
- 'web/src/lib/styles/tokens.json'
|
||||
- 'web/src/lib/styles/error-copy.json'
|
||||
- 'web/static/placeholders/album-fallback.svg'
|
||||
- '.forgejo/workflows/flutter.yml'
|
||||
- '.gitea/workflows/flutter.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
@@ -113,9 +113,12 @@ jobs:
|
||||
# the operator's persistent keystore.
|
||||
shell: bash
|
||||
env:
|
||||
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
|
||||
# PKCS12 keystores collapse store + key password into a single
|
||||
# value, so both env vars map to one secret. build.gradle still
|
||||
# reads them separately to stay format-agnostic.
|
||||
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
||||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
run: |
|
||||
TAG="${GITHUB_REF#refs/tags/v}"
|
||||
flutter build apk --release --build-name="${TAG}"
|
||||
@@ -1,6 +1,6 @@
|
||||
name: release
|
||||
|
||||
# Builds and pushes the minstrel container image to the Forgejo registry.
|
||||
# Builds and pushes the minstrel container image to the Gitea registry.
|
||||
#
|
||||
# push to main → :main
|
||||
# push tag vX.Y.Z → :vX.Y.Z and :latest
|
||||
@@ -30,7 +30,7 @@ on:
|
||||
- 'internal/**'
|
||||
- 'cmd/**'
|
||||
- '.golangci.yml'
|
||||
- '.forgejo/workflows/test-go.yml'
|
||||
- '.gitea/workflows/test-go.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
@@ -41,7 +41,7 @@ on:
|
||||
- 'internal/**'
|
||||
- 'cmd/**'
|
||||
- '.golangci.yml'
|
||||
- '.forgejo/workflows/test-go.yml'
|
||||
- '.gitea/workflows/test-go.yml'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -9,12 +9,12 @@ on:
|
||||
branches: [dev, main]
|
||||
paths:
|
||||
- 'web/**'
|
||||
- '.forgejo/workflows/test-web.yml'
|
||||
- '.gitea/workflows/test-web.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'web/**'
|
||||
- '.forgejo/workflows/test-web.yml'
|
||||
- '.gitea/workflows/test-web.yml'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -67,3 +67,11 @@ android/app/build/
|
||||
android/local.properties
|
||||
android/*.iml
|
||||
android/app/*.iml
|
||||
# Release signing material — keystore + extracted credentials live local
|
||||
# only; the canonical copy is the Gitea repo secret (ANDROID_KEYSTORE_B64
|
||||
# + the alias/password secrets). Losing the local file is fine; losing
|
||||
# the secret means rebuilding the keystore + reinstalling all clients.
|
||||
android/*.keystore
|
||||
android/*.keystore.*
|
||||
android/*.jks
|
||||
android/keystore.properties
|
||||
|
||||
@@ -44,14 +44,15 @@ exists in Flutter:
|
||||
|
||||
## Repo conventions (already in force)
|
||||
|
||||
- **No GitHub — Forgejo only.** PR/issue ops via the forgejo MCP; CI runs under
|
||||
`.forgejo/workflows/`. Never use `gh` or github.com URLs.
|
||||
- **No GitHub — Gitea only.** PR/issue ops via the gitea MCP (server lives at
|
||||
git.fabledsword.com, migrated from Forgejo); CI runs under `.gitea/workflows/`.
|
||||
Never use `gh` or github.com URLs.
|
||||
- **Git flow:** work on `dev` → PR to protected `main` → tag release. Never push
|
||||
to `main`.
|
||||
- **No in-task tests/builds.** Do not run flutter/gradle/npm `test`/`build`/
|
||||
`analyze` during implementation — CI verifies. Codegen scripts only.
|
||||
- **CI is operator-side.** After `git push origin dev`, the operator reports the
|
||||
result; don't poll Forgejo.
|
||||
result; don't poll Gitea.
|
||||
- **Specs/plans/audits/parity-map live local.** `docs/superpowers/` is
|
||||
`.gitignored` — save there for operator review; never commit those.
|
||||
- **detekt gates CI.** Watch the recurring ones: 60-line `LongMethod`,
|
||||
|
||||
@@ -91,7 +91,7 @@ Two concurrent dev processes:
|
||||
truncates your dev `minstrel` data (admin user, library, likes). It
|
||||
brings up the compose Postgres and creates the test DB if missing.
|
||||
- CI runs both: a fast `go test -short -race` gate plus an integration
|
||||
job with its own ephemeral Postgres (`.forgejo/workflows/test-go.yml`).
|
||||
job with its own ephemeral Postgres (`.gitea/workflows/test-go.yml`).
|
||||
|
||||
### Production build
|
||||
|
||||
@@ -101,7 +101,7 @@ Two concurrent dev processes:
|
||||
|
||||
- Day-to-day work happens on `dev` (or feature branches merged into `dev`).
|
||||
- `main` is **protected** — changes land via PR from `dev`.
|
||||
- Releases are cut by tagging `v*` off `main`; the release workflow builds and pushes the container image to the Forgejo registry.
|
||||
- Releases are cut by tagging `v*` off `main`; the release workflow builds and pushes the container image to the Gitea registry.
|
||||
|
||||
Task and milestone tracking: Fable (`Minstrel` project, id 12).
|
||||
|
||||
|
||||
+4
-4
@@ -12,8 +12,8 @@ git.fabledsword.com/bvandeusen/ci-go:1.26
|
||||
git.fabledsword.com/bvandeusen/ci-flutter:3.44
|
||||
```
|
||||
|
||||
- `ci-go:1.26` — Go server tests (`.forgejo/workflows/test-go.yml`), web SPA tests (`.forgejo/workflows/test-web.yml`), and the release container build (`.forgejo/workflows/release.yml`).
|
||||
- `ci-flutter:3.44` — Flutter client tests + debug/release APK builds (`.forgejo/workflows/flutter.yml`).
|
||||
- `ci-go:1.26` — Go server tests (`.gitea/workflows/test-go.yml`), web SPA tests (`.gitea/workflows/test-web.yml`), and the release container build (`.gitea/workflows/release.yml`).
|
||||
- `ci-flutter:3.44` — Flutter client tests + debug/release APK builds (`.gitea/workflows/flutter.yml`).
|
||||
|
||||
## Image deps used
|
||||
|
||||
@@ -42,6 +42,6 @@ None.
|
||||
- **Label/image split.** Workflows keep `runs-on: go-ci` / `runs-on: flutter-ci` as the scheduling label per the [`ci-runners.md`](https://…/FabledRulebook/ci-runners.md) "label = scheduling handle, image = `container.image`" pattern. The labels are intentional handles, not toolchain assertions.
|
||||
- **Integration-job docker-socket dependency.** `test-go.yml`'s integration job uses the runner's shared docker socket (`/var/run/docker.sock`) to bridge-IP-discover the per-job Postgres service container by name + network intersection — the dev compose's `minstrel-postgres-*` containers are explicitly skipped as belt-and-suspenders. Depends on `act_runner.valid_volumes` whitelisting the socket; if that ever stops auto-mounting, integration tests fail at the `docker inspect` step.
|
||||
- **Go toolchain pin.** `go.mod` is on `go 1.25.0` because `golang.org/x/crypto v0.51.0` declares 1.25 as its minimum. `ci-go:1.26` satisfies this with headroom. Future `x/crypto` bumps that move the Go floor should be paired with an image-tag bump in this file + the workflows.
|
||||
- **In-app update channel polling.** `release.yml` polls Forgejo's release-asset API for up to 15 min on tag pushes to fetch the APK that `flutter.yml` is concurrently attaching to the same release. The asset eventually appears because `flutter.yml` and `release.yml` run in parallel on the same tag; if the polling times out, the server image ships without the bundled update channel (graceful degradation, not a build failure).
|
||||
- **Cache server reachability.** `test-web.yml` does NOT use `cache: 'npm'` on `actions/setup-node` — the Forgejo Actions cache server isn't reachable from this runner's container network and `setup-node` was burning ~4m41s on ETIMEDOUT before failing open. With the migration to `ci-go:1.26`, `setup-node` is removed entirely (Node is in the image). The cache concern reappears if a future change re-introduces a network-dependent action.
|
||||
- **In-app update channel polling.** `release.yml` polls Gitea's release-asset API for up to 15 min on tag pushes to fetch the APK that `flutter.yml` is concurrently attaching to the same release. The asset eventually appears because `flutter.yml` and `release.yml` run in parallel on the same tag; if the polling times out, the server image ships without the bundled update channel (graceful degradation, not a build failure).
|
||||
- **Cache server reachability.** `test-web.yml` does NOT use `cache: 'npm'` on `actions/setup-node` — the Gitea Actions cache server isn't reachable from this runner's container network and `setup-node` was burning ~4m41s on ETIMEDOUT before failing open. With the migration to `ci-go:1.26`, `setup-node` is removed entirely (Node is in the image). The cache concern reappears if a future change re-introduces a network-dependent action.
|
||||
- **Friction asks.** None pending. The two images cover everything Minstrel needs.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ in-app update flow (#397).
|
||||
|
||||
CI populates this directory on tag releases:
|
||||
1. `flutter.yml` builds `app-release.apk` and attaches it to the
|
||||
Forgejo release as `minstrel-<TAG>.apk`.
|
||||
Gitea release as `minstrel-<TAG>.apk`.
|
||||
2. `release.yml` waits for that asset to appear, downloads it into
|
||||
this directory as `minstrel.apk`, writes the tag string to
|
||||
`minstrel.apk.version`, and `docker buildx build` includes both
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ version: "3.9"
|
||||
# tests at it:
|
||||
# make test-integration
|
||||
# (CI runs the same suite against its own ephemeral Postgres service —
|
||||
# see .forgejo/workflows/test-go.yml.)
|
||||
# see .gitea/workflows/test-go.yml.)
|
||||
#
|
||||
# Full stack (server + db):
|
||||
# docker compose up --build
|
||||
|
||||
@@ -51,10 +51,10 @@ and re-run `./tool/sync_shared.sh`.
|
||||
|
||||
## CI
|
||||
|
||||
`.forgejo/workflows/flutter.yml` runs on push to dev/main, tag pushes,
|
||||
`.gitea/workflows/flutter.yml` runs on push to dev/main, tag pushes,
|
||||
PR to main, and manual dispatch — path-filtered to `flutter_client/**`
|
||||
plus the shared web inputs. Steps: sync, analyze, test, build APK.
|
||||
Debug APKs upload as artifacts; release APKs attach to the Forgejo
|
||||
Debug APKs upload as artifacts; release APKs attach to the Gitea
|
||||
release on tag.
|
||||
|
||||
## Versioning
|
||||
@@ -67,7 +67,7 @@ when a server-side change requires a paired client update.
|
||||
|
||||
## Distribution
|
||||
|
||||
- **Android:** APK on the Forgejo release page. No Play Store for v1.
|
||||
- **Android:** APK on the Gitea release page. No Play Store for v1.
|
||||
- **iOS:** TestFlight on tag (manual upload v1, automate later).
|
||||
|
||||
## Out-of-scope for slice 1
|
||||
|
||||
Reference in New Issue
Block a user