Build and verification guide

Run a canonical plan from an exact revision.

Mozaic reads pipeline configuration from the repository revision being built, validates a closed YAML schema, records a SHA-256 plan identity, and schedules bounded jobs against an immutable source bundle.

Schema version 1.NET-focusedDigest-pinned images
Definition.mozaic/pipeline.yml in the repository
Manual permissionProject-scoped Run pipelines
Successful resultSucceeded run with immutable attempt results
01 / Before you begin

Commit the build definition with the code.

Prerequisites

  • An Active Git repository in a Mozaic project.
  • A UTF-8 file named exactly .mozaic/pipeline.yml at the revision you want to run.
  • Container images pinned to complete lowercase SHA-256 digests. Mutable tags such as :latest are rejected.
  • The Run pipelines claim for a manual run. Pull-request authors can run the current check for their own proposal; other users need Run pipelines.
  • Enough concurrent-job capacity and service credits for the resolved resource request.

Pipeline configuration is code. Editing the file on the default branch does not alter a run for an older revision, and a manual caller cannot substitute different YAML in the scheduling request.

02 / Copyable definition

Start with the shipped .NET sample.

This valid schema-version-1 definition is derived from samples/dotnet/.mozaic/pipeline.yml. The complete image digest is intentional. Adapt the solution, project, cache key, and artifact paths to your repository. The added manual trigger makes the same definition runnable from the Pipelines page.

.mozaic/pipeline.ymlcopy, then adapt repository paths
version: 1
triggers: [pull_request, manual, tag]
jobs:
  verify:
    image: mcr.microsoft.com/dotnet/sdk@sha256:ed034a8bf0b24ded0cbbac07e17825d8e9ebfe21e308191d0f7421eaf5ad4664
    resources:
      cpu_millis: 2000
      memory_mib: 4096
      scratch_mib: 10240
      pids: 512
      log_mib: 100
    network:
      mode: http_https
      allow_hosts: [api.nuget.org]
    timeout_minutes: 30
    steps:
      - name: Restore locked dependencies
        run: dotnet restore Mozaic.Sample.slnx --locked-mode
      - name: Build release binaries
        run: dotnet build Mozaic.Sample.slnx --configuration Release --no-restore
      - name: Run tests
        run: dotnet test Mozaic.Sample.slnx --configuration Release --no-build --no-restore --logger "trx;LogFileName=tests.trx" --results-directory artifacts/test-results
      - name: Pack NuGet artifacts
        run: dotnet pack src/Mozaic.Sample/Mozaic.Sample.csproj --configuration Release --no-build --no-restore --output artifacts/packages
    artifacts:
      - name: nuget-packages
        paths: [artifacts/packages/*.nupkg, artifacts/packages/*.snupkg]
    caches:
      - key: dotnet10-lock-v1
        paths: [.nuget/packages]
    test_results:
      - path: artifacts/test-results/tests.trx
        format: trx
  1. Add the file.Create the .mozaic directory at repository root and commit pipeline.yml.
  2. Adapt paths.Every artifact, cache, test-result, and publication path is workspace-root relative. Absolute paths, backslashes, and . or .. components are rejected.
  3. Keep restore deterministic.The sample uses locked restore, then builds and tests without restoring again.
  4. Push the revision.Mozaic compiles the exact committed bytes when a supported trigger is recorded.
03 / Schema

Compose a bounded job graph.

version
Must be 1. Unknown fields are rejected rather than ignored.
triggers
One or more of push, pull_request, manual, trusted_branch, and tag. Duplicates are normalized.
jobs
A map of job IDs to job definitions. IDs contain at most 63 ASCII letters, digits, hyphens, or underscores and begin with a letter or digit.
needs
Job IDs that must succeed first. Unknown, duplicate, self, and cyclic dependencies are rejected. Mozaic records a stable topological order.
image
A container image pinned with @sha256: followed by 64 lowercase hexadecimal characters.
services
Up to three named digest-pinned service images per job, with an optional bounded command array.
steps: run
A non-empty shell command of at most 16 KiB, with an optional display name.
steps: uses
An installation-allowlisted, digest-pinned oci:// action and bounded string inputs. Arbitrary actions are not fetched.
network
Defaults to none. Use http_https plus explicit public DNS names to allow outbound HTTP(S).
artifacts
Named path sets retained as downloadable run artifacts.
caches
Keyed path sets restored only from suitable immutable successful attempts with matching trust.
test_results
Currently supports normalized Visual Studio TRX files with format: trx.
No expression language

${{ ... }} expressions are not supported. YAML anchors, aliases, merge keys, custom tags, multiple documents, tab indentation, and excessively deep indentation are also rejected.

04 / Triggers and trust

Enable only the entry points you use.

TriggerWhen it is recordedRun trust
pull_requestOpening, synchronizing, or explicitly verifying a current pull-request snapshot.external_restricted
manualA user with Run pipelines selects an exact repository reference in the Pipelines page.external_restricted
pushAn accepted branch update whose actor has Manage source and Run pipelines.external_restricted
trusted_branchAn accepted update to the repository's configured default branch under server-side authorization.trusted
tagAn accepted tag update whose actor also has Manage packages.trusted

A trigger listed in YAML is necessary but not sufficient. The corresponding accepted product event and current governance claims must also exist. Client input cannot mark a manual or pull-request job trusted.

If the same default-branch update enables both push and trusted_branch, each enabled trigger is recorded independently and can produce its own run.

05 / Manual workflow

Schedule an exact repository reference.

OrganizationProjectsprojectPipelinesManual trigger
  1. Select an Active repository.Archived and provisioning repositories are not offered for manual scheduling.
  2. Select a branch or tag.The picker shows the full reference and the exact resolved revision.
  3. Schedule the run.The server reloads .mozaic/pipeline.yml from that revision, requires manual, freezes selected feed slugs to immutable feed IDs, and hashes the canonical plan.
  4. Open the receipt.A successful response shows the plan SHA-256, source-bundle SHA-256, run ID, and immutable attempt IDs.

Success state

The new run appears as Queued in project Pipelines with trigger Manual, the selected ref and revision, and trust external_restricted. Repeating the same in-flight browser command is idempotent.

06 / Pull-request workflow

Verify the current proposal snapshot.

CoderepositoryPull requestspull requestChecks
  1. Open or synchronize the proposal.Mozaic attempts to schedule check verify when the current source definition enables pull_request.
  2. Use Run verify when needed.The author can schedule their own check. A different member requires Run pipelines.
  3. Review the binding.The check records the snapshot ID, exact source revision, plan hash, attempt ID, conclusion, and trust.
  4. Rerun on new evidence.Synchronizing creates a new snapshot and revokes the old grant. Rerunning the same snapshot cancels older snapshot runs before it enqueues a replacement.

A pull-request execution grant lasts 30 minutes. A required check counts only when it belongs to the current snapshot, is trusted according to the branch policy path, and concludes Passed.

07 / Run results

Read status at both run and attempt level.

ProjectsprojectPipelinesrun
Run states
queued, running, succeeded, failed, indeterminate, or cancelled.
Attempt states
The same progression plus leased, which means a runner holds the fenced attempt but has not yet reported it running.
Immutable binding
Repository revision, canonical plan, plan SHA-256, trust class, ref, trigger, requester, and optional pull-request snapshot/check.
Logs
Per-attempt compressed job logs exposed as downloadable result objects.
Artifacts
Declared artifact archives with logical name, byte size, and SHA-256. Cache archives are intentionally not downloadable through the user result endpoint.
Tests
TRX cases normalized to suite, name, class, outcome, duration, and optional error message.
Packages
Explicit feed publication records, including feed, entry path, digest, kind, state, normalized package identity, and failure reason.

Cancel a run

The requester can cancel their own queued or running run. Another user needs Run pipelines. Cancellation is a request: already running work may take time to observe it, and the final result stays in history.

Indeterminate is different from failed

Failed means the attempt produced a definite unsuccessful result. Indeterminate means infrastructure lost certainty after execution may have begun. Mozaic does not silently retry such an attempt because doing so could repeat side effects.

Any project member can view project run history and download logs or declared artifacts. Public run history is a smaller read-only view and exists only when the organization and project are public.

08 / Publish packages

Make feed publication an explicit terminal step.

Declaring a .nupkg as an artifact makes it downloadable from the run; it does not publish it. Add publish_in_feed after all executable steps:

YAML fragmentappend to a job's steps
      - name: Publish packages
        publish_in_feed:
          feed:
            slug: releases
          paths:
            - artifacts/packages/*.nupkg
            - artifacts/packages/*.snupkg
          allow_untrusted: false
  • Select exactly one feed by id or slug. The scheduler freezes a slug to an immutable feed ID before execution.
  • Declare 1-64 safe workspace-root NuGet glob patterns. Every pattern must contain .nupkg or .snupkg.
  • No run or uses step may follow the first publish_in_feed step.
  • allow_untrusted defaults to false. Keep it false for release feeds unless the project deliberately accepts publication from restricted jobs.

See Packages for feed creation, token pushes, symbols, lifecycle, and public-feed gates.

09 / Limits and security

Design inside the operated safety envelope.

BoundaryCurrent project pipeline limit
Definition1-262,144 UTF-8 bytes; schema version 1; at most 64 spaces of indentation.
Jobs1-20 per pipeline.
Services0-3 per job.
Steps1-50 per job; run command at most 16 KiB.
CPU1-2,000 millicores per job; default 2,000.
Memory1-4,096 MiB per job; default 4,096 MiB.
Scratch1-10,240 MiB per job; default 10,240 MiB.
Processes1-512 PIDs per job; default 512.
Logs1-256 MiB per job; default 100 MiB.
Timeout1-30 minutes per job; default 30.
Network hostsAt most 100 explicit public DNS names; no IP literals, localhost, .local, or .internal.
  • Jobs execute in ephemeral, rootless isolation with bounded CPU, memory, scratch, PIDs, log size, time, and network policy.
  • Container and action images are digest-pinned; unknown fields and unsupported dynamic expressions fail closed.
  • Restricted jobs do not receive protected secrets, privileged mode, host mounts, deployment authority, or implicit package-publication authority.
  • Source staging verifies the Git bundle and referenced LFS objects against the selected repository revision and canonical plan.
  • Artifact and cache paths are validated before scheduling; archive extraction is separately bounded and traversal-safe.
10 / Troubleshooting

Resolve common failures.

Pipeline definition was not found or is not UTF-8

Check that the file is committed at exactly .mozaic/pipeline.yml in the selected revision. A working-tree file that was never pushed is not part of the run.

The selected trigger is not enabled

Add the exact trigger name to triggers, commit it, and select the new revision. Manual scheduling requires manual; pull-request checks require pull_request.

Container image must be digest-pinned

Replace a tag with an immutable reference ending in @sha256: and 64 lowercase hexadecimal characters. A digest belongs on every job image, service image, and uses reference.

Uses reference is not allowlisted

The action must be a digest-pinned oci:// reference present in the operated allowlist. Use a normal run step with the job image or an already supported action; YAML cannot expand the allowlist.

Network destination is rejected

Set mode to http_https and list a public DNS hostname only. Do not include a scheme, port, IP address, wildcard, loopback name, or private suffix.

The run is queued but does not start

Check project job concurrency and service-credit availability, then confirm no dependency job has failed. See Billing & limits.

A package file exists but nothing was published

An artifact declaration only retains bytes. Add an explicit terminal publish_in_feed step, verify its paths match, and inspect the run's Published packages section for a per-entry failure reason.