Home Technical Support GitLab CI/CD: Understanding Artifacts, the Package Registry, and YAML Configuration

GitLab CI/CD: Understanding Artifacts, the Package Registry, and YAML Configuration

Last updated on Jan 06, 2026

GitLab CI/CD: Understanding Artifacts, the Package Registry, and YAML Configuration

Introduction

GitLab’s integrated CI/CD platform provides powerful tools for automating builds, tests, and deployments. Two features that often cause confusion are Artifacts and the Package Registry. While both deal with files produced during a pipeline, they serve distinct purposes. This article explains the difference between them, walks through the basics of the Package Registry, clarifies the when: always keyword, and offers practical guidance on when and how to create your .gitlab-ci.yml file. By the end, you’ll know how to store temporary build outputs, publish reusable packages, and configure your pipelines with confidence.


1. Artifacts vs. Package Registry

Aspect Artifacts Package Registry
Purpose Temporary files generated by a pipeline (e.g., compiled binaries, test reports). Permanent storage for reusable packages (Docker images, Maven, npm, PyPI, etc.).
Lifecycle Usually retained for a limited time (default 7 days) and can be automatically expired. Persist until you delete them; they act as a versioned dependency store.
Typical Use‑Cases • Pass build output from one job to the next.• Provide downloadable logs or coverage reports.• Keep artifacts for debugging failed jobs. • Host Docker images for deployment.• Publish internal npm modules.• Share Maven artifacts across micro‑services.
Access Downloaded via the pipeline UI or via API using the job ID. Pulled with standard package managers (docker pull, npm install, mvn dependency:get, etc.).
Configuration Location Inside a job’s artifacts: block in .gitlab-ci.yml. Defined by enabling the appropriate Package Registry feature in the project settings and publishing from a job.

Quick Example

# .gitlab-ci.yml
build:
  stage: build
  script:
    - make compile
  artifacts:
    paths:
      - build/*.jar      # <-- temporary build output
    expire_in: 1 day

publish:
  stage: deploy
  script:
    - docker build -t registry.example.com/myapp:$CI_COMMIT_SHA .
    - docker push registry.example.com/myapp:$CI_COMMIT_SHA
  # No artifacts block – the Docker image lives in the Package Registry

In the snippet above, build creates a JAR file that is stored as an artifact for later jobs. The publish job pushes a Docker image to the Package Registry, where it can be pulled by any downstream environment.


2. What Is the GitLab Package Registry?

The GitLab Package Registry is a unified, self‑hosted repository for a variety of package formats:

  • Docker (container images)
  • Maven (Java libraries)
  • npm (Node.js modules)
  • RubyGems, Python (PyPI), Conan, Helm, and more

Key Benefits

  1. Single Source of Truth – Store all your binaries and libraries alongside the source code.
  2. Access Control – Leverage GitLab’s permission model to restrict who can publish or download packages.
  3. Dependency Management – Use standard tooling (docker, mvn, npm) without external registries.
  4. Traceability – Packages are linked to commits, tags, and pipeline IDs, making audits straightforward.

Publishing a Package (Docker Example)

# .gitlab-ci.yml
docker_build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

After the pipeline runs, the image appears under Packages & Registries → Container Registry in the project UI.


3. The when: always Keyword in Artifacts

Inside the artifacts: Block

test:
  stage: test
  script: npm test
  artifacts:
    when: always          # <-- always upload artifacts
    paths:
      - coverage/
  • Effect: The job will upload the specified paths even if the job fails.
  • Why use it? To retain logs, screenshots, or coverage reports that help debug failures.

Outside the artifacts: Block (Job‑Level when)

cleanup:
  stage: cleanup
  script: ./scripts/cleanup.sh
  when: always            # <-- job runs regardless of previous job status
  • Effect: The job itself executes no matter whether earlier jobs succeeded or failed.
  • Typical use‑case: Clean‑up steps, notifications, or publishing artifacts after a failure.

4. When to Create and Run .gitlab-ci.yml

  1. Early Planning (Recommended)

    • Add a minimal .gitlab-ci.yml at the start of the project to enable CI/CD from day one.
    • Example: a simple lint job that runs on every push.
  2. Late Addition

    • You can add the file later, but remember that pipelines only start after the file exists in the repository.
    • If you need to avoid automatic deployments on the first run, use rules or only/except to limit execution.
  3. Avoiding Unintended Deployments

deploy:
  stage: deploy
  script: ./deploy.sh
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual      # <-- requires manual trigger
  • The rules: block ensures the deployment only runs manually on the main branch, preventing accidental pushes from triggering a production rollout.

5. Practical Tips & Common Questions

Tips

  • Set appropriate expiration for artifacts (expire_in:) to keep storage costs low.
  • Version your packages using semantic versioning; GitLab automatically adds the version tag to the registry.
  • Leverage caching (cache:) for dependencies that don’t need to be stored as artifacts.

Common Questions

Question Answer
Can I download an artifact from a failed job? Yes—use when: always in the artifacts: block to ensure it’s uploaded even on failure.
Do artifacts appear in the Package Registry? No. Artifacts are pipeline‑specific; the Package Registry holds versioned packages meant for reuse across projects.
Do I need a separate registry for each project? Not necessarily. You can push to a shared group-level registry or use the project’s own registry; permissions are inherited from the group.
How do I limit artifact size? Use the paths: list to include only needed files and set expire_in: to control retention.

Conclusion

Understanding the distinction between Artifacts (temporary pipeline outputs) and the Package Registry (persistent, versioned packages) is essential for building efficient GitLab CI/CD pipelines. Use when: always wisely to capture valuable debugging information, and decide early whether to add your .gitlab-ci.yml file to enable continuous integration from the start. With these concepts in hand, you can streamline builds, share reusable components, and maintain clean, maintainable pipelines across your organization.