Skip to main content

Automated YAML/JSON value updates for GitOps repositories via GitHub API

Project description

gitops-replacer

License: MIT Python 3.10+ PyPI version PyPI downloads

A lightweight CLI tool that automates value updates in GitOps repositories using marker comments. Replace values across multiple GitHub repositories with a single command, enabling automated deployment workflows.

Features

  • Marker-based Approach: Uses # gitops-replacer: <name> comments to locate values
  • Format Preservation: No YAML parsing - comments, quotes, and formatting are preserved
  • Multiple Dependencies: Update different values in the same file via unique markers
  • Flexible Modes: Dry-run for validation, apply mode for commits
  • CI/CD Integration: Built-in CI mode with GITHUB_REF pattern matching
  • Multiple Repositories: Update values across any number of repos and files
  • Configuration Formats: JSON (default) and YAML support
  • Performance Optimized: Response caching eliminates duplicate API calls
  • Robust HTTP: Automatic retries, timeouts, and error handling

Requirements

  • Python 3.10+
  • A GitHub/GitHub Enterprise token with content read/write access

Installation

Via pip (recommended)

# Install from PyPI
pip install gitops-replacer

# Verify installation
gitops-replacer --help

From source

# Clone repository
git clone https://github.com/slauger/gitops-replacer.git
cd gitops-replacer

# Install in development mode
pip install -e .

# Or run directly
python -m gitops_replacer --help

Quick Start

  1. Add marker comments to your target files (see Marker Format)
  2. Create a configuration file (default: gitops-replacer.json)
  3. Run a dry-run:
    gitops-replacer "1.2.3"
    
  4. Apply changes (commit to target repos):
    gitops-replacer --apply "1.2.3"
    

Marker Format

Add a comment above the line you want to update:

dependencies:
  # gitops-replacer: my-app
  - name: my-app
    version: "0.0.0-e0f72bb"
    repository: oci://registry.example.com/charts

  # gitops-replacer: another-chart
  - name: another-chart
    version: "1.0.0"
    repository: oci://registry.example.com/charts

The tool will:

  1. Find the line with # gitops-replacer: <depName>
  2. Replace the value on the next line (preserving key, quotes, and formatting)

Examples

Chart.yaml (Helm dependency version):

dependencies:
  # gitops-replacer: my-app
  - name: my-app
    version: "0.0.0-e0f72bb"
    repository: oci://registry.example.com/charts

values.yaml (image tag):

# gitops-replacer: my-app-image
image: registry.example.com/myorg/my-app:1.2.3

Note: Only YAML files are supported (JSON has no comments). GitOps manifests are typically YAML.

CLI

usage: gitops-replacer [-h] [--config <file>] [--apply] [--ci]
                        [--name <string>] [--email <string>]
                        [--message <string>] [--api <string>]
                        [--verbose]
                        <string>
  • --config Path to the configuration file (default: gitops-replacer.json). JSON recommended.
  • --apply Apply changes (commit). Without this flag the tool runs in dry-run.
  • --ci CI mode: validates GITHUB_REF against when/except regex patterns from config.
  • --name Commit author name (default: env GIT_COMMIT_NAME or Replacer Bot).
  • --email Commit author email (default: env GIT_COMMIT_EMAIL or replacer-bot@localhost.localdomain).
  • --message Commit message template (default: fix: update {} to {}). First {} is depName, second is value.
  • --api GitHub API URL (default: env GITHUB_API_URL or https://api.github.com).
  • --verbose Print file contents and desired state (use with care in CI logs).
  • Positional: value - the new value to set at the marked location.

Environment

  • GITHUB_TOKEN (required) – token with access to read/write repository contents.
  • GITHUB_REF (required when --ci) – the current ref string, e.g., refs/heads/main. Falls back to GIT_REF for backwards compatibility.

Recommended token scopes:

  • Public repos only: public_repo
  • Private repos: repo
  • GitHub Enterprise: equivalent content permissions

Configuration

Default format is JSON. YAML (.yaml/.yml) is supported as well.

JSON schema (per entry)

{
  "gitops-replacer": [
    {
      "repository": "acme/gitops",
      "branch": "main",
      "file": "apps/my-app/Chart.yaml",
      "depName": "my-app",
      "when": "^refs/heads/main$"
    }
  ]
}

Fields

Field Description
repository Target repo on GitHub (ORG/REPO format)
branch Target branch
file Target file path relative to repo root
depName Dependency name (must match marker in file)
when Regex that must match GITHUB_REF when --ci is enabled (optional)
except Regex that must not match GITHUB_REF when --ci is enabled (optional)

The tool uses re.match (anchored at the string start). Use ^...$ in your patterns if you require a full match.

Examples

JSON (default)

{
  "gitops-replacer": [
    {
      "repository": "acme/gitops",
      "branch": "main",
      "file": "apps/my-app/Chart.yaml",
      "depName": "my-app",
      "when": "^refs/heads/(main|release/.*)$"
    },
    {
      "repository": "acme/gitops",
      "branch": "develop",
      "file": "apps/my-app-dev/Chart.yaml",
      "depName": "my-app",
      "except": "^refs/heads/legacy/"
    }
  ]
}

YAML (alternative)

gitops-replacer:
  - repository: acme/gitops
    branch: main
    file: apps/my-app/Chart.yaml
    depName: my-app
    when: '^refs/heads/(main|release/.*)$'
  - repository: acme/gitops
    branch: develop
    file: apps/my-app-dev/Chart.yaml
    depName: my-app
    except: '^refs/heads/legacy/'

How it works

  1. Validation: Checks CLI arguments, environment variables, and configuration file
  2. Precheck Phase: Validates access to all target repositories/files (caches responses)
  3. Replace Phase: Downloads files (reuses cached data), finds marker comments, replaces values
  4. Commit Phase: If --apply is set and changes detected, commits via GitHub Contents API
  5. Exit Codes: Returns 0 on success, non-zero on failures

Why Marker-based?

Traditional approaches parse YAML, modify the data structure, and serialize back. This often breaks:

  • Comments are lost
  • Quote styles change ("1.0" becomes '1.0' or 1.0)
  • Key ordering may change
  • Multi-line strings get reformatted

The marker-based approach works on raw text:

  • Explicit: Only marked lines are modified
  • Safe: No risk of unintended changes
  • Preserving: Comments, quotes, and formatting stay intact

Exit Codes

  • 0 success (no changes or committed changes)
  • 1 validation or API error

Use Cases

Automated Deployment Pipeline

Update chart version when a new release is built:

# In your CI/CD pipeline after publishing a chart
gitops-replacer --ci --apply "0.1.0-abc123"

Multi-Environment Updates

Use CI mode to update different environments based on branch:

{
  "gitops-replacer": [
    {
      "repository": "myorg/gitops",
      "branch": "main",
      "file": "apps/production/Chart.yaml",
      "depName": "myapp",
      "when": "^refs/heads/main$"
    },
    {
      "repository": "myorg/gitops",
      "branch": "main",
      "file": "apps/staging/Chart.yaml",
      "depName": "myapp",
      "when": "^refs/heads/(main|develop)$"
    }
  ]
}

Troubleshooting

Common Issues

401 Unauthorized

  • Verify GITHUB_TOKEN is set correctly
  • Check token has repo or public_repo scope
  • For GitHub Enterprise, confirm token has access to the organization

404 Not Found

  • Verify repository, branch, and file paths in config
  • Check branch name spelling (case-sensitive)
  • Ensure file exists at the specified path

No marker found

  • Confirm the marker comment exists in the target file
  • Check depName in config matches the marker exactly
  • Marker format: # gitops-replacer: <depName>

No changes detected

  • The current value already matches the new value
  • Use --verbose to see file contents

Debug Mode

Run with --verbose to see:

  • Full API URLs being called
  • Complete file contents before replacement
  • Desired file contents after replacement

Warning: Verbose mode may expose sensitive data in logs.

Contributing

Contributions are welcome! Please ensure:

  • Code follows existing style and patterns
  • Changes are tested with both dry-run and apply modes
  • Documentation is updated for new features

License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gitops_replacer-0.1.1.tar.gz (13.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gitops_replacer-0.1.1-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file gitops_replacer-0.1.1.tar.gz.

File metadata

  • Download URL: gitops_replacer-0.1.1.tar.gz
  • Upload date:
  • Size: 13.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for gitops_replacer-0.1.1.tar.gz
Algorithm Hash digest
SHA256 21b00b90bc8544e23c37838c50c7539a366921ea8f851f0d4bffdca51403cabb
MD5 b261266ee9414687eb844734d2758c41
BLAKE2b-256 fd045e88135b09f8dce6d2e2f5a8c9e16702cb58579333bb0235232ccb75d7fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for gitops_replacer-0.1.1.tar.gz:

Publisher: release.yml on slauger/gitops-replacer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gitops_replacer-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for gitops_replacer-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1a8d4ad79e638674c2257f65c14deae9abdc1433c1bcaa46cbd85f7d71971c5d
MD5 4fb50fa14f620712145ff12b5e8bf0b9
BLAKE2b-256 8707a396bcf7488890b39b5f79a4c836df9bd8d68a481f96e4ab23b5e60a6ebe

See more details on using hashes here.

Provenance

The following attestation bundles were made for gitops_replacer-0.1.1-py3-none-any.whl:

Publisher: release.yml on slauger/gitops-replacer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page