Setup
Add MemBrowse to your existing GitLab CI/CD pipeline. If you already build your firmware in CI, this takes just a few minutes.
Prerequisites
- GitLab repository with your firmware project
- ELF file output from your build
- Linker script(s) defining memory regions (optional but recommended for accurate region tracking)
- MemBrowse API key (from Project Settings)
Step 1: Include the Template
Add the MemBrowse template to your .gitlab-ci.yml:
include:
- project: 'membrowse/gitlab-ci'
ref: v1
file: '/membrowse.yml'
This makes three hidden jobs available: .membrowse-analyze, .membrowse-comment, and .membrowse-onboard.
Step 2: Add API Key to CI/CD Variables
- Go to your GitLab project
- Navigate to Settings > CI/CD > Variables
- Click Add variable
- Key:
MEMBROWSE_API_KEY - Value: Your API key from Project Settings
- Check Mask variable so the key doesn't appear in job logs
Step 3: Add the Analysis Job
Extend .membrowse-analyze after your build job. The build job must expose the ELF file as an artifact:
stages:
- build
- test
build:
stage: build
image: gcc:latest
script:
- make build
artifacts:
paths:
- build/firmware.elf
rules:
- if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS == null
membrowse:
extends: .membrowse-analyze
stage: test
variables:
MEMBROWSE_ELF: build/firmware.elf
MEMBROWSE_TARGET_NAME: stm32f4
needs:
- build
That's it. Every push to your default branch uploads a report to the MemBrowse Portal, and every MR pipeline analyzes the memory impact.
The .membrowse-analyze template uses rules: that run on both merge request pipelines and branch pipelines. Your build job must have matching rules, otherwise it won't exist in MR pipelines and the needs: [build] dependency will fail. The $CI_OPEN_MERGE_REQUESTS == null guard prevents duplicate pipelines when pushing to a branch that has an open merge request.
Linker Scripts
If your project uses linker scripts, pass them via MEMBROWSE_LD:
membrowse:
extends: .membrowse-analyze
stage: test
variables:
MEMBROWSE_ELF: build/firmware.elf
MEMBROWSE_LD: "memory.ld sections.ld"
MEMBROWSE_TARGET_NAME: stm32f4
needs:
- build
Multiple linker scripts are space-separated within the quotes.
Linker Variable Definitions
If your linker scripts use variables for memory sizes, pass them with MEMBROWSE_LINKER_VARS:
variables:
MEMBROWSE_ELF: build/firmware.elf
MEMBROWSE_LD: "linker.ld"
MEMBROWSE_TARGET_NAME: stm32f4
MEMBROWSE_LINKER_VARS: "__flash_size__=512K __ram_size__=128K"
Skipping Builds for Non-Source Commits
Not every commit affects your firmware. Use MEMBROWSE_IDENTICAL to upload just commit metadata without running a build or ELF analysis. This keeps the commit chain intact for documentation or CI config changes that don't change the ELF output.
To handle this, use two jobs with changes:-based rules so that exactly one runs per pipeline — the regular analysis for source changes, and an identical upload otherwise:
membrowse:
extends: .membrowse-analyze
stage: test
variables:
MEMBROWSE_ELF: build/firmware.elf
MEMBROWSE_TARGET_NAME: stm32f4
needs:
- build
rules:
- if: $CI_MERGE_REQUEST_IID
changes:
- src/**
- lib/**
- Makefile
- "*.ld"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS == null
changes:
- src/**
- lib/**
- Makefile
- "*.ld"
membrowse-identical:
extends: .membrowse-analyze
stage: test
variables:
MEMBROWSE_TARGET_NAME: stm32f4
MEMBROWSE_IDENTICAL: "true"
rules:
- if: $CI_MERGE_REQUEST_IID
changes:
- src/**
- lib/**
- Makefile
- "*.ld"
when: never
- if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS == null
changes:
- src/**
- lib/**
- Makefile
- "*.ld"
when: never
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS == null
The membrowse job only runs when source files changed. The membrowse-identical job only runs when they didn't. Both jobs override the default .membrowse-analyze rules, so exactly one fires per pipeline.
When MEMBROWSE_IDENTICAL is true, MEMBROWSE_ELF is not required.
MR Comments
To get memory change summaries posted as merge request comments, you need a GitLab token and the comment job.
Create a Token
The comment job uses the GitLab API to post and update MR comments, which requires an authenticated token.
A project access token is recommended over a personal access token since it is scoped to the project and doesn't depend on any individual user's account.
- Go to your project's Settings > Access Tokens
- Create a new token with:
- Role:
Reporter(minimum required) - Scopes: select
apionly
- Role:
- Go to Settings > CI/CD > Variables and add:
- Key:
MEMBROWSE_GITLAB_TOKEN - Value: the token you just created
- Check Mask variable
- Key:
Alternatively, you can use a personal access token with the api scope.
Add the Comment Job
stages:
- build
- test
- deploy
membrowse-comment:
extends: .membrowse-comment
stage: deploy
needs:
- membrowse
The comment job automatically picks up report artifacts from analysis jobs. It creates a single MR comment and updates it on subsequent pushes — no comment spam.
Complete Pipeline
Here's a full .gitlab-ci.yml with build, analysis, and MR comments:
include:
- project: 'membrowse/gitlab-ci'
ref: v1
file: '/membrowse.yml'
stages:
- build
- test
- deploy
build:
stage: build
image: gcc:latest
script:
- make build
artifacts:
paths:
- build/firmware.elf
rules:
- if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS == null
membrowse:
extends: .membrowse-analyze
stage: test
variables:
MEMBROWSE_ELF: build/firmware.elf
MEMBROWSE_LD: "linker.ld"
MEMBROWSE_TARGET_NAME: stm32f4
needs:
- build
membrowse-comment:
extends: .membrowse-comment
stage: deploy
needs:
- membrowse
Budget Alert Behavior
By default, budget alert failures are deferred to the comment job. The analysis job always succeeds so the MR comment is posted first — then the comment job fails the pipeline if any alerts were triggered. To ignore alerts entirely, set MEMBROWSE_DONT_FAIL_ON_ALERTS: "true" on the analysis job.
Variables Reference
| Variable | Required | Default | Description |
|---|---|---|---|
MEMBROWSE_ELF | Yes* | Path to ELF file | |
MEMBROWSE_TARGET_NAME | Yes | Target name (e.g., stm32f4, esp32) | |
MEMBROWSE_API_KEY | Yes | MemBrowse API key | |
MEMBROWSE_LD | No | Space-separated linker script paths | |
MEMBROWSE_LINKER_VARS | No | Space-separated VAR=VALUE definitions | |
MEMBROWSE_API_URL | No | https://api.membrowse.com | API base URL |
MEMBROWSE_VERSION | No | membrowse | Pip install specifier (e.g., membrowse==1.2.3) |
MEMBROWSE_VERBOSE | No | WARNING | Log level (WARNING, INFO, DEBUG) |
MEMBROWSE_DONT_FAIL_ON_ALERTS | No | false | Don't fail on budget alerts |
MEMBROWSE_IDENTICAL | No | false | Metadata-only upload (no ELF analysis) |
MEMBROWSE_APPEND_MODE | No | false | Upload in append mode — the report's parent is set to the head of the default branch |
MEMBROWSE_GITLAB_TOKEN | For comments | GitLab token with api scope | |
MEMBROWSE_COMMENT_TEMPLATE | No | Path to custom Jinja2 comment template | |
MEMBROWSE_REPORT_DIR | No | .membrowse | Directory for report artifacts |
*Not required when MEMBROWSE_IDENTICAL=true.
Self-Hosted GitLab
For self-hosted GitLab instances, MemBrowse Enterprise, or air-gapped environments, see the Self-Hosted guide.
Custom Comment Templates
Provide a custom Jinja2 template for MR comments:
membrowse-comment:
extends: .membrowse-comment
stage: deploy
variables:
MEMBROWSE_COMMENT_TEMPLATE: templates/memory_report.j2
needs:
- membrowse
The template receives a context with:
targets— list of target objects, each containingname,comparison_url,regions,sections,sections_by_region,symbols,alerts,has_changes,has_alertshas_alerts—trueif any target has budget alerts
See the default template for reference.
Troubleshooting
Analysis job fails with "ELF file not found"
- Ensure the build job is listed in
needs:on the analysis job - Verify the
artifacts: paths:in the build job includes the ELF file - Check that the
MEMBROWSE_ELFpath matches the actual build output
MR comment not appearing
- Verify
MEMBROWSE_GITLAB_TOKENis set as a masked CI/CD variable withapiscope - The comment job only runs on merge request pipelines, not on branch pushes
- Check that the analysis job completed and produced a report artifact
Duplicate pipelines running
- Add
$CI_OPEN_MERGE_REQUESTS == nullto the branch rule on your build job (see Step 3) - This prevents both an MR pipeline and a branch pipeline from running when you push to a branch that has an open merge request
Next Steps
- Multiple targets? Track different boards or build variants with Multiple Targets
- Historical data? Populate your project with past commits using Historical Onboarding