Environments, Deployments, Environment Tiers, URLs, Deployment History, and Operational Traceability: Concepts, Architecture, and Mental Model
Separate job success, GitLab deployment records, and actual target health while tracking environment identity, deployment tier, URL, artifact digest, history, and rollback evidence.
Learning objectives
- Explain why a successful deployment job, a successful GitLab deployment record, and a healthy external target are three different states.
- Trace a verified artifact through deployment job, environment name/tier/URL, GitLab deployment record, target-state change, independent health verification, and rollback reference.
- Distinguish static environment identity from a deployment instance and from a URL that merely points at an intended target.
- Explain current environment actions and which actions create deployment records versus only prepare, verify, access, or stop an environment.
- Use artifact digest, source SHA, pipeline/job/deployment identity, and target read-back as the minimum operational traceability chain.
1. The practical problem: “deploy job passed” is not the same as “service is healthy”
Chapter 18 controlled competing side effects with source-aware pipeline suppression, safe interruption, resource serialization, bounded retries, and reconciliation. Chapter 19 adds the missing operational identity: what environment did we intend to change, which exact artifact did we place there, what did GitLab record, and what does the target actually report now?
A deployment job can exit zero after copying files to the wrong directory. GitLab can record a successful deployment whose URL points at an old target. A target can become unhealthy minutes after a correct deployment because of an external dependency. These are different states and must have different evidence.
2. Mental model: verified bytes become an operationally traceable change
Read this model left to right. The verified artifact is evidence
from the build layer. A deployment job consumes those exact bytes
and declares an environment. GitLab creates a deployment record for
a start action. The script changes some external
target. A separate health/read-back check proves whether the
external state matches the intended artifact. Deployment history
then gives you a rollback reference, but the rollback is only
reproducible if the original bytes are still available.
flowchart TD
A[Verified artifact + SHA + digest] --> B[Deployment job]
B --> C[Environment name / tier / URL]
C --> D[GitLab deployment record]
B --> E[External target change]
E --> F[Independent health / read-back]
D --> G[History + rollback reference]
F --> G
The arrows matter: GitLab can know that a deployment job succeeded without knowing that your custom external service is healthy. Your pipeline must create the missing evidence explicitly.
3. Keep seven state domains separate before changing anything
| State domain | Examples to record | Why it is separate |
|---|---|---|
| Source/revision |
CI_PIPELINE_SOURCE, ref,
CI_COMMIT_SHA
|
Defines the repository state that initiated the pipeline. |
| Compiled configuration | environment name/tier/URL/action, rules, needs | Defines what GitLab decided the job should represent. |
| Job/runner | pipeline ID, job ID, runner/executor/image | Proves who executed the deployment script and when. |
| Artifact | producer job, path, SHA-256 digest, retention | Defines the exact bytes intended for promotion. |
| Environment | environment ID/name/state/tier/URL | Long-lived GitLab identity for a target, not a single deployment. |
| Deployment | deployment ID/status/actor/SHA/ref/job | One recorded deployment event in environment history. |
| External target | host/path/resource ID, observed digest, health result | The real/simulated state GitLab cannot infer from job success. |
4. Smallest useful environment declaration
A job becomes a deployment job when it declares an environment with
the default start action. Use a stable environment name
for one logical target; changing spelling creates a different GitLab
environment and splits history.
deploy:training:
stage: deploy
image: alpine:3.22
script:
- ./ci/deploy-simulated-target.sh dist/app.txt
environment:
name: training/ch19
deployment_tier: testing
url: https://training.invalid/ch19
The URL is metadata and a navigation link; it is not a health check.
The reserved .invalid domain keeps the course from
accidentally pointing at a real service.
5. Environment identity versus deployment identity
An environment is the stable GitLab representation
of a target such as staging, production,
or training/ch19. A deployment is one
event recorded against that environment. Repeated successful deploy
jobs create a history under the same environment name.
| Question | Environment answers | Deployment answers |
|---|---|---|
| Identity | Where is software intended to run? | Which deployment event changed it? |
| Examples | name, tier, URL, state | ID/IID, status, actor, SHA/ref, deployable job |
| Lifetime | Can outlive many pipelines | One event in history |
| Failure mode | Wrong name fragments history | Wrong SHA/digest destroys provenance |
6. Environment states and deployment tiers are metadata, not health
Current environment lifecycle states include available,
stopping, and stopped. A stopped
environment is a GitLab lifecycle state; it does not by itself prove
that every external resource was deleted.
Current deployment tiers are production,
staging, testing,
development, and other. GitLab can infer a
tier from common names, but explicit
deployment_tier removes ambiguity—especially when teams
use business names such as customer-portal.
environment:
name: customer-portal
deployment_tier: production
url: https://portal.example.invalid
7. environment:action changes what GitLab records
Do not attach a deployment record to every job that merely touches an environment. GitLab distinguishes deployment and lifecycle/access intents:
| Action | Deployment record? | Use |
|---|---|---|
start (default) |
Yes | Deploy/change the environment. |
prepare |
No ordinary deployment | Prepare environment state before deployment. |
verify |
No ordinary deployment | Verify health/state without pretending another deployment occurred. |
access |
No ordinary deployment | Access environment-scoped context without deployment semantics. |
stop |
Stops environment | Run teardown/stop workflow. |
This is why Chapter 19 uses a separate verify job after
deployment: a health check should not manufacture another deployment
event.
8. Artifact identity is the bridge from CI evidence to CD evidence
A commit SHA names source, not necessarily the exact deployable bytes. Compilers, generated assets, dependency resolution, build flags, and toolchains can make two rebuilds of the same source differ. Record a digest when the artifact is created, verify it when consumed, and carry that digest into the deployment receipt.
sha256sum dist/app.txt | tee dist/app.sha256
# Later, before deployment:
sha256sum -c dist/app.sha256
For larger systems, the equivalent identity may be a container image digest, package checksum, signed provenance statement, or registry/package version whose immutability policy is independently enforced.
9. An environment URL is not target-health evidence
environment:url makes navigation convenient. It tells
GitLab where an operator should look; it does not prove that DNS
resolves, TLS is valid, the application serves the expected version,
dependencies are healthy, or the artifact digest matches the
deployment record.
Use an independent verification step that reads version/digest/health from the target and compares it with intended evidence. In this chapter’s Free path, a filesystem snapshot stands in for an external target and the verification job checks its recorded digest.
10. Rollback is a deployment decision, not a magical byte-for-byte restore
GitLab can retry or roll back deployments by running deployment jobs associated with older commits. That creates a new deployment event. The deployment script still determines what happens. If the old deploy job requires upstream artifacts that expired—or rebuilds them—your “rollback” can produce different bytes.
11. Read-only inspection before any deployment change
Before changing a deployment pipeline, capture safe identity metadata rather than dumping the whole environment:
printf 'source=%s ref=%s sha=%s pipeline=%s job=%s
' "$CI_PIPELINE_SOURCE" "$CI_COMMIT_REF_NAME" "$CI_COMMIT_SHA" "$CI_PIPELINE_ID" "$CI_JOB_ID"
printf 'env=%s env_id=%s env_url=%s
' "${CI_ENVIRONMENT_NAME:-not-a-deploy-job}" "${CI_ENVIRONMENT_ID:-not-set}" "${CI_ENVIRONMENT_URL:-not-set}"
Then inspect Operate → Environments and the deployment history. If
API access is authorized, a read-only
GET /projects/:id/deployments can provide deployment
IDs/status/SHA/ref/environment. Do not print access tokens into
traces.
12. Common wrong mental models
- “Green deploy job means production is healthy.” It only proves the script exited successfully.
- “The environment URL is a health monitor.” It is metadata/navigation.
- “A new environment name is harmless.” It creates a separate identity/history and can break scoped controls.
- “Rollback to an old commit means the old bytes return.” Not if the deployment job rebuilds or artifacts expired.
- “Stopped in GitLab proves external deletion.” Teardown must be independently verified.
13. Chapter trajectory
Lesson 2 builds and deploys a synthetic artifact once, then verifies the simulated target separately. Lesson 3 chooses naming, tiers, actions, scoping, promotion, and rollback policy. Lesson 4 diagnoses misleading green states and broken provenance. Lesson 5 produces two traceable deployments and a rollback dossier that bridges naturally into Chapter 20’s dynamic review environments.
Knowledge check
What are the three states this chapter refuses to collapse?
Deployment job result, GitLab deployment/environment record state, and external target health/state.
Does environment:url prove that the service is healthy?
No. It is metadata/navigation; health requires independent target verification.
Which environment action creates the ordinary deployment record?
start, which is the default action.
Why record an artifact digest in addition to CI_COMMIT_SHA?
The same source can be rebuilt into different bytes; the digest names the actual promoted payload.
Why can rollback-by-rebuild be unsafe?
The old commit can produce different bytes or depend on expired/mutated inputs, so the rollback no longer restores the exact prior artifact.
Version and compatibility note
GitLab and GitLab Runner evolve continuously. Treat version-sensitive YAML, runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations as assumptions to verify against the current official GitLab documentation before production use. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for any reproducible lab or incident record.
Official references and version notes
Documentation verification date: 2026-09-12. Environment/deployment keywords, environment actions, deployment-tier variable support, auto-stop behavior, rollback UI behavior, environment-scoped variables, and deployment safety are version-sensitive. Re-check the GitLab and Runner versions used by production delivery before applying the exact examples.
- Environments — environment identity/state, tiers, URLs, stop/auto-stop behavior, environment-scoped variables, and operational views.
- Deployments — deployment history, deployment refs, retry/rollback behavior, and auditability.
- Deployment safety — deployment serialization, outdated-job prevention, protected environments, and rollback considerations.
-
CI/CD YAML syntax reference
—
environment,environment:name,url,action,auto_stop_in,deployment_tier, and related job semantics. - Deployments API — deployment IDs, statuses, SHA/ref, user, environment, and history queries.
- Environments API — environment metadata/state/tier management when API access is appropriate.
- CI/CD variables — environment scope behavior and precedence boundaries.
Current assumptions used in this chapter:
environments and deployment history are available on Free, Premium,
and Ultimate across GitLab.com, Self-Managed, and Dedicated.
Environment states include available,
stopping, and stopped.
environment:action currently supports
start (default, creates a deployment after job start),
prepare, verify, access, and
stop; the latter four model lifecycle/access work
rather than ordinary deployment creation. Deployment tiers are
production, staging, testing,
development, and other; CI/CD-variable
support for deployment_tier was added in GitLab 18.5.
auto_stop_in uses natural-language durations; stop
processing is background work and is not an exact real-time timer.
The mandatory labs use synthetic artifacts, a stable
training/ch19 environment, alpine:3.22, a
reserved .invalid URL, and filesystem/artifact
snapshots as a faithful target simulation—no cloud account,
protected production environment, or real credential is required.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.