Skip to main content

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

  1. Go to your GitLab project
  2. Navigate to Settings > CI/CD > Variables
  3. Click Add variable
  4. Key: MEMBROWSE_API_KEY
  5. Value: Your API key from Project Settings
  6. 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.

Build job rules are required

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.

  1. Go to your project's Settings > Access Tokens
  2. Create a new token with:
    • Role: Reporter (minimum required)
    • Scopes: select api only
  3. Go to Settings > CI/CD > Variables and add:
    • Key: MEMBROWSE_GITLAB_TOKEN
    • Value: the token you just created
    • Check Mask variable

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

VariableRequiredDefaultDescription
MEMBROWSE_ELFYes*Path to ELF file
MEMBROWSE_TARGET_NAMEYesTarget name (e.g., stm32f4, esp32)
MEMBROWSE_API_KEYYesMemBrowse API key
MEMBROWSE_LDNoSpace-separated linker script paths
MEMBROWSE_LINKER_VARSNoSpace-separated VAR=VALUE definitions
MEMBROWSE_API_URLNohttps://api.membrowse.comAPI base URL
MEMBROWSE_VERSIONNomembrowsePip install specifier (e.g., membrowse==1.2.3)
MEMBROWSE_VERBOSENoWARNINGLog level (WARNING, INFO, DEBUG)
MEMBROWSE_DONT_FAIL_ON_ALERTSNofalseDon't fail on budget alerts
MEMBROWSE_IDENTICALNofalseMetadata-only upload (no ELF analysis)
MEMBROWSE_APPEND_MODENofalseUpload in append mode — the report's parent is set to the head of the default branch
MEMBROWSE_GITLAB_TOKENFor commentsGitLab token with api scope
MEMBROWSE_COMMENT_TEMPLATENoPath to custom Jinja2 comment template
MEMBROWSE_REPORT_DIRNo.membrowseDirectory 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 containing name, comparison_url, regions, sections, sections_by_region, symbols, alerts, has_changes, has_alerts
  • has_alertstrue if 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_ELF path matches the actual build output

MR comment not appearing

  • Verify MEMBROWSE_GITLAB_TOKEN is set as a masked CI/CD variable with api scope
  • 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 == null to 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