How it works
One environment is shown; each environment has its own storage location and Agent, and the pipeline routes by the payload’s target.- A release is deployed to a virtual (Stage) environment in BRMS, directly or through a change request.
- The BRMS webhook creates a pipeline through the GitLab API, passing the event as the
GRL_PAYLOADvariable. The payload carries the project key and the target (for exampleenv:production) in the exact syntaxgorules pullaccepts. - The pull job from the official template resolves the target and downloads the artifact. Resolution and download are two API calls under the hood, but a single
gorules pull- the template handles both. - Your publish job ships the artifact to your object storage. The Agent reads it from there.
GORULES_CURRENT - see Job results. Without GRL_PAYLOAD, a run must state project and target explicitly (Run pipeline form variables or a pasted payload); a missing project fails fast, and the deploy job refuses the silent main default as a backstop.
Prerequisites
- BRMS webhooks (eligible plan): an organisation admin connects the GitLab integration; a Project Admin (Manage Project) creates the webhook.
- A Stage environment in the project (Settings → Environments): deploying a release to it fires the webhook and defines
env:<key>. - Two CI/CD variables (Settings → CI/CD → Variables):
GORULES_URL(org URL, e.g.https://acme.us1.gorules.io) andGORULES_TOKEN(project access token, Masked; Protected only if the pipeline runs on a protected branch). - Credentials for your storage destination; the examples show only the upload command.
1. Create the pipeline
templates/gitlab-ci-pull.yml in the gorules/cli repository defines a hidden job, .gorules-pull, that you extends:. The pull job is identical in every variant; only the deploy job differs. Pick your destination - each tab is the complete file:
- Amazon S3
- Azure Blob Storage
- Google Cloud Storage
.gitlab-ci.yml
deploy to dev and deploy to production differ only in the payload’s target, which the pull job re-exports as RULES_TARGET. The case maps the target to a destination; unmapped targets fail the job so nothing is uploaded to an unintended destination.
The pull job publishes its results as a dotenv report, so deploy:rules reads RULES_TARGET and RULES_PROJECT as ordinary variables in its script - no artifact parsing. There is no changed-gate: a BRMS-triggered run never passes GORULES_CURRENT, so the CLI always downloads; re-running a delivery re-uploads the same artifact. RULES_CHANGED only matters for scheduled pulls. The pulled files arrive via needs: as a job artifact in dist/.
The artifact is written as dist/<project-key> with no .zip suffix, because the Agent’s storage providers use the object name verbatim as the project key - upload it as-is and the Agent picks it up. See naming the output for the other layouts, and Agent configuration for the full provider settings - applications that evaluate through an SDK loader read the same object and need no Agent.
2. Connect BRMS
Integrations are connected once per organisation; webhooks are configured per project.- Connect the GitLab integration (organisation admin): open Settings → Integrations & Apps under the organisation group and connect GitLab. The webhook form also deep-links here via Configure Integrations if the connection is missing.
- Create the webhook (Project Admin - the Manage Project permission): in the project, go to Settings → Webhooks → Create webhook, choose type GitLab, then select the repository and the branch to run on (for example
main). - Subscribe it to the Release Deployed event - then every run means an environment moved, and the payload always carries an
env:<key>target. - Optionally use the Test Webhook section of the form to send a sample event before relying on it.
GRL_PAYLOAD just arrives.
404 Project Not Found on delivery. GitLab hides anything the caller cannot access behind a 404, so this one error has four possible causes:- IP restrictions. If the GitLab group restricts access by IP, it blocks BRMS. GoRules cloud has no fixed IP addresses - traffic originates from the AWS IP ranges of us-east-1 or eu-central-1 (your region). Fixes: allow those ranges (filter ip-ranges.json by region), switch to scheduled polling, or self-host BRMS with a static egress IP.
- Repository role. The identity connected in the integration needs Developer or higher on the repository.
- CI/CD disabled. The project’s CI/CD feature must be enabled (project Settings → General → Visibility).
- Stale repository selection. Re-select the repository in the webhook after reconnecting the integration.
3. Test the flow
Deploy a release to the environment in BRMS and watch the pipeline appear under Build → Pipelines. The webhook log in BRMS (Settings → Webhooks → logs) shows the exact payload delivered and lets you replay a delivery, so you can iterate on the pipeline without re-deploying releases. To test without BRMS, use Build → Pipelines → New pipeline and either setGORULES_PROJECT and GORULES_TARGET directly, or add a GRL_PAYLOAD variable to exercise the exact webhook path:
Job results
The pull job writes a dotenv report, so any job withneeds: ['pull:rules'] reads these as ordinary variables in script: and environment: (not in rules:, which GitLab evaluates before the pipeline runs):
Job configuration (set under the extending job’s
variables:): GORULES_PROJECT, GORULES_TARGET, GORULES_OUT (default dist), GORULES_NAME, GORULES_UNPACK and GORULES_DELETE (quote the booleans: 'true'), GORULES_CURRENT, and GORULES_CLI_VERSION.
RULES_CHANGED is always 'true' on a BRMS-triggered run - the pipeline never passes GORULES_CURRENT, so the CLI always downloads, which is why the deploy job above has no gate. The flag exists for scheduled pulls: run the pipeline on a schedule, pass the last RULES_RELEASE back as GORULES_CURRENT, and when the environment has not moved the CLI exits with code 3, the job reports RULES_CHANGED=false, and downstream jobs skip their upload with a script guard:
script:, not in rules: - GitLab evaluates job rules: at pipeline creation, before any job has run, so dotenv variables from an earlier job are always unset there and a rules: - if: $RULES_CHANGED == "true" gate would silently never match. See the CLI exit codes for the underlying contract.
Committing rules to Git
The same pull can also commit the rules as plain files to your repository. Three optional settings:unpack extracts the archive instead of writing a zip, name: '.' extracts straight into the output directory, and delete removes files that no longer exist in BRMS so the directory mirrors the target exactly. Point the output inside the checkout and commit what changed:
GIT_PUSH_TOKEN is a GitLab project access token with write_repository scope (the default CI job token cannot push). The extracted files travel from pull:rules to commit:rules as a job artifact, and the workflow: rules: gate from the main example already prevents the push from re-triggering the pipeline (push is not an allowed source).