gantry

command module
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2026 License: MPL-2.0 Imports: 8 Imported by: 0

README

gantry

A CLI for Platform-izing devcontainers in microservices, widely distributed, or just complicated™ situations.

Why gantry?

Devcontainers are an amazing tool for building shared, secure development environments for distributed teams. However, managing the configuration (Dockerfile, devcontainer.json) comes with its own complexities: teams want to customize tools, programming languages have different standards, and services proliferate.

There are well-known solutions for Dockerfiles like using base images and docker bake.

But what if you're a development team that wants a standard VSCode configuration for the astral stack? Or a Platform Engineering team standardizing your AI coding tool stack?

gantry is a light-weight CLI that solves this problem by:

  • Allowing teams to store devcontainer.json configuration in git repositories.
  • Uses jsonnet to merge standard configurations (e.g. a base Python devcontainer.json) with use-case (e.g. a Jupyter plugin for data teams) and/or team (e.g. Svelte for a fullstack team) from remote repositories.
  • Let developers define a configuration as a YAML file on disk and re-generate the devcontainer.json on demand.

Installing gantry

With go
go install github.com/ivanklee86/gantry@latest
With Homebrew
brew install ivanklee86/tap/gantry
With Docker
docker pull ghcr.io/ivanklee86/gantry:latest
docker run --rm ghcr.io/ivanklee86/gantry:latest

To embed gantry in your own Dockerfile:

COPY --from=ghcr.io/ivanklee86/gantry:latest /usr/local/bin/gantry /usr/local/bin/gantry

Usage and Configuration

Quick start (CLI flags)

Build from a single remote repository and print to stdout:

gantry build --repo https://github.com/ivanklee86/devcontainers --ref main --files devcontainer_configs/bases/go/devcontainer.json

Write the result to a file:

gantry build --repo https://github.com/ivanklee86/devcontainers --ref main \
  --files devcontainer_configs/bases/go/devcontainer.json \
  --write --output-path .devcontainer/devcontainer.json
YAML configuration file

For multi-repository merges or to keep the configuration in source control, use a YAML file:

version: 1

output_path: .devcontainer/devcontainer.json

overlays:
  - repo: https://github.com/ivanklee86/devcontainers
    ref: main
    files:
      - devcontainer_configs/bases/go/devcontainer.json
  - repo: https://github.com/org/team-overlays
    ref: refs/heads/main
    subdirectory: data-team
    files:
      - jupyter.jsonnet

Run it:

gantry build --config gantry.yaml --write

CLI flags --output-path and --write override the values in the config file when specified.

Multi-layer example

A typical setup has three layers: a shared org base, a language overlay, and a team overlay. Each layer is a Jsonnet file that merges on top of the previous result.

Layer 1 — org base (devcontainers/bases/base.json, plain JSON):

{
  "name": "base",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",
  "remoteUser": "vscode",
  "customizations": {
    "vscode": {
      "settings": {
        "editor.formatOnSave": true,
        "editor.rulers": [100]
      },
      "extensions": ["GitHub.vscode-github-actions", "redhat.vscode-yaml"]
    }
  },
  "postCreateCommand": {
    "upgrade": "sudo apt-get update && sudo apt-get upgrade -y"
  }
}

Layer 2 — language overlay (devcontainers/languages/python.jsonnet):

Uses +: to deep-merge into the base rather than replacing it.

{
  name: "python",
  image: "mcr.microsoft.com/devcontainers/python:3.13",

  customizations+: {
    vscode+: {
      settings+: {
        "python.defaultInterpreterPath": "/usr/local/bin/python",
        "[python]": { "editor.defaultFormatter": "charliermarsh.ruff" },
      },
      extensions+: [
        "charliermarsh.ruff",
        "ms-python.python",
        "ms-python.mypy-type-checker",
      ],
    },
  },

  postCreateCommand+: {
    "install-uv": "curl -LsSf https://astral.sh/uv/install.sh | sh",
  },
}

Layer 3 — team overlay (team-overlays/data-team/jupyter.jsonnet):

{
  name: "data-team-python",

  customizations+: {
    vscode+: {
      extensions+: [
        "ms-toolsai.jupyter",
        "ms-toolsai.vscode-jupyter-cell-tags",
      ],
    },
  },

  remoteEnv: {
    TEAM: "data",
    JUPYTER_PORT: "8888",
  },

  forwardPorts: [8888],

  postCreateCommand+: {
    "install-deps": "uv sync --all-extras",
  },
}

gantry.yaml wiring all three together:

version: 1

output_path: .devcontainer/devcontainer.json

overlays:
  - repo: https://github.com/org/devcontainers
    ref: refs/heads/main
    subdirectory: bases
    files:
      - base.json
  - repo: https://github.com/org/devcontainers
    ref: refs/heads/main
    subdirectory: languages
    files:
      - python.jsonnet
  - repo: https://github.com/org/team-overlays
    ref: refs/heads/main
    subdirectory: data-team
    files:
      - jupyter.jsonnet
gantry build --config gantry.yaml --write
Authentication
Method Flags
Token (HTTPS) --token
Basic auth --username / --password
SSH key --ssh-key-path / --ssh-key-password

In YAML configs, all string fields support ${ENV_VAR} interpolation:

overlays:
  - repo: https://github.com/org/private-devcontainers
    ref: refs/heads/main
    files:
      - base.jsonnet
    auth:
      token: ${GITHUB_TOKEN}

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
pkg
git

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL