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#

  1. A job finishes and the runner uploads its artifacts: paths: as a zip archive to the mock server.
  2. The mock server holds the artifact in memory (or on a mounted volume for persistent mock containers).
  3. Downstream jobs that declare needs: or dependencies: on the upstream job automatically receive the artifact zip, which the runner extracts into the build directory before running the job’s script.

The mock server enforces a 1 GB maximum per artifact upload. There is no configurable override.

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

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:

  1. Checks for glab >= 1.58.0 in the container.
  2. If found, authenticates via glab auth login --job-token $CI_JOB_TOKEN and runs glab release create.
  3. If glab is unavailable or too old, falls back to release-cli create (with a deprecation warning: release-cli will 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.

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#

  1. Incorrect needs: reference: The job name must exactly match (including matrix suffixes). Check with glci show.
  2. artifacts: false on the need: Downstream job will not receive file artifacts. Remove or set to true. Note: artifacts: false only blocks file downloads — artifacts: reports: dotenv variables still propagate.
  3. Artifact paths don’t match: artifacts: paths: globs are relative to $CI_PROJECT_DIR.

Artifact upload too large#

The mock server rejects uploads larger than 1 GB. Narrow artifacts: paths: or use artifacts: exclude:.

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.

Esc