Skip to content

feat: add GitLab runner provider - #44

Merged
Eli Bosley (elibosley) merged 3 commits into
unraid:mainfrom
jonschumaker:feat/gitlab-provider
Aug 6, 2026
Merged

feat: add GitLab runner provider#44
Eli Bosley (elibosley) merged 3 commits into
unraid:mainfrom
jonschumaker:feat/gitlab-provider

Conversation

@jonschumaker

@jonschumaker jonschumaker commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Add GitLab as a second CI provider while preserving the existing GitHub Actions runner behavior and keeping GitHub as the default.

The implementation consumes the official GitLab Runner image and uses the modern reusable glrt- authentication-token workflow. Each farm slot gets a persistent runner manager identity and an isolated Docker executor backed by a private, per-slot DinD daemon over a Unix socket.

What changed

  • Add CI_PROVIDER=github|gitlab and extract provider-specific behavior into GitHub and GitLab adapters.
  • Preserve the existing GitHub credentials, lifecycle, status, scaling, and runner-image behavior.
  • Add per-slot GitLab Runner managers with persistent config.toml and .runner_system_id files.
  • Generate Docker-executor configuration with per-build networks, resource limits, cache mounts, registry-mirror support, image/service allowlists, pull policy, shared-memory sizing, and job timeout controls.
  • Keep the Unraid Docker socket private by default. Isolated GitLab slots use privileged DinD sidecars over a shared Unix socket and publish no Docker TCP API.
  • Support an explicitly selected host-socket mode, while rejecting GitLab configurations where both DinD and socket sharing are disabled.
  • Add GitLab URL, runner image, monitored projects, runner token, optional API token, and self-managed CA settings to the Dynamix UI and request handlers.
  • Add provider-neutral fleet status fields while retaining existing GitHub fields for compatibility.
  • Update deployment and packaging so the complete runtime tree, including provider adapters, is synchronized.
  • Guard release automation so pushes from forks cannot publish upstream releases.
  • Add a Linux-based validation environment and mocked provider/security/configuration tests.

Why

CI Runner Farm currently manages only GitHub Actions runners. This adds GitLab.com and self-managed GitLab support without forking GitLab Runner itself or duplicating the farm's Docker, cache, locking, scaling, reconciliation, and image-update lifecycle.

The private DinD design reduces exposure compared with mounting Unraid's Docker socket into jobs. It deliberately limits the remaining privileged-Docker blast radius to one single-concurrency farm slot and surfaces that limitation in the UI.

Compatibility and security

  • GitHub remains the upgrade-safe default and retains the legacy PAT path and actions.
  • GitLab requires a modern authentication token beginning with glrt-; an API token is optional and is used only for advisory dashboard data.
  • Runner scope, tags, protected status, and untagged-job policy remain controlled in GitLab.
  • Credential and per-slot configuration files are mode-restricted and excluded from diagnostics.
  • GitLab DinD uses only /runner-services/docker.sock; the sidecar has no host bindings and no listeners on ports 2375 or 2376.
  • Graceful manager shutdown uses SIGQUIT with a configurable stop timeout.

Validation

  • bash tests/run-linux-checks.sh
    • Bash and PHP syntax
    • configuration parity and safe-path checks
    • XML, MD5, package-content, ownership, CSRF, firewall-transition, and release-guard checks
    • mocked GitHub/GitLab provider contracts, policy, token-redaction, URL-normalization, and generated-TOML tests
    • official GitLab Runner configuration parse validation
  • Real privileged docker:27-dind validation confirmed the private Unix socket works and ports 2375/2376 are not listening.
  • Installed the development package on an Unraid host while preserving existing configuration and credentials.
  • Completed a private GitLab project smoke test through the new runner:
    • 5,301 backend tests passed
    • 179 frontend test files passed
    • autoscaling created additional slots as demand increased
    • build, helper, service, and DinD containers received the configured 8 CPU / 8 GiB limits
    • no OOMs, container restarts, Docker TCP exposure, or residual executor containers were observed

Operational notes

  • GitLab queue counts are advisory and limited to configured monitored projects because GitLab does not expose a complete eligible-runner queue through a public API.
  • A privileged DinD sidecar does not provide a hard security boundary from the Unraid host; the UI and documentation call this out explicitly.
  • EPHEMERAL, RUN_AS_ROOT, and workspace tmpfs controls remain GitHub-specific because the GitLab Docker executor provides different job-isolation semantics.

Summary by CodeRabbit

  • New Features
    • Added GitLab CI/CD support alongside GitHub Actions, including provider selection, tokens, project monitoring, Docker execution, autoscaling, caching, and registry settings.
    • Added provider-specific runner images, job metadata, status reporting, and lifecycle controls.
    • Added GitLab force-forget and graceful shutdown options.
  • Security & Reliability
    • Strengthened credential handling, request validation, resource ownership checks, deployment safety, rollback protection, and release safeguards.
  • Documentation
    • Updated installation, configuration, security, provider behavior, and Community Applications documentation for GitHub and GitLab fleets.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jonschumaker, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 22 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3885417e-67e9-4f41-91ee-39f99ce15418

📥 Commits

Reviewing files that changed from the base of the PR and between 67485d4 and abb042c.

📒 Files selected for processing (14)
  • deploy.sh
  • install-dev.sh
  • src/usr/local/emhttp/plugins/ci-runner-farm/default.Dockerfile
  • src/usr/local/emhttp/plugins/ci-runner-farm/default.github.Dockerfile
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/github.sh
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/gitlab.sh
  • tests/config-parity.sh
  • tests/deploy-uninstall-safety.sh
  • tests/gitlab-runner-lint.sh
  • tests/install-dev-safety.sh
  • tests/linux-checks.Dockerfile
  • tests/package-contents.sh
  • tests/provider-contract.sh
  • tests/provider-mocks.sh
📝 Walkthrough

Walkthrough

The change adds GitLab CI/CD support beside GitHub Actions, introduces provider-aware runner lifecycle and UI behavior, hardens credentials and resource ownership, adds deterministic development packaging and safe deployment, and expands repository validation and release protections.

Changes

Provider-aware runner fleet

Layer / File(s) Summary
Provider contracts, configuration, and UI
src/usr/local/emhttp/plugins/ci-runner-farm/...
Adds GitLab settings, credentials, Dockerfiles, provider-specific API actions, provider-neutral status metadata, image editing, and force-forget controls.
Provider adapters and fleet lifecycle
src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/*, src/usr/local/emhttp/plugins/ci-runner-farm/include/runner-farm.sh
Adds GitHub and GitLab adapters for registration, job execution, telemetry, validation, scaling, shutdown, cleanup, ownership checks, and credential reconciliation.
Packaging, staging, and rollback
build-plg.sh, deploy.sh, install-dev.sh
Adds deterministic development artifacts, staged deployment with rollback, fleet locks, Docker ownership checks, and fail-closed install or removal behavior.
Repository and safety validation
tests/*
Adds repository-wide syntax, contract, policy, ownership, firewall, packaging, deployment, installation, CSRF, and GitLab Runner configuration tests.
Documentation and release wiring
README.md, community-applications/*, .github/workflows/*
Documents both providers and adds upstream repository guards to release workflows and repository checks.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: elibosley, jmagar

Poem

A rabbit checks the runners in line,
GitHub and GitLab now combine.
Tokens hide, old paths retire,
Safe locks guard the Docker fire.
Packages hop through checks so bright—
The fleet grows strong by morning light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses the required conventional commit format and accurately describes the main GitLab runner provider change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (8)
tests/linux-checks.Dockerfile (1)

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Pin the validation image and APT inputs.

FROM ubuntu:24.04 uses a mutable tag. apt-get install also resolves package versions from the live Ubuntu mirror. A later build can use different tool versions or fail after repository changes.

Pin the base image by digest. Use a timestamped APT snapshot with explicit package versions if Line 1’s reproducibility claim is required.

Also applies to: 6-19

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/linux-checks.Dockerfile` at line 3, Update the
tests/linux-checks.Dockerfile validation image to use an immutable Ubuntu digest
instead of the mutable ubuntu:24.04 tag, and configure APT to use a timestamped
Ubuntu snapshot with explicit versions for every installed package. Preserve the
existing validation packages and commands while ensuring repeated builds resolve
identical inputs.
install-dev.sh (2)

160-160: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unused PACKAGE assignment.

PACKAGE is never read. The tar at line 185 uses $PACKAGE_FILE, and no other reference exists. Shellcheck flags it as SC2034.

♻️ Proposed cleanup
   [ -n "$PACKAGE_FILE" ] && [ -n "$PACKAGE_SHA256" ] && [ -n "$PLUGIN_SHA256" ] && [ -n "$MANIFEST_SHA256" ] \
     || die "bundle validator returned an incomplete result"
-  PACKAGE="$BUNDLE_DIR/$PACKAGE_FILE"
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@install-dev.sh` at line 160, Remove the unused PACKAGE assignment near the
bundle path setup; keep the existing PACKAGE_FILE usage for the tar command
unchanged.

Source: Linters/SAST tools


277-278: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Clean up the temporary baseline and commit directories on failure.

Line 277 creates $dev_root/.rollback.XXXXXX and line 349 creates $artifacts/.commit.XXXXXX. Every fail after those points aborts the remote script and leaves the temporary path on flash. Line 274 only tests $rollback, so the leftovers are never noticed and accumulate across failed runs.

Register a cleanup trap for each temporary path, or remove the leftover before fail exits.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@install-dev.sh` around lines 277 - 278, Update the failure handling in the
rollback and commit flows to clean up both temporary directories created by the
rollback_tmp setup and the corresponding commit-directory creation before fail
exits. Register cleanup traps for each path, or otherwise ensure every fail
after those creations removes the temporary directory, while preserving the
existing rollback check behavior.
tests/package-contents.sh (1)

50-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the new GitLab fail-closed branch in the generated remove action.

The required-line list covers the missing-Docker case and the "resources still exist" case. It omits the two enumeration-failure branches that this PR adds in build-plg.sh (lines 503 and 511): Docker ownership enumeration failed and GitLab executor ownership enumeration failed. Those branches are the fail-closed guard for the new GitLab executor labels, so a regression that drops them passes this test.

💚 Proposed additional assertions
   'cleanup engine is missing and Docker is unavailable' \
+  'cleanup engine is missing and Docker ownership enumeration failed' \
+  'cleanup engine is missing and GitLab executor ownership enumeration failed' \
   'cleanup engine is missing while plugin-owned Docker resources still exist' \
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/package-contents.sh` around lines 50 - 62, Update the
required_remove_line assertions in tests/package-contents.sh to include both
fail-closed messages emitted by the generated remove action: “Docker ownership
enumeration failed” and “GitLab executor ownership enumeration failed.” Keep the
existing required-line checks unchanged.
tests/config-parity.sh (1)

45-49: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the duplicated command -v php test.

Line 45 already records the failure when php is missing. The second command -v php on line 46 only prevents invoking a missing binary, which an elif-style guard expresses more directly.

♻️ Proposed simplification
-command -v php >/dev/null 2>&1 || bad "php is required to validate default.cfg"
-if command -v php >/dev/null 2>&1 \
-   && ! php -r '$v = parse_ini_file($argv[1]); exit(is_array($v) ? 0 : 1);' "$CFG"; then
-  bad "default.cfg is not valid for PHP parse_ini_file (and therefore Unraid parse_plugin_cfg)"
-fi
+if ! command -v php >/dev/null 2>&1; then
+  bad "php is required to validate default.cfg"
+elif ! php -r '$v = parse_ini_file($argv[1]); exit(is_array($v) ? 0 : 1);' "$CFG"; then
+  bad "default.cfg is not valid for PHP parse_ini_file (and therefore Unraid parse_plugin_cfg)"
+fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/config-parity.sh` around lines 45 - 49, In the validation flow around
the initial PHP prerequisite check and the parse_ini_file command, remove the
duplicated command -v php condition and use an elif-style branch so PHP parsing
runs only after the prerequisite succeeds. Preserve the existing bad messages
and validation behavior.
deploy.sh (1)

42-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Match install-dev.sh and allowlist the staging-path suffix.

Line 44 checks only the "$DEST".deploy. prefix. $REMOTE_STAGE is then interpolated into single-quoted remote command strings at lines 49 and 57, so a suffix that contains ' would terminate the quoting. install-dev.sh lines 177-179 already constrain its suffix to [A-Za-z0-9]. Apply the same check here for consistency.

This is hardening, not a privilege gain: the operator already grants the host a root shell.

🛡️ Proposed suffix check
 case "$REMOTE_STAGE" in
   "$DEST".deploy.*) ;;
   *) echo "deploy: remote host returned an unsafe staging path: $REMOTE_STAGE" >&2; exit 1 ;;
 esac
+case "${REMOTE_STAGE#"$DEST".deploy.}" in
+  ''|*[!A-Za-z0-9]*) echo "deploy: remote host returned an unsafe staging suffix: $REMOTE_STAGE" >&2; exit 1 ;;
+esac
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy.sh` around lines 42 - 46, Strengthen the REMOTE_STAGE validation in
deploy.sh by requiring the staging-path suffix after "$DEST".deploy. to contain
only the same allowed alphanumeric characters enforced by install-dev.sh. Keep
rejecting values with an unexpected prefix, and reject any suffix containing
quotes or other non-allowlisted characters before REMOTE_STAGE is used in remote
commands.
tests/gitlab-runner-lint.sh (1)

23-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the two derived preconditions before using them.

Two values are used without a check:

  • Line 23 derives GITLAB_RUNNER_IMAGE with sed from default.cfg. If that line's format changes, the variable becomes empty and line 100 runs docker image inspect "", which reports an unrelated Docker error.
  • Lines 36-40 assume the host provides /etc/ssl/certs/ca-certificates.crt or /etc/ssl/cert.pem. If neither exists, cp aborts the test with cp: cannot stat, not a test message.

Add explicit checks so a failure names the missing precondition.

♻️ Proposed guards
 GITLAB_RUNNER_IMAGE="$(sed -n 's/^GITLAB_RUNNER_IMAGE="\([^"]*\)".*/\1/p' src/usr/local/emhttp/plugins/ci-runner-farm/default.cfg | head -1)"
+[ -n "$GITLAB_RUNNER_IMAGE" ] \
+  || { echo "gitlab-runner-lint: could not read GITLAB_RUNNER_IMAGE from default.cfg" >&2; exit 1; }
@@
 if [ -r /etc/ssl/certs/ca-certificates.crt ]; then
   cp /etc/ssl/certs/ca-certificates.crt "$GITLAB_CA_FILE"
+elif [ -r /etc/ssl/cert.pem ]; then
+  cp /etc/ssl/cert.pem "$GITLAB_CA_FILE"
 else
-  cp /etc/ssl/cert.pem "$GITLAB_CA_FILE"
+  echo "gitlab-runner-lint: no host CA bundle found for the self-managed CA case" >&2
+  exit 1
 fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/gitlab-runner-lint.sh` around lines 23 - 40, In
tests/gitlab-runner-lint.sh, validate that GITLAB_RUNNER_IMAGE extracted from
default.cfg is non-empty before any Docker image inspection, and fail with a
clear precondition message if it is missing. Also update the CA bundle selection
around GITLAB_CA_FILE to check both candidate paths explicitly, reporting a
descriptive failure when neither exists instead of attempting cp and exposing
only its system error.
src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/github.sh (1)

165-166: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Both adapters build name from idx inside the same local statement. Bash expands every word of a declaration command before it creates the locals, so ${idx} in the default for name resolves against the enclosing scope instead of "$1". cmd_recycle calls build_args "$idx" with one argument, which makes the GitHub path reachable and dependent on a dynamically scoped idx. Split the declaration at both sites.

  • src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/github.sh#L165-L166: declare idx on its own line, then declare name with the ${NAME_PREFIX}-${idx} default.
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/gitlab.sh#L744-L745: apply the same split in gitlab_build_manager_args.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/github.sh`
around lines 165 - 166, Split the combined local declarations in
github_build_args so idx is declared before name, allowing name’s
${NAME_PREFIX}-${idx} default to use the function argument; make the same change
in gitlab_build_manager_args at
src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/gitlab.sh lines
744-745. No other behavior should change.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deploy.sh`:
- Around line 102-103: Remove the trailing `|| true` from both `find` commands
that chmod files under `"$stage/nchan"` and `"$stage/event"`, allowing chmod
failures to propagate and fail the deployment. Keep the existing file selection
and permission mode unchanged.
- Around line 261-272: Update the rollback function in deploy.sh to distinguish
signal-triggered execution from ERR-triggered execution: preserve the captured
failure status for ERR, but when invoked by HUP, INT, or TERM, restore the
backup and exit with a non-zero status. Keep the existing rollback and
successful cleanup behavior unchanged.

In `@install-dev.sh`:
- Around line 453-457: Update the legacy mirror verification in install-dev.sh
to match deploy.sh’s provenance checks: validate the ci-runner-mirror
container’s name, image, mount source, and REGISTRY_PROXY_REMOTEURL before
treating it as plugin-owned. Only fail rollback for a matching owned container;
otherwise allow unrelated containers to remain or clearly instruct the operator
to rename them.

In `@src/usr/local/emhttp/plugins/ci-runner-farm/default.github.Dockerfile`:
- Around line 31-39: Update the generated wait-docker.sh script in the
Dockerfile so that after the 90-attempt readiness loop, it performs one final
docker info check and exits nonzero when Docker is still unavailable. Keep exec
"$@" reachable only after successful readiness, allowing the container restart
policy to retry failed startup.

In `@tests/deploy-uninstall-safety.sh`:
- Around line 11-19: Prevent grep-based line lookups from exiting under set
-e/pipefail before diagnostic guards run. In tests/deploy-uninstall-safety.sh
lines 11-19, make first_line tolerate pipeline failures; at lines 128-132, make
runtime_delete_line, package_delete_line, and success_line lookups tolerate
failures and assert all three are nonempty before numeric comparisons. In
tests/install-dev-safety.sh lines 9-14, make line_of tolerate failures. In
tests/provider-mocks.sh lines 1334-1337 and 1186-1187, make stop_line,
unregister_line, job_image_line, and manager_start_line lookups tolerate
failures so existing diagnostics remain reachable.

In `@tests/provider-contract.sh`:
- Around line 190-192: Replace the vacuous Dockerfile assertion in the provider
contract checks with an exact assertion for the legacy unsuffixed GitHub
fallback expression used by the engine. Keep the provider-specific editable and
shipped Dockerfile checks unchanged, and ensure the new condition cannot pass
merely because those strings contain “Dockerfile”.

---

Nitpick comments:
In `@deploy.sh`:
- Around line 42-46: Strengthen the REMOTE_STAGE validation in deploy.sh by
requiring the staging-path suffix after "$DEST".deploy. to contain only the same
allowed alphanumeric characters enforced by install-dev.sh. Keep rejecting
values with an unexpected prefix, and reject any suffix containing quotes or
other non-allowlisted characters before REMOTE_STAGE is used in remote commands.

In `@install-dev.sh`:
- Line 160: Remove the unused PACKAGE assignment near the bundle path setup;
keep the existing PACKAGE_FILE usage for the tar command unchanged.
- Around line 277-278: Update the failure handling in the rollback and commit
flows to clean up both temporary directories created by the rollback_tmp setup
and the corresponding commit-directory creation before fail exits. Register
cleanup traps for each path, or otherwise ensure every fail after those
creations removes the temporary directory, while preserving the existing
rollback check behavior.

In `@src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/github.sh`:
- Around line 165-166: Split the combined local declarations in
github_build_args so idx is declared before name, allowing name’s
${NAME_PREFIX}-${idx} default to use the function argument; make the same change
in gitlab_build_manager_args at
src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/gitlab.sh lines
744-745. No other behavior should change.

In `@tests/config-parity.sh`:
- Around line 45-49: In the validation flow around the initial PHP prerequisite
check and the parse_ini_file command, remove the duplicated command -v php
condition and use an elif-style branch so PHP parsing runs only after the
prerequisite succeeds. Preserve the existing bad messages and validation
behavior.

In `@tests/gitlab-runner-lint.sh`:
- Around line 23-40: In tests/gitlab-runner-lint.sh, validate that
GITLAB_RUNNER_IMAGE extracted from default.cfg is non-empty before any Docker
image inspection, and fail with a clear precondition message if it is missing.
Also update the CA bundle selection around GITLAB_CA_FILE to check both
candidate paths explicitly, reporting a descriptive failure when neither exists
instead of attempting cp and exposing only its system error.

In `@tests/linux-checks.Dockerfile`:
- Line 3: Update the tests/linux-checks.Dockerfile validation image to use an
immutable Ubuntu digest instead of the mutable ubuntu:24.04 tag, and configure
APT to use a timestamped Ubuntu snapshot with explicit versions for every
installed package. Preserve the existing validation packages and commands while
ensuring repeated builds resolve identical inputs.

In `@tests/package-contents.sh`:
- Around line 50-62: Update the required_remove_line assertions in
tests/package-contents.sh to include both fail-closed messages emitted by the
generated remove action: “Docker ownership enumeration failed” and “GitLab
executor ownership enumeration failed.” Keep the existing required-line checks
unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 270eb1f7-2204-40e8-a125-630325e582ab

📥 Commits

Reviewing files that changed from the base of the PR and between bac79ec and 67485d4.

📒 Files selected for processing (42)
  • .dockerignore
  • .github/workflows/lint.yml
  • .github/workflows/release-please.yml
  • .github/workflows/release.yml
  • README.md
  • build-plg.sh
  • community-applications/DESCRIPTION.md
  • community-applications/ci-runner-farm.xml
  • deploy.sh
  • install-dev.sh
  • src/usr/local/emhttp/plugins/ci-runner-farm/README.md
  • src/usr/local/emhttp/plugins/ci-runner-farm/RunnerFarmFleet.page
  • src/usr/local/emhttp/plugins/ci-runner-farm/RunnerFarmImage.page
  • src/usr/local/emhttp/plugins/ci-runner-farm/RunnerFarmSettings.page
  • src/usr/local/emhttp/plugins/ci-runner-farm/default.cfg
  • src/usr/local/emhttp/plugins/ci-runner-farm/default.github.Dockerfile
  • src/usr/local/emhttp/plugins/ci-runner-farm/default.gitlab.Dockerfile
  • src/usr/local/emhttp/plugins/ci-runner-farm/event/docker_started
  • src/usr/local/emhttp/plugins/ci-runner-farm/event/stopping_docker
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/crf-core.php
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/exec.php
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/github.sh
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/providers/gitlab.sh
  • src/usr/local/emhttp/plugins/ci-runner-farm/include/runner-farm.sh
  • tests/check.sh
  • tests/config-parity.sh
  • tests/deploy-uninstall-safety.sh
  • tests/dev-package.sh
  • tests/exec-csrf.sh
  • tests/firewall-transition.sh
  • tests/gitlab-policy.sh
  • tests/gitlab-runner-lint.sh
  • tests/install-dev-safety.sh
  • tests/linux-checks.Dockerfile
  • tests/ownership-safety.sh
  • tests/package-contents.sh
  • tests/provider-contract.sh
  • tests/provider-mocks.sh
  • tests/release-guard.sh
  • tests/resource-ownership.sh
  • tests/run-linux-checks.sh
  • tests/safe-paths.sh

Comment thread deploy.sh Outdated
Comment thread deploy.sh
Comment thread install-dev.sh
Comment thread tests/deploy-uninstall-safety.sh Outdated
Comment thread tests/provider-contract.sh Outdated

Copy link
Copy Markdown
Contributor

Addressed all actionable review feedback in abb042c.

  • Hardened deployment staging, executable permissions, and signal-aware rollback.
  • Added status-preserving development-install temp cleanup and exact legacy-mirror provenance checks.
  • Made GitHub nested-Docker startup fail closed and fixed provider default-name argument scoping.
  • Hardened test diagnostics and exact provider/Dockerfile contracts.
  • Added explicit GitLab lint preconditions and generated-remove fail-closed assertions.
  • Pinned the Linux validation image, dated Ubuntu snapshot, and direct package versions.

Validation completed:

  • bash tests/run-linux-checks.sh
  • clean native ARM64 and emulated AMD64 Linux image builds
  • official GitLab Runner configuration parse fallback
  • focused deploy/install/provider/package checks
  • git diff --check

The generic CodeRabbit docstring-coverage notice is advisory rather than an unresolved thread or repository-enforced check; this Bash/PHP plugin has no docstring construct, so adding pseudo-docstrings would be unrelated churn. CodeRabbit currently reports pass.

@elibosley

Copy link
Copy Markdown
Member

Thanks so much for this contribution jonschumaker - I'm excited to get this bad boy merged, made you a PR to your repo to fix some potential issues, would love for you to test my fixes before merging and then let me know!

@elibosley
Eli Bosley (elibosley) merged commit ae09e32 into unraid:main Aug 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants