Skip to main content

Crate commit_bridge

Crate commit_bridge 

Source
Expand description

CommitBridge

Seamless workflow dispatch for remote git dependencies.

CI Status  Security Audit  Dual License

Crates.io Version  Docs.rs Status  Docker Image


Triggering a repository workflow in response to a commit on a different repository is not a trivial problem. This is particularly useful for projects that have git dependencies, where breaking changes need to be detected as soon as possible.

This project attempts to solve this problem by providing a server that acts as an intermediary between the repositories containing the dependencies and the repositories that need those dependencies. This project uses axum to handle incoming requests, reqwest to send requests to the GitHub API, git ls-remote to check the last commit on a remote branch, and sqlx connected to a SQLite database to hold state.

§Usage

Setup GitHub App. To authorize the server to trigger a workflow in your repository, set up and install a GitHub App with Contents set to Read and write permissions. Then, annotate your client id and download your private PEM key.

Setup workflow on target repository. Set up your GitHub Actions workflow to be triggered by a repository_dispatch event:

on:
  repository_dispatch:
    types: [EVENT_TYPE]

EVENT_TYPE is a string containing up to 100 characters. It is used to distinguish the event from other repository_dispatch events.

Run the server. Follow the instructions in the “Setup” and “Security” sections to install and run the server (such as via Docker, Cargo, or Nix).

Populate the database. Populate the database with the subscriptions you need. Usage of the Scalar UI, accessible by navigating to /scalar on your server (e.g., http://localhost:3000/scalar), is preferred. The curl command below is left as an example on how to subscribe to a branch.

curl -X POST http://localhost:3000/subscriptions \
  -H "Content-Type: application/json" \
  -d '{
    "source_repo_url": "SOURCE_REPOSITORY",
    "source_branch_name": "BRANCH_NAME",
    "target_repo": "YOUR_REPOSITORY",
    "event_type": "EVENT_TYPE",
    "gh_app_installation_id": YOUR_INSTALLATION_ID
  }'

Make sure that EVENT_TYPE is the same as the one defined in the workflow.

Wait for changes. At this point, the server is ready to listen to the source repository and trigger your workflow shortly after a new commit is pushed (about 5 minutes or less).

§Setup

First, create a .env file with your GitHub App configuration or set the corresponding environment variables:

  • CBRIDGE__AUTH__CLIENT_ID: Your GitHub App’s Client ID.
  • CBRIDGE__AUTH__PEM_PATH: The path to your GitHub App private key.

If you have cloned the repository, you can copy the example file:

cp .env.example .env

Then, follow one of the installation options below.

[!warning] .env files are only suggested for development environments. In production environments, storing the .env file beside the server might introduce security risks. Therefore, always prefer storing configuration in system environment variables, or keeping the .env file separated from the server.

§Docker deployment

For containerized deployment, you can use the pre-built Docker image from Docker Hub. Create a docker-compose.yaml by copying the example in this repository or using the template below:

services:
  commit-bridge:
    image: nilirad/commit-bridge:latest
    container_name: commit-bridge-server
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - commit_bridge_data:/app/data
      - ./YOUR_PEM_FILE.pem:/app/data/YOUR_PEM_FILE.pem:ro
    env_file:
      - .env

volumes:
  commit_bridge_data:

Ensure that your private key file (./YOUR_PEM_FILE.pem in the example above) exists on the host machine before launching the container to prevent Docker from auto-creating it as an empty directory. Once the path is correctly mapped, start the container:

docker compose up -d

§Cargo installation

You can install and run the server directly from crates.io:

cargo install commit-bridge

Ensure git is installed (runtime dependency) and that your environment variables or .env are configured. Then, launch the server:

commit-bridge

§Nix flake (development)

Nix is recommended to set up the development environment.

Ensure flakes are enabled. Just run nix develop to enter a shell with the required environment. If you use nix-direnv, you can automatically enter the shell just by entering the workspace directory with a terminal.

Launch the server using one of the following commands:

cargo run

cargo run --release

nix run

§Manual setup (from source)

If you prefer not to use Nix or a container, you can build and run this server by manually configuring the environment:

  • Install Rust (build-time dependency).
  • Install git (runtime dependency).

Then, launch the server:

cargo run

cargo run --release

§Security

By default, this server mandates authentication for all /subscriptions endpoints.

  1. Configure: Set the CBRIDGE__AUTH__API_KEY environment variable to a secure value in your .env file.

  2. Authenticate: Include the key in the X-API-KEY header for all requests:

    curl -X GET http://localhost:3000/subscriptions \
      -H "X-API-KEY: YOUR_API_KEY"

§API Key Security

To mitigate timing attacks, the server uses constant-time comparison for API keys. Note that while this protects against key content discovery, an attacker may still be able to infer the length of the API key by measuring response times. For maximum security, ensure that your CBRIDGE__AUTH__API_KEY is long and generated using a cryptographically secure random source.

[!warning] Enabling this flag allows unrestricted access to endpoints capable of triggering remote GitHub workflows. Use only in trusted development environments.

If you require an unauthenticated setup for rapid local prototyping, you can explicitly opt-in by setting the following environment variable:

CBRIDGE__AUTH__ALLOW_UNAUTHENTICATED=true

§License

This repository is dual-licensed under the following, unless otherwise noted:

at your option.

Modules§

config
Server configuration module.
context
Shared context for background engines.
domain
Domain models for the application.
engine
Interface definitions for async engines.
error
Definitions for common error types.
handler
Axum route handlers.
model
Data structures representing items stored in database.
polling
Asynchronous task to periodically check for updated remote branches.
repository
Implementation of the repository pattern.
state
State of the application.
trigger
Asynchronous task to trigger remote repository workflows.

Macros§

derive_sqlx_traits
Derives sqlx trait implementations for a type that implements TryFrom<String>.

Functions§

build_http_client
Creates a new HTTP client.
build_router
Builds the application router.
run_app
Runs the server, delegating errors to the caller.
verify_api_key
Uses constant-time verification to check API key correspondence.