Skip to content
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
9e1fd06
client: replace submodule with specific release
Jun 16, 2026
3562b29
write client version in backward-compatible format
Jun 16, 2026
cba366d
check download hash
Jun 16, 2026
c826032
set FRONTEND_VERSION in tests
Jun 16, 2026
08dcc74
update check_submodules()
Jun 16, 2026
a6ad783
lower expectations
Jun 16, 2026
37618a4
smaller context expectations
Jun 16, 2026
c6e75bb
update test-images.sh
Jun 16, 2026
0c13e4c
try fix test=oiamges
Jun 16, 2026
258400c
wip
Jun 17, 2026
d1348c8
wip
Jun 19, 2026
dca226d
reconsolidate build and version-writing
Jun 19, 2026
cf7b059
whitespace
Jun 19, 2026
dadcae5
fix classic build
Jun 19, 2026
7d16353
write-version: fix test
Jun 19, 2026
6e59607
fix write-version
Jun 19, 2026
72ae170
fix test-images?
Jun 19, 2026
decdb16
fix write-version dir changes
Jun 19, 2026
7992f09
rename classic mode to "source"
Jun 19, 2026
864ed5b
ci/test-images: test source build mode
Jun 19, 2026
be4c142
log build mode
Jun 19, 2026
5f75cc9
dockerfile whitespace
Jun 19, 2026
4b941b1
treorder
Jun 19, 2026
dfefee8
revert submodule change
Jun 19, 2026
0f59ccf
handle missing git dir
Jun 19, 2026
6d769e5
whitespace
Jun 19, 2026
58b16f5
check out lcient!
Jun 19, 2026
cf12b50
comment
Jun 19, 2026
cffa55c
yaml symxac
Jun 19, 2026
dfa1e6d
update hash expectations
Jun 19, 2026
ee5d01f
whitespace
alxndrsn Jun 19, 2026
25e435b
Update comment
alxndrsn Jun 19, 2026
e3384de
Extract FRONTEND_VERSION once, more cleanly
Jun 22, 2026
60ae5b6
ci: run relevant job only
Jun 22, 2026
068a376
yaml symtax?
Jun 22, 2026
b0e49d5
debug
Jun 22, 2026
700e7d5
more debug
Jun 22, 2026
24d059b
more more debug
Jun 22, 2026
d8e7e2d
touch envfile
Jun 22, 2026
29413f1
handle API failure more cleanly
Jun 22, 2026
d35b4b4
strip debugging
Jun 22, 2026
28ebe76
better handling of GH API rate-limiting
Jun 22, 2026
422ddd1
touch .env?
Jun 22, 2026
8e1f55f
name job
Jun 22, 2026
ce711c7
matrix
Jun 22, 2026
bff8195
trust curl to handle integrity; add some robustness
Jun 22, 2026
2e1d520
finish matrix
Jun 22, 2026
39c8619
hardcode frontend repo; make version more realistic
Jun 22, 2026
e5f760a
fix URL
Jun 22, 2026
279870a
Merge branch 'next' into no-more-submodule
alxndrsn Jun 22, 2026
fdd8d40
Apply suggestion from @alxndrsn
alxndrsn Jun 22, 2026
6af66c1
reinstate ci
Jun 22, 2026
75b6c77
collapse source checks
Jun 22, 2026
9df49d1
simplify checks
Jun 22, 2026
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
157 changes: 30 additions & 127 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,143 +12,46 @@ on:
default: false

jobs:
test-misc: # quick, simple checks
Comment thread
alxndrsn marked this conversation as resolved.
timeout-minutes: 2
runs-on: ubuntu-latest
steps:
- run: docker --version
- run: docker compose version
- uses: actions/checkout@v5
- run: ./test/check-submodules.sh
- run: ./test/test-with-pgenvblock.sh
- run: sudo apt-get install shellcheck
- run: ./test/check-scripts.sh
- run: ./test/check-for-large-files.sh
- run: ./test/check-dockerfiles.sh
- run: cd test && npm clean-install
- run: cd test && npm run lint
- run: cd test && npm run test:github-actions
test-envsub:
timeout-minutes: 2
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- run: cd test/envsub && ./run-tests.sh
test-nginx:
timeout-minutes: 4
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version-file: test/package.json
- run: cd test/nginx && npm clean-install
- run: cd test/nginx && ./setup-tests.sh
- run: cd test/nginx && npm run test:nginx:mocha
- run: cd test/nginx && ./lint-config.sh

- run: cd test/nginx && npx playwright install --with-deps chromium-headless-shell
- run: cd test/nginx && npm run test:nginx:playwright

- if: always()
run: cd test/nginx && docker compose -f nginx.test.docker-compose.yml logs --no-log-prefix nginx-ssl-selfsign
- if: always()
run: cd test/nginx && docker compose -f nginx.test.docker-compose.yml logs --no-log-prefix nginx-ssl-upstream
- if: always()
run: cd test/nginx && docker compose -f nginx.test.docker-compose.yml logs --no-log-prefix service
- if: always()
run: cd test/nginx && docker compose -f nginx.test.docker-compose.yml logs --no-log-prefix enketo
- if: always()
run: cd test/nginx && docker compose -f nginx.test.docker-compose.yml logs --no-log-prefix sentry-mock
test-secrets:
timeout-minutes: 2
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- run: ./test/test-secrets.sh
test-service:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
submodules: true
- uses: actions/setup-node@v5
with:
node-version-file: test/package.json
- run: cd test/nginx && npm clean-install
- run: cd test/nginx && npm run test:service
test-images:
timeout-minutes: 10
needs:
- test-misc
- test-envsub
- test-nginx
- test-secrets
- test-service
runs-on: ubuntu-latest # TODO matrix to run on all expected versions?
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
fetch-tags: true
submodules: recursive
- run: ./test/check-docker-context.sh --min-size 15000 --max-size 25000 --min-count 1400 --max-count 1500
- run: ./test/test-images.sh
- if: always()
run: docker compose logs
build-push-image:
if: |
(github.event_name == 'workflow_dispatch' && inputs.publish_image == true) ||
(github.event_name != 'workflow_dispatch' && (
github.ref == 'refs/heads/master' ||
startsWith(github.ref, 'refs/tags/v')
))
needs:
- test-images
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
image: [nginx, service]
env:
REGISTRY: ghcr.io
x: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
y: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
Comment thread
alxndrsn marked this conversation as resolved.
Outdated
#needs:
#- test-misc
#- test-envsub
#- test-nginx
#- test-secrets
#- test-service
Comment thread
alxndrsn marked this conversation as resolved.
Outdated
runs-on: ubuntu-latest # TODO matrix to run on all expected versions?
steps:
- name: Checkout repository
uses: actions/checkout@v5
- uses: actions/checkout@v5
with:
fetch-depth: 0
fetch-tags: true
submodules: recursive
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Show Docker Context
run: ./test/check-docker-context.sh --report

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/central-${{ matrix.image }}
#- run: ./test/check-docker-context.sh --min-size 5000 --max-size 10000 --min-count 600 --max-count 700

- name: Set up QEMU emulator for multi-arch images
uses: docker/setup-qemu-action@v4
- name: Extract FRONTEND_VERSION
run: |
touch .env
echo "FRONTEND_VERSION=$(
docker compose config --format json | jq -r .services.nginx.build.args.FRONTEND_VERSION
)" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- run: FRONTEND_BUILD_MODE=fetch ./test/test-images.sh

- name: Build and push ${{ matrix.image }} Docker image
uses: docker/build-push-action@v7
with:
file: ${{ matrix.image }}.dockerfile
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: 'linux/amd64,linux/arm64'
# Check out the current frontend version referenced by docker-compose, as it should build OK.
- run: |
git clone \
--depth 1 \
--branch "$FRONTEND_VERSION" \
https://github.com/alxndrsn/odk-central-frontend.git \
Comment thread
alxndrsn marked this conversation as resolved.
Outdated
client
- run: FRONTEND_BUILD_MODE=source ./test/test-images.sh

- if: always()
run: docker compose logs
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.swp
*.swo
/.env
/client/
/docker-compose.override.yml
/version.txt

Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "server"]
path = server
url = https://github.com/getodk/central-backend.git
[submodule "client"]
path = client
url = https://github.com/getodk/central-frontend.git
1 change: 0 additions & 1 deletion client
Submodule client deleted from 56b6bb
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ services:
build:
context: .
dockerfile: nginx.dockerfile
args:
FRONTEND_BUILD_MODE: ${FRONTEND_BUILD_MODE:-fetch}
FRONTEND_VERSION: v2026.2.0-beta.0
depends_on:
- service
- enketo
Expand Down
56 changes: 51 additions & 5 deletions files/prebuild/build-frontend.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
set -o pipefail
shopt -s inherit_errexit

cd client
log() { echo >&2 "[build-frontend] $*"; }

if [[ ${SKIP_FRONTEND_BUILD-} != "" ]]; then
echo "[build-frontend] Skipping frontend build."
if [[ $FRONTEND_BUILD_MODE = test ]]; then
log "Building mock frontend..."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test and fetch modes have some overlap, and I wonder if we can completely get rid of test mode, and instead of building a mock frontend actually download the latest frontend. I think that would make the testing more realistic because it would be testing actual files rather than stubs.

Feel free to leave this for a subsequent issue...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely worth considering 👍


# Create minimal fake frontend to allow tests to pass:
mkdir dist dist/assets dist/fonts dist/apps dist/apps/forms
Expand Down Expand Up @@ -39,9 +39,55 @@ if [[ ${SKIP_FRONTEND_BUILD-} != "" ]]; then
}

generateFile 10k-file.txt 10240
elif [[ $FRONTEND_BUILD_MODE = source ]]; then
log "Building frontend from source..."

if ! [[ -d client ]]; then
log "!!!"
log "!!! No frontend repository found at ./client"
log "!!!"
log "!!! Make sure this directory is present, or change FRONTEND_BUILD_MODE."
log "!!!"
exit 1
fi
if ! [[ -f client/package.json ]]; then
log "!!!"
log "!!! No NodeJS project found in ./client"
log "!!!"
log "!!! Make sure this file is present, or change FRONTEND_BUILD_MODE."
log "!!!"
exit 1
fi

cd client

exit
else
npm clean-install --no-audit --fund=false --update-notifier=false
NODE_OPTIONS="--max-old-space-size=2048" npm run build

mv dist ..
elif [[ $FRONTEND_BUILD_MODE = fetch ]]; then
log "Fetching pre-built frontend..."

filename="dist-$FRONTEND_VERSION.tar.gz"

artifactUrl="https://github.com/getodk/central-frontend/releases/download/$FRONTEND_VERSION/$filename"
log "Fetching release artifact from $artifactUrl ..."
curl \
--connect-timeout 60 \
--fail \
--retry 5 \
--retry-delay 10 \
--retry-all-errors \
--location "$artifactUrl" \
--output "$filename"

log "Extracting dist bundle..."
tar --extract --file "$filename"
else
log "!!!"
log "!!! Unrecognised FRONTEND_BUILD_MODE: '$FRONTEND_BUILD_MODE'"
log "!!!"
exit 1
fi

log "Completed OK."
44 changes: 40 additions & 4 deletions files/prebuild/write-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,47 @@
set -o pipefail
shopt -s inherit_errexit

log() {
echo >&2 "[write-version] $*"
}

print_version() {
printf ' %s %s (%s)\n' "$1" "$2" "$3"
}

git_version() {
local path="$1"
pushd "$path" >/dev/null
commit="$(git rev-parse HEAD)"
tag="$(git describe --tags --always)"
print_version "$commit" "$path" "$tag"
popd >/dev/null
}

{
echo "versions:"
echo "$(git rev-parse HEAD) ($(git describe --tags --always))"
git submodule foreach --quiet --recursive \
"commit=\$(git rev-parse HEAD); \
tag=\$(git describe --tags --always); \
printf ' %s %s (%s)\n' \"\$commit\" \"\$path\" \"\$tag\""

if [[ "$FRONTEND_BUILD_MODE" = fetch ]] || [[ "$FRONTEND_BUILD_MODE" = test ]]; then
print_version 0000000000000000000000000000000000000000 client "$FRONTEND_VERSION"
elif [[ "$FRONTEND_BUILD_MODE" = source ]]; then
if ! [[ -d ./client/.git ]]; then
log "!!!"
log "!!! No frontend git repository found at ./client/.git"
log "!!!"
log "!!! Make sure this directory is present, or change FRONTEND_BUILD_MODE."
log "!!!"
exit 1
fi

git_version client
else
log "!!!"
log "!!! Unrecognised FRONTEND_BUILD_MODE: '$FRONTEND_BUILD_MODE'"
log "!!!"
exit 1
fi

git_version server

} > /tmp/version.txt
10 changes: 7 additions & 3 deletions nginx.dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
FROM node:24.14.1-slim AS intermediate

ARG FRONTEND_BUILD_MODE
ARG FRONTEND_VERSION

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
&& rm -rf /var/lib/apt/lists/*

COPY ./ ./
RUN files/prebuild/write-version.sh

ARG SKIP_FRONTEND_BUILD
RUN files/prebuild/write-version.sh
RUN files/prebuild/build-frontend.sh


Expand Down Expand Up @@ -39,7 +43,7 @@ COPY files/nginx/setup-odk.sh \
COPY files/nginx/redirector.conf /usr/share/odk/nginx/
COPY files/nginx/common-headers.conf /usr/share/odk/nginx/
COPY files/nginx/robots.txt /usr/share/nginx/html
COPY --from=intermediate client/dist/ /usr/share/nginx/html
COPY --from=intermediate dist/ /usr/share/nginx/html
COPY --from=intermediate /tmp/version.txt /usr/share/nginx/html

ENTRYPOINT [ "/scripts/setup-odk.sh" ]
13 changes: 0 additions & 13 deletions test/check-submodules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,12 @@ not_rel() {
}

check_submodules() {
local actualClientSubmodule
local actualServerSubmodule

actualClientSubmodule="$(git config --file .gitmodules --get submodule.client.url)"
actualServerSubmodule="$(git config --file .gitmodules --get submodule.server.url)"

local expectedClientSubmodule=https://github.com/getodk/central-frontend.git
local expectedServerSubmodule=https://github.com/getodk/central-backend.git

if ! [[ "$actualClientSubmodule" = "$expectedClientSubmodule" ]]; then
log "!!!"
log "!!! client submodule is pointing to unexpected repo:"
log "!!!"
log "!!! actual: $actualClientSubmodule"
log "!!! expected: $expectedClientSubmodule"
log "!!!"
exit 1
fi

if ! [[ "$actualServerSubmodule" = "$expectedServerSubmodule" ]]; then
log "!!!"
log "!!! server submodule is pointing to unexpected repo:"
Expand Down
3 changes: 2 additions & 1 deletion test/nginx/lib.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ services:
context: ../..
dockerfile: nginx.dockerfile
args:
SKIP_FRONTEND_BUILD: true
FRONTEND_BUILD_MODE: test
FRONTEND_VERSION: v0.0.0
depends_on:
- service
- enketo
Expand Down
Loading
Loading