Artifacts & Releases
Artifacts#
Standard artifacts: keywords (paths, exclude, reports, needs, dependencies, when, expire_in) work the same as production GitLab CI. This page covers glci-specific behavior and differences.
How artifacts work in glci#
- A job finishes and the runner uploads its
artifacts: paths:as a zip archive to the mock server. - The mock server holds the artifact in memory for the life of the pipeline.
- Downstream jobs that declare
needs:ordependencies:on the upstream job automatically receive the artifact zip, which the runner extracts into the build directory before running the job’s script.
Artifact size is not capped. With a local Docker daemon, needs: downloads go straight from the runner to the mock server. Across runs, the daemon copies the archive to and from the history store in 32 MiB chunks, so multi-gigabyte archives (container images, OS images) also survive --reuse-artifacts.
Two practical limits remain. Artifacts live in the mock server’s memory, so their size is bounded by available RAM rather than by a configured maximum. And with a remote Docker daemon the runner reaches the mock server through the muxproto relay, which carries at most 1 GB per request — including multipart overhead, so the usable archive is marginally smaller. A larger upload fails with 413, a larger download with 502. Neither is ever truncated silently.
artifacts: reports: entries (junit, cobertura, sast, etc.) are passed through to the runner but glci does not render or aggregate them. The raw report files are included in the artifact archive and can be inspected via glci artifacts inspect or glci artifacts extract.
Exception: artifacts: reports: dotenv is fully supported. When a job uploads a dotenv report, glci extracts the KEY=VALUE pairs and injects them as variables into downstream jobs that declare needs: or dependencies: on the producer — matching GitLab CI behavior. When neither needs: nor dependencies: is specified, dotenv variables propagate from all jobs in prior stages (the default dependency behavior).
Limits: a dotenv artifact may contain at most 20 variables (matching GitLab’s default). The decompressed file must be under 5 MB. Variables beyond the limit are silently dropped. Keys must match [a-zA-Z_][a-zA-Z0-9_]*; lines with invalid keys or format are skipped.
producer:
script: echo "MY_VAR=hello" > variables.env
artifacts:
reports:
dotenv: variables.env
consumer:
needs: [producer]
script: echo $MY_VAR # prints "hello"
Reusing artifacts across runs#
When iterating on a failing job, skip re-running upstream dependencies if their artifacts already exist from a prior pipeline:
glci run --reuse-artifacts test-integration
The stored archive is re-injected into the mock server for the skipped job, so downstream jobs download exactly the bytes the earlier run produced. If the archive cannot be read or injected, the job runs for real instead of being marked reused — the reason is logged to the daemon log (glci daemon logs) and the job reports its real result instead of reused.
CLI commands#
List:
glci artifacts list # from latest pipeline
glci artifacts list 38 # from a specific pipeline
glci artifacts list --all # across all pipelines
Download and extract:
glci artifacts download build # latest pipeline
glci artifacts download 38 build --output /tmp/b.zip # specific pipeline
glci artifacts extract build # to ./build/
glci artifacts extract 38 build --output /tmp/build/ # specific dir
Inspect and compare:
glci artifacts inspect build # list zip contents without extracting
glci artifacts diff 41 42 --job build # compare between two pipelines
Delete:
glci artifacts delete 38 # all from pipeline #38
glci artifacts delete 38 build # specific job artifact
glci artifacts delete --all # all from all pipelines
glci artifacts delete --older-than 7d # older than 7 days
Pipeline ID is optional for download, extract, and inspect – defaults to the latest pipeline that has artifacts for the named job.
Releases#
The release: keyword works the same as production GitLab CI. glci generates a release step appended to the job’s script (after main script, before after_script). The generated step:
- Checks for
glab>= 1.58.0 in the container. - If found, authenticates via
glab auth login --job-token $CI_JOB_TOKENand runsglab release create. - If
glabis unavailable or too old, falls back torelease-cli create(with a deprecation warning:release-cliwill not be supported after GitLab 20.0).
Release creation goes to the embedded mock server, not the real GitLab API. The release is stored locally and can be browsed via glci releases.
All release: fields are supported: tag_name, name, description, tag_message, ref, milestones, released_at, and assets: links: (with name, url, link_type).
CI_RELEASE_DESCRIPTION is set with raw=true (so $-references are not expanded) and truncated to 1024 characters, matching GitLab’s behavior.
Release assets uploaded to the generic package registry are capped at 1 GB each; a larger upload is rejected with 400 Bad request - File is too large (what the real generic-packages API returns) rather than stored truncated.
CLI commands#
glci releases list # from latest pipeline
glci releases list --all # across all pipelines
glci releases show v1.2.3 # show release details
glci releases download v1.2.3 # download all package files
glci releases download v1.2.3 my-app.tar.gz # download single file
Running release jobs locally#
Standard release: YAML works as-is. Use a tag context to set CI_COMMIT_TAG:
glci run --context tag=v1.2.3 release-job
Troubleshooting#
Artifacts not found by downstream jobs#
- Incorrect
needs:reference: The job name must exactly match (including matrix suffixes). Check withglci show. artifacts: falseon the need: Downstream job will not receive file artifacts. Remove or set totrue. Note:artifacts: falseonly blocks file downloads —artifacts: reports: dotenvvariables still propagate.- Artifact paths don’t match:
artifacts: paths:globs are relative to$CI_PROJECT_DIR.
Artifact upload too large#
Only relevant with a remote Docker daemon, where artifacts travel through the muxproto relay: a request body above 1 GB is rejected with 413 and a response above 1 GB with 502. Narrow artifacts: paths:, use artifacts: exclude:, or run against a local Docker daemon, which has no such limit.
Artifacts missing after daemon restart#
Completed pipeline artifacts are persisted in the history store under ~/.glci/projects/. In-flight artifacts in a pipeline container are lost on daemon restart.
Reports artifacts not visible#
glci does not render report artifacts (junit, cobertura, etc.) – use glci artifacts inspect or glci artifacts extract to access the raw files. The exception is artifacts: reports: dotenv, which is fully processed for variable propagation between jobs.