ci: move CI to Gitea Actions
ci / secret-sweep (pull_request) Successful in 13s
ci / image (pull_request) Successful in 2m1s
ci / vectors-head (pull_request) Failing after 1m0s
ci / unit-tests (pull_request) Failing after 1m2s

Translates .gitlab-ci.yml to .gitea/workflows/ci.yml and deletes it. Kept:
secret sweep, the four-module unit run with --rerun-tasks against the
pinned vectors, the XML floors (595/405/68/515, 1580 total), vectors-head
(advisory).

Runs on mac1/mac2 inside a pinned toolchain image (ci/android-ci.Dockerfile:
Temurin 21.0.5, cmdline-tools 11076708, platform 35, build-tools 34.0.0 and
35.0.0, Node 22.11.0), never on pauls-imac. The `image` job pushes the tag
to git.extant2000.com when it is missing.

Vector and README links now point at git.extant2000.com/extant2000.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Paul Hitt
2026-10-14 10:03:52 -04:00
co-authored by Claude Opus 5.5
parent 92776e6f8c
commit 465a192d7f
6 changed files with 237 additions and 242 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# Why this repository pins flamenet-e2e
`.e2e-ref` is the commit of [flamenet-e2e](https://gitlab.com/extant2000/flamenet-e2e)
`.e2e-ref` is the commit of [flamenet-e2e](https://git.extant2000.com/extant2000/flamenet-e2e)
whose protocol vectors the `unit-tests` job checks against. `AccountKdfTest`,
`PQVectorTest` and `PublishedVectorsTest` all read them.
@@ -17,7 +17,7 @@ A pin alone is worse than HEAD, though. The argument for HEAD is real: a
client tested against a pinned old harness is tested against a pinned old spec,
and if the vectors move and nothing says so, this suite quietly stops checking
the protocol anybody is actually running. That is why `vectors-head` exists and
is `allow_failure: true`.
is `continue-on-error: true` in `.gitea/workflows/ci.yml`.
Being behind is LOUD and NON-BLOCKING. Being broken is a hard stop. A red
`vectors-head` means an update is waiting, not that anything is wrong.
+196
View File
@@ -0,0 +1,196 @@
# CI for the Android app on Gitea Actions. Translated from .gitlab-ci.yml on
# 2026-10-13; every gate it had is kept. Instrumented tests stay manual: they
# need an emulator and a local relay.
#
# Runs on mac1/mac2 (`ubuntu-latest`) inside the pinned toolchain image built
# from ci/android-ci.Dockerfile. Never on pauls-imac: Android unit tests hang
# there (2026-10-09).
name: ci
on:
push:
branches: [main]
pull_request:
env:
# Bump when ci/android-ci.Dockerfile changes.
IMAGE: git.extant2000.com/extant2000/flamenet-android-ci:jdk21.0.5-api35-r1
GITEA_BASE: https://git.extant2000.com/extant2000
jobs:
# The repository is public, so this sweep is the last thing between a pasted
# key and the internet. It was red for nine days in 2026-09 because nobody
# ran it.
secret-sweep:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- run: bash scripts/secret-sweep.sh
# Builds and pushes the toolchain image when its tag is not in the registry
# yet. A no-op on every other run.
image:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Build and push the toolchain image if missing
env:
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
JOB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ACTOR: ${{ gitea.actor }}
run: |
set -euo pipefail
curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz \
| tar -xz -C /usr/local/bin --strip-components=1 docker/docker
if [ -n "${REGISTRY_TOKEN:-}" ]; then
echo "$REGISTRY_TOKEN" | docker login git.extant2000.com -u extant2000git --password-stdin
else
echo "$JOB_TOKEN" | docker login git.extant2000.com -u "$ACTOR" --password-stdin
fi
if docker manifest inspect "$IMAGE" >/dev/null 2>&1; then
echo "image $IMAGE exists"; exit 0
fi
DOCKER_BUILDKIT=0 docker build -t "$IMAGE" -f ci/android-ci.Dockerfile ci
docker push "$IMAGE"
unit-tests:
needs: image
runs-on: ubuntu-latest
timeout-minutes: 45
container:
image: git.extant2000.com/extant2000/flamenet-android-ci:jdk21.0.5-api35-r1
env:
# The interop tests FAIL rather than skip when unconfigured, on purpose.
# They need a real lyrebird from the flamenet-elligator2 checkout, so they
# are opted out HERE and nowhere else. Run scripts/obfs4-interop.sh
# locally before merging any obfs4 change.
OBFS4_INTEROP_OPTOUT: "1"
steps:
- uses: actions/checkout@v4
- name: Fetch the pinned protocol vectors
run: |
set -euo pipefail
# Pinned to .e2e-ref, not tip (flamenet-relay#56 is what tip cost).
# `vectors-head` below is the advisory half that watches HEAD.
FLAMENET_E2E_PIN=$(cat .e2e-ref)
rm -rf .ci-vectors
git clone -q "$GITEA_BASE/flamenet-e2e.git" .ci-vectors
git -C .ci-vectors checkout -q "$FLAMENET_E2E_PIN"
- name: Unit tests
run: |
set -euo pipefail
V="$GITHUB_WORKSPACE/.ci-vectors/test/vectors"
export FLAMENET_VECTORS="$V/protocol-v1.json"
export FLAMENET_PQ_VECTORS="$V/pqx3dh-v2.json"
export FLAMENET_ACCOUNT_VECTORS="$V/account-kdf-v1.json"
export FLAMENET_BACKUP_VECTORS="$V/backup-v1.json"
export FLAMENET_BACKUP_PAYLOAD_VECTORS="$V/backup-payload-v1.json"
export FLAMENET_CONTENT_VECTORS="$V/content-v1.json"
export FLAMENET_POLL_VECTORS="$V/poll-tally-v1.json"
export FLAMENET_PADDING_VECTORS="$V/padding-v1.json"
export FLAMENET_SYNC_VECTORS="$V/sync-merge-v1.json"
export FLAMENET_HANDLE_CERT_VECTORS="$V/handle-cert-v1.json"
export FLAMENET_LINK_VECTORS="$V/links-v1.json"
export FLAMENET_BRIDGE_VECTORS="$V/bridge-offer-v1.json"
export FLAMENET_CONTENT_KINDS_VECTORS="$V/content-kinds-v1.json"
export FLAMENET_TODAY_VECTORS="$V/today-v1.json"
export FLAMENET_HELLO_LINK_VECTORS="$V/hello-link-v1.json"
# A path that silently does not exist would read as a protocol bug.
for f in "$FLAMENET_VECTORS" "$FLAMENET_PQ_VECTORS" "$FLAMENET_ACCOUNT_VECTORS" \
"$FLAMENET_BACKUP_VECTORS" "$FLAMENET_BACKUP_PAYLOAD_VECTORS" \
"$FLAMENET_CONTENT_VECTORS" "$FLAMENET_POLL_VECTORS" \
"$FLAMENET_PADDING_VECTORS" "$FLAMENET_SYNC_VECTORS" \
"$FLAMENET_HANDLE_CERT_VECTORS" "$FLAMENET_LINK_VECTORS" \
"$FLAMENET_BRIDGE_VECTORS" "$FLAMENET_CONTENT_KINDS_VECTORS" \
"$FLAMENET_TODAY_VECTORS" "$FLAMENET_HELLO_LINK_VECTORS"; do
[ -f "$f" ] || { echo "GATE: vector file missing: $f"; exit 1; }
done
# Clear old results so the gate never counts ghosts.
rm -rf ./*/build/test-results
# --rerun-tasks: a FROM-CACHE pass prints the same BUILD SUCCESSFUL
# as a real one. Both app variants: release is the one that ships.
./gradlew --no-daemon --rerun-tasks :engine:test :client:test :obfs4:test \
:games:test :app:testDebugUnitTest :app:testReleaseUnitTest
- name: Gate on the test results
run: |
# Assert on the XML, never on Gradle's exit status: `:app` prints no
# test names, and an up-to-date task is also "BUILD SUCCESSFUL".
python3 - <<'PY'
import glob, re, sys
# Floors near 90% of the suite (663 / 453 / 75 / 572, games 15).
# `app` counts both variants.
MINIMUMS = {"engine": 595, "client": 405, "obfs4": 68, "games": 13, "app": 515}
totals = {}
for module in MINIMUMS:
tests = failures = skipped = 0
for path in glob.glob(f"{module}/build/test-results/*/TEST-*.xml"):
text = open(path).read()
m = re.search(r'tests="(\d+)" skipped="(\d+)" failures="(\d+)" errors="(\d+)"', text)
if not m:
continue
tests += int(m.group(1)); skipped += int(m.group(2))
failures += int(m.group(3)) + int(m.group(4))
totals[module] = (tests, failures, skipped)
bad = False
for module, (tests, failures, skipped) in totals.items():
print(f"GATE: {module}: {tests} tests, {failures} failures, {skipped} skipped")
if tests < MINIMUMS[module]:
print(f"GATE: {module} reported {tests} tests, the suite did not run")
bad = True
if failures:
bad = True
grand = sum(t for t, _, _ in totals.values())
print(f"GATE: {grand} tests in total")
if grand < 1580:
print(f"GATE: only {grand} tests in the whole build; something is not running")
bad = True
sys.exit(1 if bad else 0)
PY
# The pin's conscience: the vector suites against flamenet-e2e HEAD.
# Allowed to fail. A red run means an update is waiting; see .e2e-ref.md.
vectors-head:
needs: image
runs-on: ubuntu-latest
timeout-minutes: 20
continue-on-error: true
container:
image: git.extant2000.com/extant2000/flamenet-android-ci:jdk21.0.5-api35-r1
env:
OBFS4_INTEROP_OPTOUT: "1"
steps:
- uses: actions/checkout@v4
- name: Vector suites at flamenet-e2e HEAD
run: |
set -euo pipefail
rm -rf .ci-vectors-head
git clone --depth 1 "$GITEA_BASE/flamenet-e2e.git" .ci-vectors-head
echo "pinned: $(cat .e2e-ref)"
echo "at HEAD: $(git -C .ci-vectors-head rev-parse HEAD)"
V="$GITHUB_WORKSPACE/.ci-vectors-head/test/vectors"
export FLAMENET_VECTORS="$V/protocol-v1.json"
export FLAMENET_PQ_VECTORS="$V/pqx3dh-v2.json"
export FLAMENET_ACCOUNT_VECTORS="$V/account-kdf-v1.json"
export FLAMENET_BACKUP_VECTORS="$V/backup-v1.json"
export FLAMENET_BACKUP_PAYLOAD_VECTORS="$V/backup-payload-v1.json"
export FLAMENET_CONTENT_VECTORS="$V/content-v1.json"
export FLAMENET_POLL_VECTORS="$V/poll-tally-v1.json"
export FLAMENET_PADDING_VECTORS="$V/padding-v1.json"
export FLAMENET_SYNC_VECTORS="$V/sync-merge-v1.json"
export FLAMENET_HANDLE_CERT_VECTORS="$V/handle-cert-v1.json"
export FLAMENET_LINK_VECTORS="$V/links-v1.json"
export FLAMENET_BRIDGE_VECTORS="$V/bridge-offer-v1.json"
export FLAMENET_CONTENT_KINDS_VECTORS="$V/content-kinds-v1.json"
export FLAMENET_TODAY_VECTORS="$V/today-v1.json"
export FLAMENET_HELLO_LINK_VECTORS="$V/hello-link-v1.json"
# Only the tests that read vectors: the engine, :obfs4 (the
# bridge-offer vectors, SPEC section 24), and the three 0.32 loaders
# in :client and :app.
./gradlew --no-daemon --rerun-tasks :engine:test :obfs4:test \
:client:test --tests io.flamenet.client.SharedVectorsTodayTest \
:app:testDebugUnitTest --tests io.flamenet.messenger.app.SharedVectorsContentKindsTest \
--tests io.flamenet.messenger.app.SharedVectorsHelloLinkTest
-238
View File
@@ -1,238 +0,0 @@
# T4: the Mac is in the merge path. Engine, client, obfs4 and app unit suites on
# the project's own runner (tag mac-local). Instrumented tests stay manual:
# they need an emulator and a local relay.
stages: [test]
# The repository is public, so this sweep is the last thing between a pasted
# key and the internet. Until 2026-09-17 it only ran when somebody remembered
# to, and it had been red for nine days without anyone noticing, because a
# formatter carried an allow marker off the line it covered. A check nobody
# runs protects nothing; here it runs on every merge request and every push
# to main, and it finishes in seconds.
secret-sweep:
stage: test
tags: [mac-local]
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'
variables:
GIT_DEPTH: "1"
script:
- bash scripts/secret-sweep.sh
timeout: 5m
unit-tests:
stage: test
tags: [mac-local]
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'
variables:
GIT_DEPTH: "1"
# The interop tests FAIL rather than skip when unconfigured, on purpose,
# a silent skip is how a transport suite goes green while proving nothing.
# They need a real lyrebird from the flamenet-elligator2 checkout, which is
# not in this build directory, so they are opted out HERE and nowhere else.
# Run `scripts/obfs4-interop.sh` locally before merging any obfs4 change:
# every other test in that module compares against recorded vectors or
# against itself, and two identically-wrong ends agree perfectly.
OBFS4_INTEROP_OPTOUT: "1"
script:
- export JAVA_HOME=/opt/homebrew/opt/openjdk@21
- export ANDROID_HOME=$HOME/Library/Android/sdk
# The protocol vectors are not in this repo, and CI never had them.
# `AccountKdfTest`, `PQVectorTest` and `PublishedVectorsTest` look for a
# sibling `flamenet-e2e` checkout. That exists on a developer's machine and
# has never existed in a build directory, so all twenty of them have been
# failing here since they were written, invisibly, because the build cache
# replayed a local pass. They fail rather than skip when the file is
# missing, exactly so this could not hide; it took `--rerun-tasks` to let
# them say so.
#
# Pinned to a commit, NOT cloned at tip. Tip was the first instinct,
# "if the protocol changes this SHOULD go red", and flamenet-relay#56 is
# the write-up of what that actually costs. There, a job clones
# `flamenet-e2e` at HEAD, so merging anything in that repo turned relay's
# `main` red in a pipeline nobody was watching, blocked six MRs sitting on
# merge-when-pipeline-succeeds, and was misdiagnosed as runner starvation.
# It fired twice in one evening. The person who merged was working in a
# different project and had no reason to look.
#
# A pin makes the same divergence a deliberate, reviewable bump here instead
# of a surprise failure in a repo nobody was thinking about. The commit
# lives in `.e2e-ref`; `.e2e-ref.md` says how to take an update.
#
# A pin ALONE is worse than HEAD, and that is what the first version
# of this got wrong. Pinning silently means the vectors can move and this
# suite goes on checking last month's protocol, reporting green, the exact
# "tested against a pinned old spec" failure the relay's own note warns
# about. `vectors-head` below is the other half: it runs the same checks at
# HEAD and is allowed to fail, so being behind is LOUD and non-blocking
# while being broken stays a hard stop.
#
# `flamenet-e2e` is public, so no credentials are needed.
- FLAMENET_E2E_PIN=$(cat "$CI_PROJECT_DIR/.e2e-ref")
- rm -rf "$CI_PROJECT_DIR/.ci-vectors"
- git clone -q https://gitlab.com/extant2000/flamenet-e2e.git "$CI_PROJECT_DIR/.ci-vectors"
- git -C "$CI_PROJECT_DIR/.ci-vectors" checkout -q "$FLAMENET_E2E_PIN"
- export FLAMENET_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/protocol-v1.json"
- export FLAMENET_PQ_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/pqx3dh-v2.json"
- export FLAMENET_ACCOUNT_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/account-kdf-v1.json"
- export FLAMENET_BACKUP_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/backup-v1.json"
- export FLAMENET_BACKUP_PAYLOAD_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/backup-payload-v1.json"
- export FLAMENET_CONTENT_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/content-v1.json"
- export FLAMENET_POLL_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/poll-tally-v1.json"
- export FLAMENET_CONTENT_KINDS_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/content-kinds-v1.json"
- export FLAMENET_TODAY_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/today-v1.json"
- export FLAMENET_HELLO_LINK_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/hello-link-v1.json"
- export FLAMENET_PADDING_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/padding-v1.json"
- export FLAMENET_SYNC_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/sync-merge-v1.json"
- export FLAMENET_HANDLE_CERT_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/handle-cert-v1.json"
- export FLAMENET_LINK_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/links-v1.json"
- export FLAMENET_BRIDGE_VECTORS="$CI_PROJECT_DIR/.ci-vectors/test/vectors/bridge-offer-v1.json"
# Checked before the suite runs. A path that silently does not exist puts
# the tests straight back where they were, and the failure would read as a
# protocol bug rather than a missing file.
- |
for f in "$FLAMENET_VECTORS" "$FLAMENET_PQ_VECTORS" "$FLAMENET_ACCOUNT_VECTORS" \
"$FLAMENET_BACKUP_VECTORS" "$FLAMENET_BACKUP_PAYLOAD_VECTORS" \
"$FLAMENET_CONTENT_VECTORS" "$FLAMENET_POLL_VECTORS" \
"$FLAMENET_CONTENT_KINDS_VECTORS" "$FLAMENET_TODAY_VECTORS" \
"$FLAMENET_HELLO_LINK_VECTORS" "$FLAMENET_PADDING_VECTORS" \
"$FLAMENET_SYNC_VECTORS" "$FLAMENET_HANDLE_CERT_VECTORS" \
"$FLAMENET_LINK_VECTORS" "$FLAMENET_BRIDGE_VECTORS"; do
[ -f "$f" ] || { echo "GATE: vector file missing: $f"; exit 1; }
done
# Clear old results before running, or the gate counts ghosts. The
# runner reuses its build directory, so XML from a previous pipeline
# survives, and a suite that stopped running entirely would still be
# counted, by the very check meant to notice that it had stopped.
- rm -rf ./*/build/test-results
# Keep the build output out of Spotlight.
#
# The module build directories are rewritten every job on a host that is
# also the mac-local runner for both app repos. Indexing them drives the
# machine to a load average in the hundreds, with `mds_stores` and
# `mdworker_shared` at the top of CPU while no build process is near it.
# Measured on the iPhone repo: the same from-scratch build peaks at load
# ~12 with its output excluded and well over a hundred without.
#
# Written here rather than committed, because the directories these belong
# in are created by the build.
- |
for m in app engine client obfs4 games; do
mkdir -p "$m/build" && touch "$m/build/.metadata_never_index"
done
# `:obfs4:test` was missing from this list. The module shipped in !77
# with ~100 tests, the Elligator2 port, the framing, the handshake, the
# socket factory, and not one of them ran in CI. A break in the transport
# would have merged green.
#
# `--rerun-tasks` because this runner is the developer's own Mac.
# Gradle's build cache is shared with local runs, so a task whose inputs a
# local run already covered comes back FROM-CACHE and CI replays a result it
# never computed. That is not independent verification, and it is invisible:
# a cached pass and a real pass print the same "BUILD SUCCESSFUL".
# Both app variants, not just debug. The release variant was never run
# here, so four tests that die on it -- the merged manifest has no
# ComponentActivity, which is a debug-only dependency -- were red from the
# day they landed and CI never said a word. A variant nobody tests is a
# variant nobody knows about, and release is the one that ships.
- ./gradlew --no-daemon --rerun-tasks :engine:test :client:test :obfs4:test :games:test :app:testDebugUnitTest :app:testReleaseUnitTest
- |
# Assert on the RESULTS, never on Gradle's exit status. `:app` prints
# no per-test names at all, so a filter matching nothing and a full green
# run are indistinguishable in the log, and a skipped-as-up-to-date task
# is likewise just "BUILD SUCCESSFUL". The XML is the only thing that says
# what actually executed.
python3 - <<'PY'
import glob, re, sys
# Floors, not exact counts. Set around 90% of the suite as it stands
# (663 / 453 / 75 / 572, games 15) so a module that loses most of its
# tests to a bad filter is caught, without a gate that has to be edited
# every time somebody adds one.
#
# `app` counts both variants, because the glob takes every
# `test-results/*` directory and both now run.
MINIMUMS = {"engine": 595, "client": 405, "obfs4": 68, "games": 13, "app": 515}
totals = {}
for module in MINIMUMS:
tests = failures = skipped = 0
for path in glob.glob(f"{module}/build/test-results/*/TEST-*.xml"):
text = open(path).read()
m = re.search(r'tests="(\d+)" skipped="(\d+)" failures="(\d+)" errors="(\d+)"', text)
if not m:
continue
tests += int(m.group(1)); skipped += int(m.group(2))
failures += int(m.group(3)) + int(m.group(4))
totals[module] = (tests, failures, skipped)
bad = False
for module, (tests, failures, skipped) in totals.items():
print(f"GATE: {module}: {tests} tests, {failures} failures, {skipped} skipped")
if tests < MINIMUMS[module]:
print(f"GATE: {module} reported {tests} tests, the suite did not run")
bad = True
if failures:
bad = True
# A floor across the whole build as well as per module: a module can be
# present and still have lost most of its suite to a bad filter.
grand = sum(t for t, _, _ in totals.values())
print(f"GATE: {grand} tests in total")
if grand < 1580:
print(f"GATE: only {grand} tests in the whole build; something is not running")
bad = True
sys.exit(1 if bad else 0)
PY
timeout: 30m
# The pin's conscience. Runs the vector suites against flamenet-e2e's
# actual HEAD, and is allowed to fail. Without it, `.e2e-ref` is permission to
# fall behind forever with a green board, which is the failure mode a pin
# introduces and the reason the relay pairs its pin with the same job.
#
# A red run here means an update is waiting. Take it per `.e2e-ref.md`.
vectors-head:
stage: test
tags: [mac-local]
allow_failure: true
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'
variables:
GIT_DEPTH: "1"
OBFS4_INTEROP_OPTOUT: "1"
script:
- export JAVA_HOME=/opt/homebrew/opt/openjdk@21
- export ANDROID_HOME=$HOME/Library/Android/sdk
- rm -rf "$CI_PROJECT_DIR/.ci-vectors-head"
- git clone --depth 1 https://gitlab.com/extant2000/flamenet-e2e.git "$CI_PROJECT_DIR/.ci-vectors-head"
- |
echo "pinned: $(cat "$CI_PROJECT_DIR/.e2e-ref")"
echo "at HEAD: $(git -C "$CI_PROJECT_DIR/.ci-vectors-head" rev-parse HEAD)"
- export FLAMENET_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/protocol-v1.json"
- export FLAMENET_PQ_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/pqx3dh-v2.json"
- export FLAMENET_ACCOUNT_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/account-kdf-v1.json"
- export FLAMENET_BACKUP_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/backup-v1.json"
- export FLAMENET_BACKUP_PAYLOAD_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/backup-payload-v1.json"
- export FLAMENET_CONTENT_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/content-v1.json"
- export FLAMENET_POLL_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/poll-tally-v1.json"
- export FLAMENET_CONTENT_KINDS_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/content-kinds-v1.json"
- export FLAMENET_TODAY_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/today-v1.json"
- export FLAMENET_HELLO_LINK_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/hello-link-v1.json"
- export FLAMENET_PADDING_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/padding-v1.json"
- export FLAMENET_SYNC_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/sync-merge-v1.json"
- export FLAMENET_HANDLE_CERT_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/handle-cert-v1.json"
- export FLAMENET_LINK_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/links-v1.json"
- export FLAMENET_BRIDGE_VECTORS="$CI_PROJECT_DIR/.ci-vectors-head/test/vectors/bridge-offer-v1.json"
# Only the tests that read vectors: the engine, :obfs4 (the bridge-offer
# vectors, SPEC section 24), and the three 0.32 loaders
# in :client and :app. The rest of the suite has nothing to say about
# whether flamenet-e2e moved, and running it here would double the board's
# cost to answer a question it cannot answer.
- ./gradlew --no-daemon --rerun-tasks :engine:test :obfs4:test
:client:test --tests io.flamenet.client.SharedVectorsTodayTest
:app:testDebugUnitTest --tests io.flamenet.messenger.app.SharedVectorsContentKindsTest
--tests io.flamenet.messenger.app.SharedVectorsHelloLinkTest
timeout: 20m
+1 -1
View File
@@ -47,7 +47,7 @@ less than the two existing engines quietly agreed on, but only if it is
written against the spec and the published vectors rather than against a
reading of our own Swift and JavaScript. So the engine is held to
`test/vectors/protocol-v1.json` in
[flamenet-e2e](https://gitlab.com/extant2000/flamenet-e2e), the same file the
[flamenet-e2e](https://git.extant2000.com/extant2000/flamenet-e2e), the same file the
other two engines are checked against, read from that repository rather than
copied here, because a copied vector file drifts and a drifting vector file
stops being a check. `PublishedVectorsTest` looks for it beside this checkout
+37
View File
@@ -0,0 +1,37 @@
# Toolchain image for the Android unit suites on Gitea Actions (mac1/mac2,
# `ubuntu-latest`, Intel). Every version is pinned. When anything here
# changes, bump IMAGE_TAG in .gitea/workflows/ci.yml; the `image` job builds
# and pushes a tag that does not exist yet.
#
# JDK 21, as the GitLab runner used (openjdk@21). Node is here because
# actions/checkout is a JavaScript action and runs inside this container.
FROM eclipse-temurin:21.0.5_11-jdk-jammy
ARG NODE_VERSION=22.11.0
ARG CMDLINE_TOOLS=11076708
ENV ANDROID_HOME=/opt/android-sdk \
ANDROID_SDK_ROOT=/opt/android-sdk
# python3 for the result gate; fontconfig for Robolectric's NATIVE graphics.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates curl git unzip xz-utils python3 fontconfig \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz" \
| tar -xJ -C /usr/local --strip-components=1 \
&& node --version
RUN mkdir -p "$ANDROID_HOME/cmdline-tools" \
&& curl -fsSL -o /tmp/ct.zip \
"https://dl.google.com/android/repository/commandlinetools-linux-${CMDLINE_TOOLS}_latest.zip" \
&& unzip -q /tmp/ct.zip -d "$ANDROID_HOME/cmdline-tools" \
&& mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest" \
&& rm /tmp/ct.zip
# compileSdk 35; AGP 8.7.3 defaults to build-tools 34.0.0. 35.0.0 matches the
# developer machines.
RUN yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null \
&& "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
"platform-tools" "platforms;android-35" "build-tools;34.0.0" "build-tools;35.0.0"
@@ -30,7 +30,7 @@ class PublishedVectorsTest {
file != null,
"published vectors not found. Looked in: " +
candidates.joinToString(", ") { it.absolutePath } +
". Clone https://gitlab.com/extant2000/flamenet-e2e beside this repo, " +
". Clone https://git.extant2000.com/extant2000/flamenet-e2e beside this repo, " +
"or set FLAMENET_VECTORS to protocol-v1.json.",
)
JSONObject(file!!.readText())