ci: build the image
- commit
- a873e08622b13cbb3ed3d25b2fa06ddd4def80b5
- author
- brice · · 2026-10-10 11:55 UTC
- parent
- 63f8a7f
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +45 -0
M .forgejo/workflows/ci.yml +27 -0
| @@ -94,3 +94,30 @@ jobs: | |||
| 94 | 94 | go generate ./internal/ports | |
| 95 | 95 | git diff --exit-code -- internal/ports/mocks/ | |
| 96 | 96 | test -z "$(git status --porcelain -- internal/ports/mocks/)" | |
| 97 | + | ||
| 98 | + | image: | |
| 99 | + | name: Image | |
| 100 | + | # Build only, nothing is pushed. The arch job container gets the runner's rootless | |
| 101 | + | # Podman socket as /var/run/docker.sock (docker_host in ci-runner/config.yml), so the | |
| 102 | + | # docker CLI builds through Podman. | |
| 103 | + | runs-on: arch | |
| 104 | + | steps: | |
| 105 | + | - name: System packages | |
| 106 | + | run: pacman -Syu --noconfirm --needed git docker | |
| 107 | + | - uses: actions/checkout@v6 | |
| 108 | + | with: | |
| 109 | + | # git describe needs the tags for the image version. | |
| 110 | + | fetch-depth: 0 | |
| 111 | + | # The build container is a nested container: it reaches Forgejo on the host loopback | |
| 112 | + | # the same way the job container does (10.0.2.2, see vps-infra homelab/igor/ci-runner). | |
| 113 | + | - name: Build the image | |
| 114 | + | run: | | |
| 115 | + | docker build \ | |
| 116 | + | --add-host git.bnema.dev:10.0.2.2 \ | |
| 117 | + | --build-arg GIT_REWRITE_BASE=http://git.bnema.dev:8088/ \ | |
| 118 | + | --build-arg VERSION="$(git describe --tags --always --dirty)" \ | |
| 119 | + | -t ermite:ci . | |
| 120 | + | - name: Smoke test | |
| 121 | + | run: | | |
| 122 | + | docker run --rm ermite:ci version | |
| 123 | + | docker run --rm --entrypoint git ermite:ci --version | |
| @@ -94,3 +94,30 @@ jobs: | |||||
| 94 | go generate ./internal/ports | 94 | go generate ./internal/ports | ||
| 95 | git diff --exit-code -- internal/ports/mocks/ | 95 | git diff --exit-code -- internal/ports/mocks/ | ||
| 96 | test -z "$(git status --porcelain -- internal/ports/mocks/)" | 96 | test -z "$(git status --porcelain -- internal/ports/mocks/)" | ||
| 97 | + | ||||
| 98 | + | image: | |||
| 99 | + | name: Image | |||
| 100 | + | # Build only, nothing is pushed. The arch job container gets the runner's rootless | |||
| 101 | + | # Podman socket as /var/run/docker.sock (docker_host in ci-runner/config.yml), so the | |||
| 102 | + | # docker CLI builds through Podman. | |||
| 103 | + | runs-on: arch | |||
| 104 | + | steps: | |||
| 105 | + | - name: System packages | |||
| 106 | + | run: pacman -Syu --noconfirm --needed git docker | |||
| 107 | + | - uses: actions/checkout@v6 | |||
| 108 | + | with: | |||
| 109 | + | # git describe needs the tags for the image version. | |||
| 110 | + | fetch-depth: 0 | |||
| 111 | + | # The build container is a nested container: it reaches Forgejo on the host loopback | |||
| 112 | + | # the same way the job container does (10.0.2.2, see vps-infra homelab/igor/ci-runner). | |||
| 113 | + | - name: Build the image | |||
| 114 | + | run: | | |||
| 115 | + | docker build \ | |||
| 116 | + | --add-host git.bnema.dev:10.0.2.2 \ | |||
| 117 | + | --build-arg GIT_REWRITE_BASE=http://git.bnema.dev:8088/ \ | |||
| 118 | + | --build-arg VERSION="$(git describe --tags --always --dirty)" \ | |||
| 119 | + | -t ermite:ci . | |||
| 120 | + | - name: Smoke test | |||
| 121 | + | run: | | |||
| 122 | + | docker run --rm ermite:ci version | |||
| 123 | + | docker run --rm --entrypoint git ermite:ci --version | |||
M README.md +18 -0
| @@ -53,6 +53,24 @@ Use the admin token (`ERMITE_ADMIN_TOKEN`) or a stored token as the password; th | |||
| 53 | 53 | ||
| 54 | 54 | The server keeps its runtime files in `$ERMITE_DATA_DIR/run/` (the hook socket and scripts that git calls on each push); the hook socket path must stay under about 100 bytes. | |
| 55 | 55 | ||
| 56 | + | ## Run with Docker | |
| 57 | + | ||
| 58 | + | ```sh | |
| 59 | + | docker build --build-arg VERSION="$(git describe --tags --always --dirty)" -t ermite . | |
| 60 | + | docker run -d -p 7341:7341 -v ermite-data:/data \ | |
| 61 | + | -e ERMITE_PUBLIC_URL=http://localhost:7341 -e ERMITE_ADMIN_TOKEN="$(head -c 32 /dev/urandom | base64)" ermite | |
| 62 | + | ``` | |
| 63 | + | ||
| 64 | + | The image is alpine with git, runs as uid 10001 and keeps its data in the `/data` volume. Logs are JSON by default. The build fetches `bnema.dev/ermite-*` from `git.bnema.dev`, so the host must reach it (NetBird); the build container uses the host's DNS and routes. Behind another route, pass `--build-arg GIT_REWRITE_BASE=http://git.bnema.dev:8088/` (and `--add-host`), as the CI job does. | |
| 65 | + | ||
| 66 | + | ## Develop with compose | |
| 67 | + | ||
| 68 | + | ```sh | |
| 69 | + | docker compose up | |
| 70 | + | ``` | |
| 71 | + | ||
| 72 | + | Serves on `http://localhost:7341` with the development admin token in `compose.yaml`. The source is mounted and [air](https://github.com/air-verse/air) (`go tool air`, `.air.toml`) rebuilds and restarts the server on each change to a `.go` or `.templ` file; the module and build caches and the data live in named volumes. `docker compose down -v` removes them. | |
| 73 | + | ||
| 56 | 74 | ## Build | |
| 57 | 75 | ||
| 58 | 76 | ```sh | |
| @@ -53,6 +53,24 @@ Use the admin token (`ERMITE_ADMIN_TOKEN`) or a stored token as the password; th | |||||
| 53 | 53 | ||||
| 54 | The server keeps its runtime files in `$ERMITE_DATA_DIR/run/` (the hook socket and scripts that git calls on each push); the hook socket path must stay under about 100 bytes. | 54 | The server keeps its runtime files in `$ERMITE_DATA_DIR/run/` (the hook socket and scripts that git calls on each push); the hook socket path must stay under about 100 bytes. | ||
| 55 | 55 | ||||
| 56 | + | ## Run with Docker | |||
| 57 | + | ||||
| 58 | + | ```sh | |||
| 59 | + | docker build --build-arg VERSION="$(git describe --tags --always --dirty)" -t ermite . | |||
| 60 | + | docker run -d -p 7341:7341 -v ermite-data:/data \ | |||
| 61 | + | -e ERMITE_PUBLIC_URL=http://localhost:7341 -e ERMITE_ADMIN_TOKEN="$(head -c 32 /dev/urandom | base64)" ermite | |||
| 62 | + | ``` | |||
| 63 | + | ||||
| 64 | + | The image is alpine with git, runs as uid 10001 and keeps its data in the `/data` volume. Logs are JSON by default. The build fetches `bnema.dev/ermite-*` from `git.bnema.dev`, so the host must reach it (NetBird); the build container uses the host's DNS and routes. Behind another route, pass `--build-arg GIT_REWRITE_BASE=http://git.bnema.dev:8088/` (and `--add-host`), as the CI job does. | |||
| 65 | + | ||||
| 66 | + | ## Develop with compose | |||
| 67 | + | ||||
| 68 | + | ```sh | |||
| 69 | + | docker compose up | |||
| 70 | + | ``` | |||
| 71 | + | ||||
| 72 | + | Serves on `http://localhost:7341` with the development admin token in `compose.yaml`. The source is mounted and [air](https://github.com/air-verse/air) (`go tool air`, `.air.toml`) rebuilds and restarts the server on each change to a `.go` or `.templ` file; the module and build caches and the data live in named volumes. `docker compose down -v` removes them. | |||
| 73 | + | ||||
| 56 | ## Build | 74 | ## Build | ||
| 57 | 75 | ||||
| 58 | ```sh | 76 | ```sh | ||