.. _howto-publish-consume: Publish and consume: docker pull, apt install, promotion ========================================================= Goal: let users ``docker pull`` and ``apt install`` straight from a project, and move artifacts from ``staging`` to ``rc`` to ``release`` without rebuilding. Every build lands in ``staging`` -------------------------------- A green build's artifacts are immediately consumable under the project's channel labels, ``staging`` by default: .. code-block:: console $ docker pull saggar.dev/val/web:staging $ echo "deb [trusted=yes] https://saggar.dev/apt/val staging main" \ | sudo tee /etc/apt/sources.list.d/saggar.list $ sudo apt update && sudo apt install web The owner-scoped paths (``val/web``, ``apt/val``) name the project's owner; the specific job id is a version tag of its own, and artifact files are downloadable one by one through the API (``GET /api/v1/artifacts/:id/files/:filename``). See :doc:`../reference/registries` for the full address and auth rules, including ``docker login`` and apt's ``auth.conf.d`` for private projects, and pull-only tokens for machine-readable credentials. Promotion is a label, never a rebuild ------------------------------------- Channels move one way, ``staging`` → ``rc`` → ``release``, and promotion applies a label to the existing, immutable artifact: .. code-block:: console $ curl -X POST -H "X-Auth-Token: sgt-…" -d '{"channel": "release"}' \ https://saggar.dev/api/v1/artifacts/a-5b249e203f7076f7/promote Promotion needs *promoter* standing on the project and is audited: who, what, when. After promoting, the same content pulls as ``…:rc`` or ``…:release``, and the apt suite flips the same way: .. code-block:: console $ echo "deb [trusted=yes] https://saggar.dev/apt/val release main" | … Typical loop: submit, verify the ``staging`` pull, promote to ``rc``, promote to ``release``. Immutable artifacts mean "release" is a pointer to exactly what was tested: no drift. Browsing what is published -------------------------- .. code-block:: console $ curl -H "X-Auth-Token: sgt-…" \ 'https://saggar.dev/api/v1/artifacts?project=val/web&channel=release' Or ``saggar watch ls``-style visibility in the web app: artifacts, channels, files with digests. Ephemeral artifacts (``--ephemeral``) are the exception: excluded from the registries and collected after the instance's TTL. For check-builds, never for publishing. Sharing with someone outside the account ---------------------------------------- A share link hands one artifact to someone with no saggar account. Mint it with viewer standing: .. code-block:: console $ curl -X POST -H "X-Auth-Token: sgt-…" -d '{"expires_in_secs": 86400}' \ https://saggar.dev/api/v1/artifacts/a-5b249e203f7076f7/shares The reply carries the link path exactly once, ``/s/``; prefix the service origin (``https://saggar.dev``) and send it. It serves the whole artifact as a ``.tar.gz`` bundle, or single files at ``/s//files/``. Give it its own clock with ``expires_in_secs`` (absent: no expiry). The link grants its artifact and nothing else: not the job, not the logs, not the project. ``GET /api/v1/artifacts/:id/shares`` lists who minted what; ``DELETE /api/v1/shares/:id`` revokes it immediately, and a revoked link is then indistinguishable from an unknown one. Private projects ---------------- Until a project is public, pulls follow the project ladder: members only, with the credentials from :doc:`login`. Denials are indistinguishable from unknown names; a private project leaks nothing, not even its existence.