diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..449af70 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,87 @@ +# CI on the self-hosted Gitea, ported from .gitlab-ci.yml during the move off +# GitLab (2026-09-22). Gitea reads .gitea/workflows and ignores .github/ once +# this directory exists; .github/workflows stays as it was for GitHub. +# +# There is deliberately no publish job, although publish.yml is in the tree. +# Every tag in this repository is one of ihasmail's own upstream tags, the +# same commits, and at those tags publish.yml pushed to ihasmail's image, not +# an INBUXA one. A tag-driven publish here would ship plain ihasmail under the +# INBUXA name the moment upstream tags reached this project -- which happened +# once, by hand, and was deleted. Add one back only with a release scheme that +# produces tags this repository alone has. +# +# Every job runs in an image pinned by digest (tag in the trailing comment), +# and the only action used is coffey-labs/actions/checkout pinned by SHA. The +# instance resolves short `uses:` against itself, never GitHub, so nothing +# unreviewed can be pulled in. Read the comment for the version; the digest is +# what runs. Do not "simplify" one back to a bare tag. +# +# Jobs run on the runner's `ci-net` network and clone from Gitea's internal +# address, never through the Cloudflare-proxied public name, which caps +# request bodies at 100 MB. +name: ci + +on: + push: + branches: [main] + tags: ['**'] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # -------------------------------------------------------------- test ------ + node: + runs-on: docker + container: + image: node:26-bookworm-slim@sha256:582460f614631b59b824ac6020533b9bf339c7fdf3a6d7db31abb6b4065f0212 # 26-bookworm-slim + env: + NPM_CONFIG_CACHE: ${{ github.workspace }}/.npm + steps: + # version.test.ts shells out to git to resolve a build version, and the + # slim image ships without it; the checkout action installs it when it + # is missing, so it is there for the tests too. Full history, because + # the version is computed from it. + - uses: coffey-labs/actions/checkout@fab0c4d45e0162963965f1555df27b7bed5e20ec + with: + fetch-depth: 0 + # config.test.ts chmods a directory to 0555 and expects the write to be + # refused. Root ignores the permission bits, so as root that assertion + # can never hold. The tests run as the image's unprivileged `node` user + # for that reason; -p keeps the environment. + # + # imageproxy.test.ts needs IPv6 as well, which is not set here but on the + # runner: jobs run on the `ci-net` docker network, created with --ipv6. + # Without a non-loopback IPv6 address on the container, getaddrinfo's + # AI_ADDRCONFIG drops ::1 from the results entirely, localhost resolves + # to IPv4 only, and the test's control case connects to a port nothing + # is listening on. That is a runner property, so it cannot be fixed from + # this file -- if these tests ever fail again with ECONNREFUSED on + # 127.0.0.1, check that the runner still puts jobs on an IPv6-enabled + # network. + - run: chown -R node:node "$GITHUB_WORKSPACE" + - run: su node -p -c "npm ci --ignore-scripts" + - run: su node -p -c "npm run typecheck" + - run: su node -p -c "npm test" + - run: su node -p -c "npm run build" + + # ------------------------------------------------------------- build ------ + # Proves the Dockerfile still builds on every change, without pushing. The + # equivalent of ci.yml's final `docker build -t ihasmail:ci .` step. The + # Dockerfile builds everything itself; `needs` only keeps the order. + docker-build: + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + needs: [node] + runs-on: docker + container: + image: docker:28-cli@sha256:625d9431a9f54c5a2bc90f24f0e1c3d55b1349fd857dd85035f98c2c9acbdd4d # 28-cli + volumes: + - /var/run/docker.sock:/var/run/docker.sock + steps: + - uses: coffey-labs/actions/checkout@fab0c4d45e0162963965f1555df27b7bed5e20ec + - run: | + tag="ihasmail:ci-$(echo "$GITHUB_SHA" | cut -c1-8)" + docker build -t "$tag" . + docker image rm "$tag"