Set up cross-repo triggers for library consumers
Cross-repo triggers allow you to run a pipeline to build code from one repository when an event occurs in another repository. In this guide you will learn how to set up a cross-repo trigger.
Introduction
For this how-to guide we have chosen the following scenario:
Configure CircleCI to automatically run tests for a project that consumes a library when a new tag is created in the library repository. Run integration tests to validate that changes in the library work with dependent applications before publishing the release.
You can either store the config in the consumer repository or in a centralized config repository. The setup for each is shown in the diagrams below:
What you will set up
-
A trigger that watches for new tags in your library repository.
-
A consumer pipeline that runs automatically when those tags are created.
-
Configuration to test the consumer application against the specific library version that was tagged.
| Why tag-based triggers? Tags represent stable release points in your library’s development. Testing consumers against tagged versions ensures that each library release is validated before being published to package registries or deployed to production. While this guide focuses on tag-based triggers, if you need to trigger on other events like branch pushes or pull requests, see the Triggers Overview page for alternative approaches. |
Prerequisites
Before following this guide, ensure you have the following:
-
A CircleCI account connected to GitHub using the GitHub App integration.
-
A "library" repository and a "consumer" repository. These repositories must be in the same GitHub organization. If you want to follow the centralized config options, you will need a third repository for your centralized config store.
-
Admin access to both the library repository and the consumer repository in GitHub.
Decide on your configuration approach
You have two options for structuring your cross-repo trigger setup. Each approach has different benefits depending on your situation.
| Option 1: Config in consumer repository | Option 2: Centralized config repository | |
|---|---|---|
Description |
The pipeline configuration file lives in the same repository as the consumer code. |
The pipeline configuration file lives in a separate repository dedicated to CI/CD configurations. |
Config source |
Consumer repository |
Central config repository |
Checkout source |
Consumer repository |
Consumer repository |
Trigger source |
Library repository |
Library repository |
When to use |
Use this option when each consumer has unique test requirements or when you want teams to maintain their own CI/CD configurations. |
Use this option when you want a platform team to maintain consistent test configurations across multiple consumers, or when you want to reuse the same configuration file for multiple consumer repositories. |
Repository structure |
|
|
Benefits |
Teams maintain their own configurations |
|
| This guide demonstrates both approaches. The steps below use tabs to show the differences between Option 1 and Option 2. |
1. Create configuration file for your consumer pipeline
To follow this how-to guide you need a CircleCI configuration file for your consumer pipeline. This file defines the steps you want to run when the library changes.
This section covers some elements to include in your configuration file. If you just want to follow along you can use the example config file provided at the end of this section.
When a change to your library triggers your consumer pipeline, you need to know which version of the library initiated the trigger so you can test against that specific version. CircleCI provides built-in pipeline values that capture details about the trigger event, including:
-
Tag name
-
Branch name
-
Commit SHA
-
Repository name
For a full list of pipeline values, see the Pipeline Values guide.
CircleCI automatically populates the following pipeline values when a cross-repo trigger fires:
-
pipeline.event.github.ref: The full Git ref that was pushed, this will be a tag name for tag triggers. -
pipeline.event.github.repository.name: The name of the library repository that triggered the pipeline.
You can use these values directly in your configuration without declaring them as parameters.
Here is an example consumer configuration file that uses the built-in pipeline values. This configuration works regardless of whether you store your configuration in the consumer repository or a centralized config repository. CircleCI automatically populates the pipeline values with trigger information regardless of where the config file is stored.
version: 2.1
# Minimal config file for library integration tests
# This config will be triggered when the library repository has events (tags, pushes, etc.)
jobs:
test-with-library:
docker:
- image: cimg/node:18.0
steps:
- checkout # checks out the consumer repository code
- run:
name: Display trigger information
command: |
echo "=== Cross-repo trigger information ==="
RAW_REF="<< pipeline.event.github.ref >>"
LIBRARY_VERSION="${RAW_REF#refs/tags/}"
echo "Library version/tag: ${LIBRARY_VERSION}"
echo "Library repo: << pipeline.event.github.repository.name >>"
- run:
name: Install consumer dependencies
command: |
# Create a minimal package.json for the consumer app
echo '{"name": "my-consumer-app", "version": "1.0.0", "dependencies": {}}' > package.json
npm install
- run:
name: Install library version from trigger
command: |
# In a real scenario, this would install from npm registry:
# npm install @myorg/my-library@<< pipeline.event.github.ref >>
echo "Installing library from trigger..."
RAW_REF="<< pipeline.event.github.ref >>"
# Strip refs/tags/ or refs/heads/ prefix
LIBRARY_VERSION="${RAW_REF#refs/tags/}"
echo "Would install: @myorg/my-library@${LIBRARY_VERSION}"
echo "Installation simulated successfully"
- run:
name: Run integration tests
command: |
echo "Running integration tests with library..."
echo "Testing consumer app functionality with library..."
echo "All integration tests passed!"
workflows:
validate-library-integration:
jobs:
- test-with-library
In this example:
-
When a tag like
v1.2.3is created in the library repository,<< pipeline.event.github.ref >>will containrefs/tags/v1.2.3. -
The configuration installs that specific version using
npm install @myorg/my-library@v1.2.3. -
The consumer tests then run against the exact library version that triggered the pipeline.
Once you have created your config file, or decided to use our example, commit and push the config file to either your consumer repository or your centralized config repository. We recommend storing CircleCI configuration files in a .circleci directory in your repository but you can store them wherever you like as long as they have a .yml extension.
2. Set up your consumer project in CircleCI
Follow steps in the Create a Project in CircleCI guide, or just follow the in-app guidance to create/set up your consumer project in CircleCI.
3. Set up the consumer pipeline
The consumer pipeline defines what should run when the library changes. Follow these steps, selecting the project you set up for your consumer repository.
-
In the CircleCI web app, select your org from the org cards on your user homepage.
-
Select Projects from the sidebar and locate your project from the list. You can use the search to help.
-
Select the ellipsis
next to your project and select Project Settings.
You can also access project settings from each project overview page using the Settings button. -
Select Project Setup in the sidebar.
-
Select Add Pipeline at the top of the pipelines section.
-
Give your pipeline a descriptive name, for example
Library integration tests. -
Configure the pipeline sources and config file based on your chosen approach:
-
Option 1: Config in consumer repository
-
Option 2: Centralized config repository
-
For Config source, select your consumer repository from the dropdown menu.
-
In the Config filepath field, you can either leave the default if you want to run your existing
circleci/config.ymlfile, or enter the path to the specific configuration file for this pipeline if you want to run a different build on changes to the library, for example.circleci/library-integration-tests-config.yml. -
For Checkout source, select your consumer repository from the dropdown menu.
-
Select Save.
You now have a pipeline configured for your consumer repository. The next step is to add a trigger that watches for events in your library repository.
-
For Config source, select your central config repository from the dropdown menu (not the consumer repository). Select the branch where your configuration files are stored (typically
main). -
In the Config path field, enter the path to the specific configuration file for this consumer, for example
.circleci/consumer-app-config.yml.If your central config repository contains configurations for multiple projects, use descriptive file names like .circleci/consumer-app-integration-tests.ymlor organize them in subdirectories like.circleci/consumers/my-app/config.yml. -
For Checkout source, select your consumer repository from the dropdown menu (this is the repository whose code will be tested).
-
Select Save.
When using centralized configuration, the checkoutstep will check out code from the consumer repository (the checkout source), not from the central config repository. This allows you to maintain configurations separately from application code.
Your pipeline is now configured to fetch its configuration from the central repository while checking out code from the consumer repository.
-
4. Add a trigger for library events
The trigger tells CircleCI to run the consumer pipeline when tags are created in your library repository. This guide focuses on tag-based triggers as they are the most common pattern for library releases.
4.a. Create the trigger in CircleCI
-
Select GitHub trigger + at the bottom of the pipeline box.
-
From the Event dropdown menu, select Tag pushes. Using this option means the pipeline will only be triggered when a new tag is created in the library repository.
You can also configure triggers for other events like PR merged or All pushes. See the Triggers Overview for more information. -
From the Event Source dropdown menu, select your library repository instead of the consumer repository.
The trigger will now run the consumer pipeline when a new tag is created in the library repository, which is ideal for testing against official library releases.
Changing the event source is what enables the cross-repo trigger. The trigger now watches for events in the library repository rather than the consumer repository.
-
Because the event source differs from the config source, you will see a field labeled Config branch. Enter the branch name where your consumer pipeline configuration is stored (typically
main).This tells CircleCI which branch to use when fetching the configuration file from the consumer repository.
If you are using a centralized config repository, you will also need to enter a branch name for the checkout source, typically
main. -
Select Save.
-
Option 1: Config in consumer repository
-
Option 2: Centralized config repository
Your cross-repo trigger is now fully configured. When a tag is created in your library repository, CircleCI will trigger the consumer pipeline and run your workflows.
5. Test your cross-repo trigger
Verify that your trigger is configured by creating a tag in your library repository.
-
Navigate to your library repository in GitHub.
-
Create a new tag using the command line or GitHub interface:
$ git tag v1.2.3 $ git push origin v1.2.3 -
Open the CircleCI web app in your browser and select your organization.
-
You should see a new pipeline running with the name you configured in step 2.
-
Select the running pipeline to view the workflow and jobs.
-
Verify that the library information is passed to your jobs by checking the job output.
Figure 5. Example of the job output for a cross-repo trigger
If your pipeline does not trigger:
-
Verify that the trigger event source is set to your library repository.
-
Check that the config branch name matches the branch where your
.circleci/config.ymlfile exists. -
Ensure the event type matches the action you performed (for example, creating a tag for "Tag created" triggers).
Conclusion
You have now set up a tag-based cross-repo trigger system that automatically validates library releases against consumer repositories.
What happens now:
When you create a tag in your library repository (for example, v1.2.3), the following workflow runs automatically:
This setup helps catch integration issues and ensures that library releases do not break dependent applications. You now have confidence that when you publish a library release, it works with your consumers.
| Multiple consumers for one library? If you have multiple consumer repositories that depend on your library, repeat the steps in this guide for each consumer repository. Each consumer can have its own pipeline configuration and trigger settings based on its specific testing requirements. |
Next steps
-
Learn about trigger types in the Triggers Overview page. Explore triggering on pushes or pull requests instead of tags.
-
Learn about Workflow Filtering. Configure more advanced workflow filters for different scenarios.
-
Implement dynamic configuration for complex validation scenarios. See the Dynamic Configuration page for more information.