CI Integration Guide
Suture works with any CI system. This guide covers GitHub Actions, GitLab CI, CircleCI, Jenkins, and generic bash environments.
Overview
All integrations follow the same pattern:
- Extract file content at three git refs: base (common ancestor), ours (current branch), theirs (incoming branch).
- Send the three versions to the Suture merge API.
- Write the merged result back to disk.
- Optionally commit and push.
Two approaches are available:
- GitHub Action — pre-built, zero-config for GitHub.
- Shell script (
scripts/merge-ci.sh) — portable, works everywhere.
Supported Formats
DOCX, XLSX, PPTX, JSON, YAML, TOML, CSV, XML, Markdown, OTIO, SQL, PDF, and image formats (PNG, JPG, GIF, BMP, WebP, TIFF, ICO, AVIF).
GitHub Actions
Quick Start
# .github/workflows/semantic-merge.yml
name: Semantic Merge
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
semantic-merge:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: WyattAu/suture-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
Full Configuration
- uses: WyattAu/suture-action@v1
with:
files: |
package.json
tsconfig.json
.eslintrc.json
api-url: https://merge.suture.dev/api
api-token: ${{ secrets.SUTURE_API_TOKEN }}
base-ref: origin/main
ours-ref: HEAD
theirs-ref: origin/${{ github.head_ref }}
fail-on-conflict: true
create-comment: true
Outputs
merged-filesconflict-fileshas-conflictstrue if any conflicts were detectedconflict-countGitLab CI
Quick Start
Copy the example config:
# .gitlab-ci.yml
stages:
- merge-check
suture:merge:
stage: merge-check
image: node:20-alpine
rules:
- if: $CI_MERGE_REQUEST_IID
before_script:
- apk add --no-cache git jq
script:
- |
git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
BASE_SHA=$(git merge-base origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME HEAD)
bash scripts/merge-ci.sh \
--files "package.json tsconfig.json Cargo.toml" \
--base-ref "$BASE_SHA" \
--theirs-ref "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
git diff --quiet || {
git config user.name "Suture Bot"
git config user.email "suture-bot@example.com"
git commit -am "Auto-merge structured files via Suture"
git push origin HEAD:$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
}
See the GitLab CI Integration doc for full details.
CircleCI
# .circleci/config.yml
version: 2.1
orbs:
node: circleci/node@5
jobs:
suture-merge:
docker:
- image: cimg/base:stable
steps:
- checkout
- run:
name: Install dependencies
command: sudo apt-get update && sudo apt-get install -y jq
- run:
name: Fetch and merge
command: |
git fetch origin $CIRCLE_BRANCH
BASE_SHA=$(git merge-base origin/$CIRCLE_BRANCH HEAD)
bash scripts/merge-ci.sh \
--files "package.json tsconfig.json" \
--base-ref "$BASE_SHA"
git diff --quiet || {
git config user.name "Suture Bot"
git config user.email "suture-bot@example.com"
git commit -am "Auto-merge structured files via Suture"
git push origin HEAD
}
workflows:
merge-check:
jobs:
- suture-merge:
filters:
branches:
ignore: main
Jenkins
// Jenkinsfile
pipeline {
agent any
environment {
SUTURE_API_URL = 'https://merge.suture.dev/api'
}
stages {
stage('Semantic Merge') {
when {
changeRequest()
}
steps {
sh '''
BASE_SHA=$(git merge-base origin/${CHANGE_TARGET} HEAD)
bash scripts/merge-ci.sh \
--files "package.json tsconfig.json Cargo.toml" \
--base-ref "$BASE_SHA" \
--theirs-ref "origin/${CHANGE_TARGET}"
git diff --quiet || {
git config user.name "Suture Bot"
git config user.email "suture-bot@example.com"
git commit -am "Auto-merge structured files via Suture"
}
'''
}
}
}
}
Generic / Any CI
The shell script works anywhere bash, curl, jq, and git are available:
bash scripts/merge-ci.sh \
--files "package.json tsconfig.json pyproject.toml" \
--base-ref HEAD~1 \
--ours-ref HEAD \
--theirs-ref origin/main \
--api-url https://merge.suture.dev/api \
--token $SUTURE_API_TOKEN \
--no-fail
Arguments
--files--driver--base-refHEAD~1--ours-refHEAD--theirs-ref--api-urlhttps://merge.suture.dev/api--token--no-failEnvironment Variables
SUTURE_API_URLSUTURE_API_TOKENSupported Drivers
.jsonjson.yaml, .ymlyaml.tomltoml.xmlxml.csvcsv.sqlsql.html, .htmhtml.mdmarkdown.svgsvg.properties, .inipropertiesExit Codes
01--no-fail is set)Self-Hosted Suture
Point --api-url or SUTURE_API_URL at your self-hosted instance:
SUTURE_API_URL="https://suture.internal.example.com/api" \
SUTURE_API_TOKEN="your-token" \
bash scripts/merge-ci.sh --files "package.json"