Migrate CI from GitLab to Forgejo Actions (#40) #80

Merged
danny merged 5 commits from issue40_migrate_to_forgejo into main 2026-07-09 13:09:28 +01:00
Collaborator

Closes #40.

Replaces .gitlab-ci.yml with .forgejo/workflows/ci.yml - a close translation of the same lint/build/release jobs to Forgejo Actions syntax, using the golang-ci runner label already registered against registry.keyop.co.uk/keyop/docker/golang-ci:1.26.4.

Two deliberate deviations, called out in CLAUDE.md:

  • lint/build run in parallel instead of GitLab's sequential stages (neither depends on the other's output). release still needs both.
  • Dropped the GitLab-specific private-Go-module credential rewrite - unused, go.mod has no dependencies on either git host.

Also retargets .goreleaser.yaml from gitlab_urls to gitea_urls (goreleaser's Gitea client works against Forgejo unchanged) - this needs a GITEA_TOKEN Actions secret with repository write access before the release job can actually publish. I have not set this up myself per your preference to keep Forgejo admin actions in your hands - could you add it (Settings -> Actions -> Secrets, name GITEA_TOKEN)?

Still to verify empirically once this runs: whether runs-on: golang-ci actually pulls the image cleanly (registry credentials on the runner host are outside this repo), and whether actions/checkout@v4 resolves at all from this runner (no actions mirror is visible from here) - I'll watch the real run and fix forward if either breaks.

Separate observation, not acted on: the old GitLab pipeline had a test stage declared with no job ever assigned to it - go test ./... was never actually run in CI, only lint/static checks. Flagging it since it seems like an oversight, not fixing it here (bigger scope than this migration).

make lint/test/build/package all pass locally.

Closes #40. Replaces `.gitlab-ci.yml` with `.forgejo/workflows/ci.yml` - a close translation of the same `lint`/`build`/`release` jobs to Forgejo Actions syntax, using the `golang-ci` runner label already registered against `registry.keyop.co.uk/keyop/docker/golang-ci:1.26.4`. Two deliberate deviations, called out in CLAUDE.md: - `lint`/`build` run in parallel instead of GitLab's sequential stages (neither depends on the other's output). `release` still needs both. - Dropped the GitLab-specific private-Go-module credential rewrite - unused, `go.mod` has no dependencies on either git host. Also retargets `.goreleaser.yaml` from `gitlab_urls` to `gitea_urls` (goreleaser's Gitea client works against Forgejo unchanged) - this needs a `GITEA_TOKEN` Actions secret with repository write access before the `release` job can actually publish. I have not set this up myself per your preference to keep Forgejo admin actions in your hands - could you add it (Settings -> Actions -> Secrets, name `GITEA_TOKEN`)? **Still to verify empirically once this runs**: whether `runs-on: golang-ci` actually pulls the image cleanly (registry credentials on the runner host are outside this repo), and whether `actions/checkout@v4` resolves at all from this runner (no actions mirror is visible from here) - I'll watch the real run and fix forward if either breaks. Separate observation, not acted on: the old GitLab pipeline had a `test` stage declared with no job ever assigned to it - `go test ./...` was never actually run in CI, only lint/static checks. Flagging it since it seems like an oversight, not fixing it here (bigger scope than this migration). `make lint`/`test`/`build`/`package` all pass locally.
claude self-assigned this 2026-07-09 10:18:39 +01:00
Migrate CI from GitLab to Forgejo Actions (#40)
Some checks failed
CI / lint (push) Has been cancelled
CI / build (push) Has been cancelled
CI / release (push) Has been cancelled
CI / lint (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / release (pull_request) Has been cancelled
ffaf469c8a
The canonical repo moved to forgejo.keyop.co.uk/keyop-go/nfq_forwarder.
Replaces .gitlab-ci.yml with .forgejo/workflows/ci.yml, a close
translation of the same lint/build/release jobs to Forgejo Actions
syntax, using the 'golang-ci' runner label already registered against
registry.keyop.co.uk/keyop/docker/golang-ci:1.26.4 - the same image
.gitlab-ci.yml used, so no per-job container: block is needed.

Two deliberate deviations from a strict 1:1 translation:
- lint and build run in parallel (no needs: between them) rather than
  GitLab's sequential lint-then-build stages, since neither's output
  feeds the other. release still needs: [lint, build].
- Dropped the GitLab-specific private-Go-module credential rewrite
  (CI_JOB_TOKEN/CI_SERVER_HOST insteadOf, ~/.netrc) - go.mod has no
  dependencies on either git host, so it was doing nothing under GitLab
  either.

Retargets .goreleaser.yaml from gitlab_urls/changelog.use: gitlab to
gitea_urls/use: gitea - goreleaser's Gitea client works against Forgejo
unchanged. No gitea equivalent of use_package_registry exists, so
release assets now attach directly to the Forgejo Release. Needs a
GITEA_TOKEN Actions secret (not yet provisioned - Forgejo-side admin
actions are Danny's to run per his stated preference).

make lint/test/build/package all still pass locally.
Trigger a fresh Actions run to test runner pickup after restart
Some checks failed
CI / lint (push) Failing after 1s
CI / build (push) Failing after 0s
CI / lint (pull_request) Failing after 0s
CI / build (pull_request) Failing after 0s
CI / release (push) Has been skipped
CI / release (pull_request) Has been skipped
8693456217
Re-trigger Actions run against the rebuilt golang-ci image
Some checks failed
CI / lint (push) Failing after 0s
CI / build (push) Failing after 0s
CI / release (push) Has been skipped
CI / lint (pull_request) Successful in 25s
CI / build (pull_request) Failing after 23s
CI / release (pull_request) Has been skipped
37c5d4f8a4
Downgrade upload-artifact to v3 (#40)
All checks were successful
CI / lint (push) Successful in 24s
CI / build (push) Successful in 26s
CI / lint (pull_request) Successful in 24s
CI / build (pull_request) Successful in 26s
CI / release (push) Has been skipped
CI / release (pull_request) Has been skipped
edb207aa21
v4+ uses a newer artifact backend protocol Forgejo doesn't support yet:

  GHESNotSupportedError: @actions/artifact v2.0.0+, upload-artifact@v4+
  and download-artifact@v4+ are not currently supported on GHES.

v3 uses the older, supported protocol. Confirmed via a real run that
everything before this step (checkout, make package, the full goreleaser
build producing all four package formats) already succeeds - this was
the last failure.
Author
Collaborator

CI is fully green now (lint/build succeed, release correctly skips on a non-tag push) - confirmed end to end via a real run, not just config review.

Root causes hit and fixed along the way (all infra-side, resolved outside this repo by Danny):

  1. Runner was registered at the wrong scope (personal-user, not org/instance) - queued jobs never got picked up at all.
  2. registry.keyop.co.uk needed auth the runner did not have - resolved by moving the golang-ci image to Forgejos own registry instead (forgejo.keyop.co.uk/keyop-go/golang-ci).
  3. The image layer hit nginxs client_max_body_size (413) - fixed by both raising the limit and trimming the image (go install leaves module/build caches behind - cleaning them dropped a 3.97GB layer to 229MB).
  4. actions/checkout@v4 needs Node.js inside the job container (Forgejo runs JS actions via node in-container, not on the runner host) - added nodejs to the image.
  5. The dynamically-spawned job container could not resolve forgejo.keyop.co.uk (nested Docker-in-Docker breaks the host-gateway magic value - it resolves to the nested dinds own bridge gateway, not the real host) - fixed with an explicit --add-host=forgejo.keyop.co.uk:<real-host-ip> in the runners container.options.
  6. actions/upload-artifact@v4 uses a newer artifact protocol Forgejo does not support yet (GHESNotSupportedError) - downgraded to @v3.

Still outstanding before merge: a GITEA_TOKEN Actions secret needs provisioning for the release job to actually publish on a real tag push - that path is config-reviewed but not yet exercised end to end (deliberately not testing with a real tag in this PR).

CI is fully green now (`lint`/`build` succeed, `release` correctly skips on a non-tag push) - confirmed end to end via a real run, not just config review. Root causes hit and fixed along the way (all infra-side, resolved outside this repo by Danny): 1. Runner was registered at the wrong scope (personal-user, not org/instance) - queued jobs never got picked up at all. 2. `registry.keyop.co.uk` needed auth the runner did not have - resolved by moving the golang-ci image to Forgejos own registry instead (`forgejo.keyop.co.uk/keyop-go/golang-ci`). 3. The image layer hit nginxs `client_max_body_size` (413) - fixed by both raising the limit and trimming the image (go install leaves module/build caches behind - cleaning them dropped a 3.97GB layer to 229MB). 4. `actions/checkout@v4` needs Node.js inside the job container (Forgejo runs JS actions via `node` in-container, not on the runner host) - added `nodejs` to the image. 5. The dynamically-spawned job container could not resolve `forgejo.keyop.co.uk` (nested Docker-in-Docker breaks the `host-gateway` magic value - it resolves to the nested dinds own bridge gateway, not the real host) - fixed with an explicit `--add-host=forgejo.keyop.co.uk:<real-host-ip>` in the runners `container.options`. 6. `actions/upload-artifact@v4` uses a newer artifact protocol Forgejo does not support yet (`GHESNotSupportedError`) - downgraded to `@v3`. Still outstanding before merge: a `GITEA_TOKEN` Actions secret needs provisioning for the `release` job to actually publish on a real tag push - that path is config-reviewed but not yet exercised end to end (deliberately not testing with a real tag in this PR).
Rename release secret to RELEASE_TOKEN (#40)
All checks were successful
CI / lint (push) Successful in 26s
CI / build (push) Successful in 26s
CI / lint (pull_request) Successful in 24s
CI / build (pull_request) Successful in 27s
CI / release (push) Has been skipped
CI / release (pull_request) Has been skipped
75a5aee0a4
Forgejo rejects a stored secret literally named GITEA_TOKEN (blocks the
GITEA_/FORGEJO_/GITHUB_ prefixes, to stop secrets shadowing its own
auto-injected ones) - but that's only a restriction on the secret's
stored name, not on what environment variable name a workflow step can
expose it as. The secret is now named RELEASE_TOKEN and mapped to the
GITEA_TOKEN env var goreleaser's Gitea client actually reads:

  env:
    GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
danny requested review from danny 2026-07-09 13:06:28 +01:00
danny approved these changes 2026-07-09 13:09:11 +01:00
danny left a comment

All looks good to me.

All looks good to me.
danny merged commit 9d7fad8798 into main 2026-07-09 13:09:28 +01:00
danny deleted branch issue40_migrate_to_forgejo 2026-07-09 13:09:29 +01:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
keyop-go/nfq_forwarder!80
No description provided.