Run CI on the self-hosted GitLab #2
+101
@@ -0,0 +1,101 @@
|
|||||||
|
# CI for the self-hosted GitLab that replaced GitHub Actions when the account
|
||||||
|
# was suspended on 2026-09-20. This is a port of .github/workflows/ci.yml and
|
||||||
|
# publish.yml, which are kept in the tree for reference and for the day the
|
||||||
|
# appeal succeeds.
|
||||||
|
#
|
||||||
|
# Every `image:` here is pinned to a digest, with the tag it belonged to in the
|
||||||
|
# trailing comment. That is the direct replacement for the SHA-pinned `uses:`
|
||||||
|
# in the Actions workflows: GitLab has no equivalent of an action allowlist, so
|
||||||
|
# the only thing standing between this pipeline and whatever the publisher
|
||||||
|
# pushes to a tag next is the digest. Read the comment for the version; the
|
||||||
|
# digest is what runs. Do not "simplify" one back to a bare tag.
|
||||||
|
#
|
||||||
|
# The runner is a group runner on Web_Host with the host docker socket bound
|
||||||
|
# in, reached over the internal container network rather than
|
||||||
|
# https://git.coffeylabs.org -- that name is Cloudflare-proxied on the Free
|
||||||
|
# plan, which caps request bodies at 100 MB and would break artifact uploads.
|
||||||
|
|
||||||
|
stages: [test, build, publish]
|
||||||
|
|
||||||
|
variables:
|
||||||
|
# Jobs talk to the registry directly on its DNS-only name, never through the
|
||||||
|
# proxy, for the same 100 MB reason.
|
||||||
|
IMAGE: $CI_REGISTRY_IMAGE
|
||||||
|
GIT_DEPTH: "0"
|
||||||
|
|
||||||
|
default:
|
||||||
|
interruptible: true
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- test ------
|
||||||
|
node:
|
||||||
|
stage: test
|
||||||
|
image: node:26-bookworm-slim@sha256:582460f614631b59b824ac6020533b9bf339c7fdf3a6d7db31abb6b4065f0212 # 26-bookworm-slim
|
||||||
|
cache:
|
||||||
|
key:
|
||||||
|
files: [package-lock.json]
|
||||||
|
paths: [.npm/]
|
||||||
|
before_script:
|
||||||
|
- npm config set cache .npm --global
|
||||||
|
script:
|
||||||
|
- npm ci --ignore-scripts
|
||||||
|
- npm run typecheck
|
||||||
|
- npm test
|
||||||
|
- npm run build
|
||||||
|
artifacts:
|
||||||
|
paths: [dist/]
|
||||||
|
expire_in: 1 week
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
|
- if: $CI_COMMIT_TAG
|
||||||
|
|
||||||
|
# --------------------------------------------------------------- build ------
|
||||||
|
# Proves the Dockerfile still builds on every change, without pushing. The
|
||||||
|
# equivalent of ci.yml's final `docker build -t ihasmail:ci .` step.
|
||||||
|
#
|
||||||
|
# Not called `image`: that is a reserved keyword, and a job by that name is
|
||||||
|
# silently read as the global image: setting instead ("image name should be a
|
||||||
|
# string"). Same trap for `stages`, `cache`, `services` and `variables`.
|
||||||
|
docker-build:
|
||||||
|
stage: build
|
||||||
|
image: docker:28-cli@sha256:625d9431a9f54c5a2bc90f24f0e1c3d55b1349fd857dd85035f98c2c9acbdd4d # 28-cli
|
||||||
|
needs: [node]
|
||||||
|
script:
|
||||||
|
- docker build -t ihasmail:ci-$CI_COMMIT_SHORT_SHA .
|
||||||
|
- docker image rm ihasmail:ci-$CI_COMMIT_SHORT_SHA
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
|
|
||||||
|
# ------------------------------------------------------------- publish ------
|
||||||
|
# Tag-driven, replacing the release -> publish workflow_call chain. GitHub
|
||||||
|
# needed that dance because a release cut with GITHUB_TOKEN raises no event;
|
||||||
|
# GitLab has no such rule, so a tag pipeline is enough.
|
||||||
|
#
|
||||||
|
# arm64 is built under QEMU on this amd64 host, not on a native runner as
|
||||||
|
# GitHub's free `ubuntu-24.04-arm` did. It is slow -- tens of minutes for the
|
||||||
|
# npm install and Vite build through instruction translation -- which is
|
||||||
|
# tolerable for a weekly tag and would not be for every push. That is why this
|
||||||
|
# job is tag-only. If arm64 ever starts timing out, the fix is an arm64 runner,
|
||||||
|
# not dropping the platform: TrueNAS and Unraid users pull it.
|
||||||
|
publish:
|
||||||
|
stage: publish
|
||||||
|
image: docker:28-cli@sha256:625d9431a9f54c5a2bc90f24f0e1c3d55b1349fd857dd85035f98c2c9acbdd4d # 28-cli
|
||||||
|
needs: [node]
|
||||||
|
variables:
|
||||||
|
DOCKER_BUILDKIT: "1"
|
||||||
|
before_script:
|
||||||
|
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
|
||||||
|
- docker run --privileged --rm tonistiigi/binfmt --install arm64
|
||||||
|
- docker buildx create --use --name ci-builder --driver docker-container || docker buildx use ci-builder
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
docker buildx build \
|
||||||
|
--platform linux/amd64,linux/arm64 \
|
||||||
|
--tag "$IMAGE:$CI_COMMIT_TAG" \
|
||||||
|
--tag "$IMAGE:latest" \
|
||||||
|
--push .
|
||||||
|
after_script:
|
||||||
|
- docker logout "$CI_REGISTRY" || true
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_TAG
|
||||||
Reference in New Issue
Block a user