CI/CD Pipelines
GitBlixt runs continuous integration pipelines for your repositories. It understands both
GitLab CI (.gitlab-ci.yml) and GitHub Actions
(.github/workflows/*.yml) configuration, so most repositories work without
changing their existing config. Jobs execute in isolated Docker containers, and you watch
logs stream live in the web UI.
How pipelines trigger
A pipeline is created automatically whenever you push to a repository (over SSH or HTTP). You can also start one manually from the Pipelines tab: pick a branch and click Run pipeline. Pipelines are scoped to the branch (ref) and commit (SHA) they ran against.
Turning off Run CI/CD
in the repository's General settings (builds_access_level
in the API) stops pipelines from pushes, merges, merge requests and the Run pipeline
button, stops re-runs and CI job retries (a deploy job can still be retried), and
refuses merge when pipeline succeeds. A push to the branch of an environment that deploys on every push, or of any
auto-deploy environment while CI/CD is off, gets a pipeline with no jobs that only runs
the deploy.
The pipeline list lives at /<namespace>/<repo>/-/pipelines. Each
pipeline links to a detail page at /-/pipelines/<pipeline_id>, and each job to /-/pipelines/<pipeline_id>/jobs/<job_id>.
Configuration
When a pipeline runs, GitBlixt looks for config in this order — the first match wins:
-
GitHub Actions workflows in
.github/workflows/(files ending in.ymlor.yaml) - GitLab CI in
.gitlab-ci.ymlat the repository root
Only GitHub Actions workflows whose on:
trigger matches a push to the pipeline's branch are run. If neither config exists, or
none of its jobs run on the branch, the pipeline is skipped: it never counts
as passing CI, though merge when pipeline succeeds
still fires on it. On a branch an environment auto-deploys, it runs the deploy instead
and takes the deploy's result.
GitLab CI example
Jobs are grouped into stages, which run in order. If you don't declare stages:, the defaults are build, test, deploy. A job's
script
runs inside the container named by its image.
stages:
- test
unit:
stage: test
image: elixir:1.17
script:
- mix deps.get
- mix test
Supported .gitlab-ci.yml keywords
Jobs take stage, image, script, before_script, after_script, variables, services,
parallel
and environment. needs
and artifacts
are accepted but not used yet. Which jobs a pipeline creates follows GitLab:
-
workflow: rulesdecide whether the pipeline gets any jobs. The matched rule'svariablesreach every job. -
rulesmatch in order and the first match decides; a job no rule matches isn't created. A rule takesif,exists,changesandvariables, which the job gets.existsglobs take**(any directories),*,?and$VAR;{a,b},[abc]and\escapes aren't supported.changesalways matches, as GitBlixt doesn't compare against a previous commit, and a rule'sallow_failureis ignored. -
onlyandexcepttake branch names,/regexes/, keywords such asbranches,pushesandmerge_requests, or therefs/variables/changesmap. In the map formonlyneeds every key to match, while any one key ofexceptexcludes the job, so anexceptwithchangesalways does. They can't be combined withrules. Pipelines started with the Run pipeline button or the API haveCI_PIPELINE_SOURCEpush, sowebandapinever match. -
when: on_successandwhen: alwayscreate the job (alwaysbehaves likeon_success).neverdoesn't, and neither domanual,delayedandon_failure, which aren't supported yet.
An if
expression sees the predefined and YAML variables and the project variables the job
gets, matched to its environment:
as described under CI/CD variables. It supports $VAR, quoted strings, null, ==, !=,
=~
and !~
with a /regex/
(flags i, m, s), &&, ||
and parentheses. An expression or keyword GitBlixt can't evaluate fails the pipeline,
and the reason, naming the job and the clause, goes to the server log. Rules are checked
again when each job starts: a job they no longer create, say because a variable changed,
fails with the reason in its log.
A push makes one pipeline, with CI_PIPELINE_SOURCE
push. When its rules create no jobs and the branch has an open, ready merge
request, it runs as that merge request's pipeline instead, with merge_request_event
and the CI_MERGE_REQUEST_*
variables, so configs that select jobs for merge request pipelines work.
GitHub Actions example
GitHub Actions jobs are translated into the same job/stage model. Stages are derived from
the needs: dependency graph, and common setup actions are mapped to equivalent
commands. Expressions like ${{ ... }} are evaluated where supported.
A job's runs-on
label picks its image. Ubuntu labels, hosted ones like blacksmith-4vcpu-ubuntu-2204
included, run on that Ubuntu release, self-hosted
on the latest one, and any other label is taken as the image name. Of a list of
labels, like [self-hosted, linux, x64], the first Ubuntu or self-hosted one wins.
name: CI
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Building on ${{ github.ref }}"
- run: ./run-tests.sh
Stages and jobs
Each stage's jobs are dispatched when the previous stage completes; jobs in the earliest stage that has jobs start as soon as the pipeline begins. Every job is an entry in the pipeline detail view showing its stage, status, duration, and exit code.
Statuses
Pipelines and jobs share the same set of statuses:
| Status | Meaning |
|---|---|
pending |
Created, waiting to start |
running |
Jobs are executing |
success |
All jobs finished successfully |
failed |
At least one job failed |
canceled |
Stopped before completion |
skipped |
Pipelines only: no job ran for the commit |
Job logs
Open any job to see its log. Output streams live over the websocket while the job runs and is persisted so you can review it afterward. Use the Copy log button to grab the full output.
Manual actions
From a pipeline or job page you can:
-
Cancel
— stop a
pendingorrunningpipeline; any running job containers are killed -
Re-run — re-trigger a finished
(
success/failed/canceled) pipeline against the same branch and commit - Clear cache & re-run — wipe the repository's CI build cache, then re-trigger
CI/CD variables
Variables are defined per repository under Settings. They are injected as environment variables into CI job containers. Each variable has:
| Field | Description |
|---|---|
key |
Name (letters, digits, underscores; must start with a letter or underscore) |
value |
The value, encrypted at rest |
masked |
Hides the value in logs and the UI (value must be at least 8 characters) |
protected |
Restricts exposure to protected branches/tags |
environment_scope |
Which environment the variable applies to (defaults to *, all). A
*
inside a scope, as in review/*, matches any characters.
|
A scoped variable reaches a job when its scope matches an environment that deploys from the
pipeline's branch, preview environments included. On a protected branch, a job that names
an environment with environment:
gets that environment's variables instead, as in GitLab; on other branches the name is
ignored, so a job can't widen what it gets. When several scopes set a key, an exact name
beats a wildcard, which beats *. Protected
variables remain the security boundary: only protected
keeps a value off unprotected branches. Jobs that name an environment also get
CI_ENVIRONMENT_NAME
and CI_ENVIRONMENT_SLUG. A GitHub Actions environment:
holding an expression GitBlixt can't evaluate names none.
CI/CD variables are for CI pipeline jobs only. They are not passed to deployed applications — deployed apps get their own environment variables, configured separately on each app environment.
Artifacts
Jobs can produce artifacts — files saved after a job runs. Each artifact records a
file_type
(defaults to archive), file_name, file_path, size, and an optional
expire_at
timestamp after which it can be cleaned up.
External runners (GitLab Runner API)
In addition to the built-in Docker executor, GitBlixt exposes a GitLab Runner–compatible
API so external runners can pull and execute jobs. Authenticate with a personal access token
(PRIVATE-TOKEN or Authorization: Bearer header). The runner is
handed the next pending job belonging to a repository owned by the
authenticated user.
| Endpoint | Purpose |
|---|---|
POST /api/v4/jobs/request |
Fetch the next pending job (204 when none are available) |
PUT /api/v4/jobs/:id |
Update a job's status, exit code, and finish time |
PATCH /api/v4/jobs/:id/trace |
Append raw text to the job's log |
When a runner reports a job as success, failed, or canceled, GitBlixt recalculates the overall pipeline status automatically.