name: CI on: push: branches: [main] pull_request: branches: [main] workflow_dispatch: env: REGISTRY: gitea.nik4nao.com IMAGE_PREFIX: gitea.nik4nao.com/nik GOPATH: /tmp/go GOMODCACHE: /tmp/go/pkg/mod GOCACHE: /tmp/go-build jobs: # Determines which images actually need rebuilding for this push, so an # edit scoped to one service doesn't rebuild (and re-push) all five. `gen/`, # `go.work`, and `go.work.sum` are treated as shared - a change there can # affect every Go module's resolved dependencies, so it marks all of them # as changed rather than trying to model cross-module version unification # precisely. `test` (go vet/go test) always runs regardless - it's fast and # correctness-critical, not worth gating. changes: runs-on: ubuntu-latest outputs: ai-gateway: ${{ steps.filter.outputs.ai-gateway }} ha-gateway: ${{ steps.filter.outputs.ha-gateway }} discord-bot: ${{ steps.filter.outputs.discord-bot }} tts-gateway: ${{ steps.filter.outputs.tts-gateway }} tts-sidecar: ${{ steps.filter.outputs.tts-sidecar }} steps: - uses: actions/checkout@v6 - uses: dorny/paths-filter@v3 id: filter with: # Deliberately not using YAML anchors to dedupe the shared # gen/**+go.work(.sum) paths across filters here - dorny/paths-filter # parses this block as its own YAML document, and an anchor # substitutes as a nested array (`[[...], 'x/**']`) rather than a # flattened one, which risks silently matching nothing. Spelled out # per-filter instead. filters: | ai-gateway: - 'gen/**' - 'go.work' - 'go.work.sum' - 'ai-gateway/**' ha-gateway: - 'gen/**' - 'go.work' - 'go.work.sum' - 'ha-gateway/**' discord-bot: - 'gen/**' - 'go.work' - 'go.work.sum' - 'discord-bot/**' tts-gateway: - 'gen/**' - 'go.work' - 'go.work.sum' - 'tts-gateway/**' - '!tts-gateway/sidecar/**' tts-sidecar: - 'tts-gateway/sidecar/**' test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: prepare go cache dirs run: mkdir -p "$GOMODCACHE" "$GOCACHE" - uses: actions/setup-go@v6 with: go-version-file: go.work cache-dependency-path: | go.work.sum ai-gateway/go.sum ha-gateway/go.sum discord-bot/go.sum tts-gateway/go.sum gen/go.sum - name: go vet run: | cd gen && go vet ./... cd ../ai-gateway && go vet ./... cd ../ha-gateway && go vet ./... cd ../discord-bot && go vet ./... cd ../tts-gateway && go vet ./... - name: go test run: | cd gen && go test ./... cd ../ai-gateway && go test ./... cd ../ha-gateway && go test ./... cd ../discord-bot && go test ./... cd ../tts-gateway && go test ./... build-ai-gateway: needs: [test, changes] if: github.ref == 'refs/heads/main' && needs.changes.outputs.ai-gateway == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: docker/setup-buildx-action@v4 - uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_PASSWORD }} - uses: docker/build-push-action@v7 with: context: . file: ai-gateway/Dockerfile push: true platforms: linux/amd64 cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}/ai-gateway:buildcache cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}/ai-gateway:buildcache,mode=max tags: | ${{ env.IMAGE_PREFIX }}/ai-gateway:${{ github.sha }} ${{ env.IMAGE_PREFIX }}/ai-gateway:latest build-ha-gateway: needs: [test, changes] if: github.ref == 'refs/heads/main' && needs.changes.outputs.ha-gateway == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: docker/setup-buildx-action@v4 - uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_PASSWORD }} - uses: docker/build-push-action@v7 with: context: . file: ha-gateway/Dockerfile push: true platforms: linux/amd64 cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}/ha-gateway:buildcache cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}/ha-gateway:buildcache,mode=max tags: | ${{ env.IMAGE_PREFIX }}/ha-gateway:${{ github.sha }} ${{ env.IMAGE_PREFIX }}/ha-gateway:latest build-discord-bot: needs: [test, changes] if: github.ref == 'refs/heads/main' && needs.changes.outputs.discord-bot == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: docker/setup-buildx-action@v4 - uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_PASSWORD }} - uses: docker/build-push-action@v7 with: context: . file: discord-bot/Dockerfile push: true platforms: linux/amd64 cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}/discord-bot:buildcache cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}/discord-bot:buildcache,mode=max tags: | ${{ env.IMAGE_PREFIX }}/discord-bot:${{ github.sha }} ${{ env.IMAGE_PREFIX }}/discord-bot:latest build-tts-gateway: needs: [test, changes] if: github.ref == 'refs/heads/main' && needs.changes.outputs.tts-gateway == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: docker/setup-buildx-action@v4 - uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_PASSWORD }} - uses: docker/build-push-action@v7 with: context: . file: tts-gateway/Dockerfile push: true platforms: linux/amd64 cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}/tts-gateway:buildcache cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}/tts-gateway:buildcache,mode=max tags: | ${{ env.IMAGE_PREFIX }}/tts-gateway:${{ github.sha }} ${{ env.IMAGE_PREFIX }}/tts-gateway:latest build-tts-sidecar: needs: [test, changes] if: github.ref == 'refs/heads/main' && needs.changes.outputs.tts-sidecar == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: docker/setup-buildx-action@v4 - uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_PASSWORD }} # CUDA base image makes this a large (~13GB) build/push - it doesn't # need a GPU to build (only to usefully run). Registry cache matters # most here: requirements.txt/Dockerfile rarely change, so cached runs # should skip straight past the apt/pip/Cython layers to just the final # `COPY . .` + re-tagging. - uses: docker/build-push-action@v7 with: context: tts-gateway/sidecar file: tts-gateway/sidecar/Dockerfile push: true platforms: linux/amd64 cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}/tts-sidecar:buildcache cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}/tts-sidecar:buildcache,mode=max tags: | ${{ env.IMAGE_PREFIX }}/tts-sidecar:${{ github.sha }} ${{ env.IMAGE_PREFIX }}/tts-sidecar:latest