Skip to content
Ryno

Publish from your pipeline

Copy one job, store one token, and let your default branch hand the shared part of your project to your team.

Your project lives in a folder, and your repository already carries it. This page is about the last step: letting the pipeline that builds your default branch hand the shared part of that folder to your company catalogue, so a colleague reads the same requests as you without cloning anything.

You need two things, and the second is the only one you have to keep safe: a job to copy, and a project token to store as a variable.

What the job sends

The job packs .ryno/ into an archive and posts it to your Ryno service. What goes in is decided before anything leaves the runner, and it is a short list: your shared requests and the environments your team versions. Values you marked as local are left where they are.

It runs on every pipeline of your default branch, even when nothing under .ryno/ has changed. That is on purpose. An archive that arrives unchanged is a sign of life, and it is what lets the service tell a project that has nothing new to say from a pipeline that has stopped running. Only the branch matters: a job on a working branch would publish something your team has not agreed on yet.

Add the job to your pipeline

Copy this into .gitlab-ci.yml, at the root of your repository, and put your own service in place of https://ryno.example.com. Nothing else in it is yours to fill in.

publish-ryno-catalog:
  stage: deploy
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
  resource_group: ryno-publication
  script:
    - tar --exclude='*.env.local.json' -czf ryno-catalog.tar.gz .ryno
    - curl --fail-with-body --silent --show-error --header "Authorization: Bearer $RYNO_PROJECT_TOKEN" --header "Content-Type: application/gzip" --data-binary @ryno-catalog.tar.gz "https://ryno.example.com/api/v1/publications"

Only GitLab is covered here. If you build somewhere else, the same two commands work in any job that can reach your service, and you write the surrounding syntax yourself. There is no snippet for another forge on this page, because a snippet written without being run takes longer to debug than one you wrote.

Store the token as a masked, protected variable

Ryno gives you a project token once, when you attach your project. Put it in a CI/CD variable of your repository named RYNO_PROJECT_TOKEN, and turn on both of the flags GitLab offers for it:

  • Masked hides the value in job logs. The token is shaped to fit that flag, so GitLab accepts it as it is, with nothing to trim or re-encode.
  • Protected hands the variable only to jobs running on a protected branch. Since the job publishes from your default branch alone, nothing else has any business reading it.

The token opens with rynopt, which is what lets a secret scanner recognise it if it ever ends up somewhere it should not. It says which project you publish to, so the address in the job carries no project name at all.

What your runner needs

Two commands, and no image to pull: tar and curl. Both are on almost every runner already, which is the point — the first thing you meet should not be an error about an image you do not control.

One version matters: curl 7.76 or newer, for --fail-with-body. Older builds do not know the option and stop on it. With it, a refused publication both fails the job and prints what the service answered, which is the line that tells you what to fix.

What is published, and what stays behind

Published What it holds
collections/**/*.json Your requests, at any depth of the tree you arranged them in.
environments/*.env.json The environments your team versions, so a reader can fill in the variables a request refers to.

Everything else is left out, and it is left out by construction: a file that is not on that list has nowhere to go, even when somebody has committed it by mistake. Two cases are worth saying out loud.

A file ending in .env.local.json never leaves your machine, whichever folder it sits in. If one turns up in an archive built by a pipeline, the receipt names it, because that means a secret has been committed and nothing else is going to tell you.

Flows stay out for now. They are yours and they stay in your repository; what a colleague reads from the catalogue is requests and shared environments.

When the job is refused

The service answers in plain text, one line of cause and one line of what to do, and the job prints it for you. Your token is never echoed back, not even partly, because a job log gets read, copied and pasted.

A refusal that says the project token is not valid means the value in RYNO_PROJECT_TOKEN no longer names a project. Regenerate the token from Ryno, then paste the new value into the variable. Regenerating draws a fresh token, so the old one stops working the moment you ask for a new one, and every job still holding it is refused until you update the variable.

Two other refusals read the same way. A file that your requests’ own format rejects fails the whole publication, with the name of the file and the reason: publishing the rest would leave your team with a catalogue that looks complete and is missing the request you just added. An archive that is too large, or that holds too many files, is refused with the limit it went past.

A refused job changes nothing. The version your team reads stays the one from the last publication that went through.

This project was removed

If an administrator removed your project from the company workspace, a job that still holds its token is refused with these two lines:

Refused: this project was removed from its RYNO workspace.
Refused: remove the RYNO publish job from this pipeline, or attach this repository again from RYNO and paste the new project token into the masked RYNO_PROJECT_TOKEN variable.

The token is not wrong, and regenerating it will not help: the project it named no longer exists. You have two ways out. Delete the publish job from your pipeline if the project is not meant to come back. Or attach the repository again from Ryno, which creates a new project with a new token, and paste that token into RYNO_PROJECT_TOKEN.

Remove a project says what the removal takes away and what it leaves.