apiforge 0.1.0

Production-grade API release automation CLI. From merged code to healthy pods in production β€” one command.
Documentation

Apiforge πŸ”₯

Production-grade API release automation CLI. From merged code to healthy pods in production β€” one command, zero tribal knowledge required.

Rust License: MIT


The Problem

Releasing an API to production typically involves:

  1. ✏️ Bumping version numbers in multiple files
  2. πŸ“ Writing changelog entries manually
  3. πŸ“¦ Building Docker images with correct tags
  4. πŸ” Authenticating with container registries (ECR, DockerHub, GHCR)
  5. ⬆️ Pushing images to the registry
  6. ☸️ Updating Kubernetes deployments
  7. ⏳ Waiting for rollouts to complete
  8. πŸ₯ Running health checks
  9. 🏷️ Creating Git tags and GitHub releases
  10. πŸ“’ Sending notifications to Slack/webhooks
  11. πŸ”™ Rolling back if anything fails

This is error-prone, time-consuming, and requires tribal knowledge.

The Solution

apiforge release patch

One command. That's it. Apiforge handles the entire pipeline automatically:

  • βœ… Validates your environment before making any changes
  • βœ… Bumps versions in Cargo.toml, package.json, etc.
  • βœ… Generates changelogs from commit messages
  • βœ… Builds, tags, and pushes Docker images
  • βœ… Updates Kubernetes deployments
  • βœ… Monitors rollout progress
  • βœ… Runs health checks
  • βœ… Creates Git tags and GitHub releases
  • βœ… Sends success/failure notifications
  • βœ… Automatically rolls back on failure

Table of Contents


Installation

Option 1: Install from Cargo (Recommended for Rust users)

cargo install apiforge

Option 2: Download Prebuilt Binary

# Linux (x86_64)
curl -L https://github.com/PrazwalR/Apiforge/releases/latest/download/apiforge-linux-x86_64 -o apiforge
chmod +x apiforge
sudo mv apiforge /usr/local/bin/

# macOS (Apple Silicon)
curl -L https://github.com/PrazwalR/Apiforge/releases/latest/download/apiforge-darwin-arm64 -o apiforge
chmod +x apiforge
sudo mv apiforge /usr/local/bin/

# macOS (Intel)
curl -L https://github.com/PrazwalR/Apiforge/releases/latest/download/apiforge-darwin-x86_64 -o apiforge
chmod +x apiforge
sudo mv apiforge /usr/local/bin/

Option 3: Build from Source

git clone https://github.com/PrazwalR/Apiforge.git
cd Apiforge
cargo build --release
sudo cp target/release/apiforge /usr/local/bin/

Verify Installation

apiforge --version
# apiforge 0.1.0

Quick Start

1. Initialize Configuration

cd your-api-project
apiforge init

This creates apiforge.toml with sensible defaults based on your project.

2. Validate Your Environment

apiforge doctor

Output:

β–Έ Checking dependencies
  βœ“ git (2.39.0)
  βœ“ docker (24.0.5)
  βœ“ kubectl (1.28.0)

β–Έ Checking configuration
  βœ“ apiforge.toml found
  βœ“ Dockerfile exists
  βœ“ Kubernetes context 'prod' available

β–Έ Checking connectivity
  βœ“ Docker daemon accessible
  βœ“ Kubernetes cluster reachable
  βœ“ AWS credentials valid

βœ“ All checks passed! Ready to release.

3. Preview a Release (Dry Run)

apiforge release patch --dry-run

This shows exactly what will happen without making any changes.

4. Execute the Release

apiforge release patch

Output:

β–Έ Pre-flight checks
  βœ“ git-preflight
  βœ“ version-bump
  βœ“ docker-build
  βœ“ k8s-update

β–Έ Executing release pipeline
  βœ“ git-preflight         Repository clean, on main branch (12ms)
  βœ“ version-bump          Bumped version from 1.2.3 to 1.2.4 (5ms)
  βœ“ changelog             Generated changelog with 3 commits (8ms)
  βœ“ git-commit            Committed: Release v1.2.4 (15ms)
  βœ“ git-tag               Created tag v1.2.4 (3ms)
  βœ“ docker-build          Built image sha256:abc123 with tags: 1.2.4, latest (45s)
  βœ“ docker-push           Pushed 123456789.dkr.ecr.us-east-1.amazonaws.com/my-api:1.2.4 (12s)
  βœ“ git-push              Pushed to origin/main (2s)
  βœ“ k8s-update            Updated deployment api-server container 'api' to 1.2.4 (1s)
  βœ“ k8s-rollout           Rollout complete: 3/3 replicas ready (25s)
  βœ“ health-check          Health check passed: https://api.example.com/health (500ms)
  βœ“ github-release        Created release v1.2.4 (800ms)

✨ Release 1.2.4 complete!
   12 steps executed successfully

Commands

apiforge init

Generates a configuration file for your project.

apiforge init

Detects your project type (Rust, Node.js, Python, Go, Java) and creates appropriate defaults.

apiforge doctor

Validates your environment and configuration.

apiforge doctor

Checks:

  • Required CLI tools (git, docker, kubectl)
  • Configuration file validity
  • Docker daemon connectivity
  • Kubernetes cluster access
  • AWS/GitHub credentials

apiforge release <bump>

Executes the full release pipeline.

# Patch release (1.2.3 β†’ 1.2.4)
apiforge release patch

# Minor release (1.2.3 β†’ 1.3.0)
apiforge release minor

# Major release (1.2.3 β†’ 2.0.0)
apiforge release major

Options:

Flag Description
--dry-run Preview without making changes
--skip-docker Skip Docker build and push
--skip-k8s Skip Kubernetes deployment
--skip-github Skip GitHub release creation
--skip-notify Skip notifications
--no-changelog Skip changelog generation
--output json Output results as JSON
-y, --yes Skip confirmation prompt

apiforge rollback

Roll back to a previous version.

# Roll back to previous version (auto-detect)
apiforge rollback

# Roll back to specific version
apiforge rollback --to v1.2.3

# Preview rollback
apiforge rollback --dry-run

apiforge history

View release history.

# Show recent releases
apiforge history

# Limit results
apiforge history --limit 5

# Filter by status
apiforge history --filter success
apiforge history --filter failed

# JSON output
apiforge history --output json

apiforge status

Show current deployment status.

apiforge status

Output:

β–Έ Current State
  Project: my-api
  Language: rust
  Current Version: 1.2.4
  Git Branch: main
  Kubernetes Context: prod-cluster

β–Έ Deployment Status
  Namespace: production
  Deployment: api-server
  Ready: 3/3 replicas
  Image: 123456789.dkr.ecr.us-east-1.amazonaws.com/my-api:1.2.4

Configuration

Apiforge uses apiforge.toml in your project root.

Full Configuration Reference

# Project metadata
[project]
name = "my-api"
language = "rust"  # rust, node, python, go, java

# Git configuration
[git]
require_clean = true           # Require clean working tree
require_main_branch = true     # Only release from main/master
main_branch = "main"           # Name of main branch
tag_format = "v{version}"      # Tag format ({version} is replaced)
changelog = true               # Generate changelog
commit_message = "Release v{{ version }}"

# Docker configuration
[docker]
registry = "aws-ecr"           # aws-ecr, dockerhub, ghcr, custom
repository = "my-api"          # Repository name
dockerfile = "Dockerfile"      # Dockerfile path
context = "."                  # Build context
tags = ["{version}", "latest"] # Tag patterns

# Optional: Build arguments
[docker.build_args]
NODE_ENV = "production"
BUILD_DATE = "$(date -u +%Y-%m-%dT%H:%M:%SZ)"

# AWS configuration (for ECR)
[aws]
region = "us-east-1"
# profile = "production"       # Optional: AWS profile

# Kubernetes configuration
[kubernetes]
context = "prod-cluster"       # kubectl context name
namespace = "production"       # Target namespace
deployment = "api-server"      # Deployment name
image_field = "api"            # Container name or index ("0", "api", "sidecar")
rollout_timeout = 300          # Seconds to wait for rollout
min_ready_percent = 100        # Minimum ready replicas percentage

# GitHub configuration (optional)
[github]
token = "${GITHUB_TOKEN}"      # Environment variable reference
create_release = true
prerelease = false
draft = false
generate_notes = true          # Auto-generate release notes

# Health check (optional)
[health_check]
url = "https://api.example.com/health"
method = "GET"
expected_status = 200
timeout = 60                   # Seconds
interval = 5                   # Check interval
# expected_body_field = "status"
# expected_body_value = "healthy"

# Notifications (optional)
[notifications.slack]
webhook_url = "${SLACK_WEBHOOK_URL}"
channel = "#releases"
message = "πŸš€ {{ project }} {{ version }} released! {{ status_emoji }}"

Environment Variables

Sensitive values can be referenced using ${VAR_NAME} syntax:

[github]
token = "${GITHUB_TOKEN}"

[notifications.slack]
webhook_url = "${SLACK_WEBHOOK_URL}"

How It Works

Release Pipeline

When you run apiforge release patch, the following steps execute in order:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Pre-flight     β”‚ ← Validates all steps before executing
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Git Preflight  β”‚ ← Checks clean tree, correct branch
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Version Bump   β”‚ ← Updates Cargo.toml/package.json
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Changelog      β”‚ ← Generates CHANGELOG.md from commits
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Git Commit     β”‚ ← Commits version + changelog
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Git Tag        β”‚ ← Creates version tag (e.g., v1.2.4)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Docker Build   β”‚ ← Builds image with version tags
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Docker Push    β”‚ ← Pushes to registry (ECR/DockerHub/GHCR)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Git Push       β”‚ ← Pushes commit and tag to remote
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  K8s Update     β”‚ ← Patches deployment with new image
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  K8s Rollout    β”‚ ← Waits for rollout to complete
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Health Check   β”‚ ← Verifies API is healthy
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  GitHub Release β”‚ ← Creates GitHub release with notes
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Notifications  β”‚ ← Sends Slack/webhook notifications
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Automatic Rollback

If any step fails, Apiforge automatically rolls back completed steps in reverse order:

Step 7 (K8s Update) FAILED!

β–Έ Rolling back completed steps
  βœ“ git-push (rolled back)       ← Reverts pushed commits
  βœ“ git-tag (rolled back)        ← Deletes created tag
  βœ“ git-commit (rolled back)     ← Resets to previous commit
  βœ“ changelog (rolled back)      ← Restores original file
  βœ“ version-bump (rolled back)   ← Restores original version

βœ— Release failed. All changes have been rolled back.

This ensures your repository and infrastructure never end up in an inconsistent state.


Supported Integrations

Container Registries

Registry Config Value Authentication
AWS ECR aws-ecr AWS credentials (env/profile/IAM role)
Docker Hub dockerhub DOCKER_USERNAME + DOCKER_PASSWORD
GitHub Container Registry ghcr GITHUB_TOKEN
Custom Registry custom Docker config.json

Languages

Language Version File Detection
Rust Cargo.toml package.version
Node.js package.json version
Python pyproject.toml (Coming soon)
Go go.mod (Coming soon)
Java pom.xml (Coming soon)

Kubernetes

  • Deployments: Update container images
  • Rollout monitoring: Wait for ready replicas
  • Automatic rollback: Uses revision history

Notifications

Service Configuration
Slack Webhook URL + message template
Custom Webhook Any HTTP endpoint

CI/CD Integration

GitHub Actions

name: Release

on:
  workflow_dispatch:
    inputs:
      bump:
        description: 'Version bump type'
        required: true
        type: choice
        options:
          - patch
          - minor
          - major

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for changelog

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1

      - name: Setup kubectl
        uses: azure/setup-kubectl@v3

      - name: Configure kubeconfig
        run: |
          aws eks update-kubeconfig --name my-cluster --region us-east-1

      - name: Install Apiforge
        run: |
          curl -L https://github.com/PrazwalR/Apiforge/releases/latest/download/apiforge-linux-x86_64 -o apiforge
          chmod +x apiforge
          sudo mv apiforge /usr/local/bin/

      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        run: |
          apiforge release ${{ inputs.bump }} --yes

GitLab CI

release:
  stage: deploy
  image: rust:latest
  before_script:
    - cargo install apiforge
    - aws eks update-kubeconfig --name my-cluster
  script:
    - apiforge release patch --yes
  only:
    - main
  when: manual

Troubleshooting

"Docker daemon not accessible"

# Check Docker is running
docker ps

# If using Docker Desktop, ensure it's started
# If using Linux, check the socket
sudo systemctl status docker

"Kubernetes context not found"

# List available contexts
kubectl config get-contexts

# Set the correct context in apiforge.toml
[kubernetes]
context = "your-context-name"

"AWS credentials invalid"

# Check AWS credentials
aws sts get-caller-identity

# If using profiles, set in config
[aws]
profile = "your-profile"

"Tag already exists"

Apiforge validates that the version tag doesn't exist before creating it. If you see this error:

# Either bump to a new version
apiforge release minor

# Or delete the existing tag (use with caution!)
git tag -d v1.2.4
git push origin :refs/tags/v1.2.4

"Rollout timeout"

# Check pod status
kubectl get pods -n your-namespace

# Check events
kubectl describe deployment your-deployment -n your-namespace

# Increase timeout in config
[kubernetes]
rollout_timeout = 600  # 10 minutes

Architecture

apiforge/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.rs              # CLI entry point
β”‚   β”œβ”€β”€ cli.rs               # Command definitions (clap)
β”‚   β”œβ”€β”€ config.rs            # Configuration parsing
β”‚   β”œβ”€β”€ error.rs             # Error types
β”‚   β”‚
β”‚   β”œβ”€β”€ integrations/        # External service clients
β”‚   β”‚   β”œβ”€β”€ aws.rs           # AWS ECR authentication
β”‚   β”‚   β”œβ”€β”€ docker.rs        # Docker build/push (bollard)
β”‚   β”‚   β”œβ”€β”€ git/             # Git operations (git2)
β”‚   β”‚   β”œβ”€β”€ github.rs        # GitHub releases (octocrab)
β”‚   β”‚   └── kubernetes.rs    # K8s deployments (kube-rs)
β”‚   β”‚
β”‚   β”œβ”€β”€ steps/               # Pipeline steps
β”‚   β”‚   β”œβ”€β”€ mod.rs           # Step trait definition
β”‚   β”‚   β”œβ”€β”€ docker/          # Docker build/push steps
β”‚   β”‚   β”œβ”€β”€ git/             # Git operations steps
β”‚   β”‚   β”œβ”€β”€ github/          # GitHub release step
β”‚   β”‚   β”œβ”€β”€ health/          # Health check step
β”‚   β”‚   β”œβ”€β”€ kubernetes/      # K8s update/rollout steps
β”‚   β”‚   └── notify/          # Notification steps
β”‚   β”‚
β”‚   β”œβ”€β”€ orchestrator/        # Pipeline execution engine
β”‚   β”œβ”€β”€ audit/               # Release history tracking
β”‚   β”œβ”€β”€ output/              # Colored terminal output
β”‚   └── utils/               # Version parsing, templates
β”‚
β”œβ”€β”€ apiforge.toml            # Example configuration
β”œβ”€β”€ Cargo.toml               # Rust dependencies
└── README.md                # This file

Contributing

Contributions are welcome! Please read our Contributing Guide first.

Development Setup

# Clone the repository
git clone https://github.com/PrazwalR/Apiforge.git
cd Apiforge

# Build
cargo build

# Run tests
cargo test

# Run lints
cargo clippy

# Format code
cargo fmt

Running Locally

# Run without installing
cargo run -- doctor
cargo run -- release patch --dry-run

License

MIT License - see LICENSE for details.


Acknowledgments

Built with: