Skip to content

Commit 94a5546

Browse files
committed
🐛 fix(fireglab): resolve gitlab-runner execution issues in VMs
- Fix RunOnce() to use run-single with CLI args (--url, --token, --executor, --builds-dir, --cache-dir) instead of --config flag since run-single doesn't read from config.toml - Remove existing config.toml before registration to prevent duplicate [[runners]] entries when service restarts - Store metadata during Register() for use in RunOnce() - Change config path from /etc/gitlab-runner to /home/runner/.gitlab-runner to avoid permission issues when running as runner user - Add --work-dir and --config runtime arguments to systemd service
1 parent 5892451 commit 94a5546

3 files changed

Lines changed: 49 additions & 14 deletions

File tree

fireglab/runner/runner.go

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ type Runner struct {
4545
stdout io.Writer
4646
stderr io.Writer
4747
log *logrus.Logger
48+
// metadata stores registration info for run-single mode
49+
metadata *mmds.Metadata
4850
}
4951

5052
// Option is a functional option for configuring the Runner.
@@ -156,6 +158,13 @@ func (r *Runner) Register(ctx context.Context, metadata *mmds.Metadata) error {
156158
return fmt.Errorf("failed to create config directory: %w", err)
157159
}
158160

161+
// Remove any existing config to prevent duplicate [[runners]] entries on restart
162+
// gitlab-runner register appends to existing config, which causes issues if
163+
// the service restarts after a failed run attempt
164+
if err := os.Remove(r.configPath); err != nil && !os.IsNotExist(err) {
165+
r.log.Warnf("Failed to remove existing config file: %v", err)
166+
}
167+
159168
// Build registration command
160169
// With the new runner authentication tokens (glrt-*), we use --token directly
161170
// The runner was already created via the API, so we just need to register locally
@@ -194,18 +203,21 @@ func (r *Runner) Register(ctx context.Context, metadata *mmds.Metadata) error {
194203
return fmt.Errorf("registration failed: %w", err)
195204
}
196205

206+
// Store metadata for run-single mode
207+
r.metadata = metadata
208+
197209
r.log.Info("Runner registered successfully")
198210
return nil
199211
}
200212

201213
// Run starts the gitlab-runner daemon and blocks until it exits.
202214
// This should be called after Register.
203-
// The daemon runs with --max-builds 1 to exit after completing one job (ephemeral mode).
215+
// The runner will continuously poll for jobs until stopped or the context is cancelled.
204216
func (r *Runner) Run(ctx context.Context) error {
205-
r.log.Info("Starting gitlab-runner daemon (ephemeral mode)")
217+
r.log.Info("Starting gitlab-runner daemon (continuous mode)")
206218

207-
// Use run-single or run with max-builds=1 for ephemeral behavior
208-
// run-single executes exactly one build and then exits
219+
// Use 'run' command which reads from config.toml
220+
// The runner will poll for jobs until the context is cancelled
209221
args := []string{
210222
"run",
211223
"--config", r.configPath,
@@ -256,16 +268,33 @@ func (r *Runner) Run(ctx context.Context) error {
256268
}
257269

258270
// RunOnce starts gitlab-runner to run exactly one job and then exit.
259-
// This uses the run-single command which is designed for ephemeral runners.
271+
// Uses run-single command which processes one job and exits - true ephemeral behavior.
272+
// This requires metadata to be stored during Register().
260273
func (r *Runner) RunOnce(ctx context.Context) error {
261-
r.log.Info("Starting gitlab-runner in single-job mode")
274+
r.log.Info("Starting gitlab-runner in single-job mode (run-single)")
262275

263-
// run-single is specifically designed for ephemeral runners
264-
// It picks up one job, executes it, and exits
276+
if r.metadata == nil {
277+
return fmt.Errorf("metadata not available - Register() must be called before RunOnce()")
278+
}
279+
280+
// Build directories
281+
buildsDir := filepath.Join(r.workDir, "builds")
282+
cacheDir := filepath.Join(r.workDir, "cache")
283+
284+
// Use 'run-single' command which executes exactly one job and exits
285+
// This provides true ephemeral behavior without relying on external VM termination
265286
args := []string{
266287
"run-single",
267-
"--config", r.configPath,
268-
"--wait-timeout", "0", // Wait indefinitely for a job
288+
"--url", r.metadata.GitLabInstanceURL,
289+
"--token", r.metadata.RunnerToken,
290+
"--executor", r.executor,
291+
"--builds-dir", buildsDir,
292+
"--cache-dir", cacheDir,
293+
}
294+
295+
// Add runner name if available
296+
if r.metadata.RunnerName != "" {
297+
args = append(args, "--name", r.metadata.RunnerName)
269298
}
270299

271300
cmd := exec.CommandContext(ctx, r.gitlabRunnerPath, args...)

images/docker/ubuntu-24.04/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ RUN case "$TARGETARCH" in amd64|x86_64|i386) export RUNNER_ARCH="amd64";; arm64)
280280
&& chmod +x gitlab-runner \
281281
&& ln -s /opt/gitlab-runner/gitlab-runner /usr/local/bin/gitlab-runner \
282282
&& chown -R runner:docker /opt/gitlab-runner \
283-
&& mkdir -p /etc/gitlab-runner \
284-
&& chown -R runner:docker /etc/gitlab-runner
283+
&& mkdir -p /home/runner/.gitlab-runner \
284+
&& chown -R runner:docker /home/runner/.gitlab-runner
285285

286286
# Install GitLab CLI (glab)
287287
RUN curl -fsSL https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository | bash \

images/docker/ubuntu-24.04/overlay/gitlab/etc/systemd/system/fireglab.service

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@ User=root
1818
# The runner command:
1919
# 1. Fetches metadata from MMDS (glrt-* token, gitlab URL, tags)
2020
# 2. Registers gitlab-runner with GitLab using the token
21-
# 3. Starts gitlab-runner daemon in single-job mode
21+
# 3. Starts gitlab-runner daemon in single-job mode (run-single)
2222
# 4. Exits when job completes (triggering VM reboot via SuccessAction)
23-
ExecStart=/usr/bin/fireglab runner --log-level=info --single-job
23+
#
24+
# Runtime paths configured for runner user context:
25+
# - work-dir: Runner's home directory for builds/cache
26+
# - config: User-specific config to avoid /etc permission issues
27+
ExecStart=/usr/bin/fireglab runner --log-level=info --single-job \
28+
--work-dir=/home/runner \
29+
--config=/home/runner/.gitlab-runner/config.toml
2430
Restart=on-failure
2531
RestartSec=5s
2632

0 commit comments

Comments
 (0)