quitsh

module
v0.23.0 Latest Latest
Warning

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

Go to latest
Published: May 14, 2025 License: MIT

README

Coverage Current Release Pipeline Status License label


[!CAUTION]

This repository is in beta and not stable enough since the design space of this tool is still explored.

The quitsh framework (/kwɪʧ/) is a build-tooling CLI framework designed to replace loosely-typed scripting languages (e.g., bash, python, and similar alternatives) with the statically-typed language Go. Its goal is to simplify tooling tasks while providing robust, extendable solutions for component repositories (mono-repositories).

quitsh is an opinionated framework born out of frustration with the lack of simple and extendable tooling for mono-repos. It is language-agnostic and toolchain-independent, allowing users to focus on their workflows without being constrained by specific technologies.

Key Features

Code-First Approach

  • All tooling logic is implemented in Go.
  • Tasks are defined primarily in code, avoiding declarative configurations or templated non-typed languages, which often add unnecessary complexity despite their flexibility.

Component Identification

  • Components (i.e., buildable units) are identified by placing a configuration file (default: .component.yaml) in the corresponding subdirectory.

Extendability

  • quitsh serves as a library to build your customized CLI tool for your specific tasks.
  • Users can add custom commands and specialized tooling features using libraries like cobra.

Targets and Steps

  • Each component defines targets, which consist of multiple steps.
  • Targets can depend on other targets across the repository.
  • Input change sets can be specified for each target to track modifications and determine if the target is outdated.

Runner System

  • Steps within targets are executed by runners, which are written by you in Go and act as reusable replacements for traditional build/tooling scripts.
  • Runners can have custom YAML configuration options specified per component in .component.yaml.

Toolchain Dispatch

  • Runners are associated with specific toolchains.

  • By default, quitsh includes a Nix development shell dispatch, providing stable and reproducible environments.

  • While container-based dispatching is not a primary goal, it can be implemented by extending the dispatch interface.

  • The tool was built to replicate the same procedure one executes during local development and also in CI. Having CI align with what you execute locally is not a nice thing to have, its a necessity. Nix development shells (or containers) help with this. A Nix shell provides a simple and robust abstraction to pin a toolchain. The following visualization gives an overview about how quitsh is used:

    quitsh-design

Built-in Libraries

The pkg folder offers utilities for common development needs, such as:

  • Command Execution: pkg/exec provides utilities for process execution and command chaining.
  • Structured Logging: pkg/log enables consistent and readable logging.
  • Error Handling: pkg/error facilitates contextual error management.
  • Dependency Graphs: Tools for managing and resolving dependency graphs across targets.
  • Some Go test runners (here as an example) for running Go tests (its used internally to test quitsh it-self).

Performance

  • Since all tooling is written in Go, quitsh provides type safety and fast performance by default.
  • Combined with Nix-based toolchain dispatch and the ability to write tests easily, the framework significantly accelerates the "change, test, improve" workflow.

Nix Integration

  • CLI tools built with quitsh can be seamlessly packaged into Nix development shells, ensuring accessibility for all users of a given repository.

How We Use It?

TODO: unfinished.

Understand what this framework does, is best accomplished by understanding how we use this framework in our components repo (mono-repo).

Components

Our major components are located in ./components. Each component in quitsh is defined by a .component.yaml (name is customizable) file which more or less looks like:

# The name of the component: Must be a unique.
name: my-component

# A semantic version.
# This is useful for Nix packaging etc.
version: 0.2.1

# A simple annotation (not used internally) what main language this component uses.
language: go

targets:
  # A target called `test` with two steps.
  my-test:
    # The stage to which this target belongs. Does not need to be provided
    # if the CLI is setup to map target names to stages.
    stage: test

    steps:
      # Step 1: Using runner with ID (how it was registered).
      - runner-id: banana-project::my-test-runner
        config: # Your custom runner YAML config, (optional).

      # Step 2: Using a runner with registered key (stage: `test`, name `my-test`)
      - runner: my-test

  # A target called `build-all` with one step.
  build-all:
    stage: build

    # Defining when this target is considered changed:
    # i.e. whenever `self::sources` input change set is changed.
    inputs: ["self::sources"]

    # Defining dependencies on other targets such that this
    # target is executed after target `my-test` above.
    # You can also link to other components (e.g `other-comp::build`).
    depends: ["self::my-test"]

    steps:
      # Step 1: Using a runner with registered key (stage: `build`, name `my-test`)
      - runner: my-build
        config:
          tags: ["doit"]

  lint:
    steps:
      - ... other steps ...

inputs:
  # An input change set with name `sources` which defines
  # patterns to match all source files.
  sources:
    # A regex which matches `*.go` files in `./src` in the components folder.
    patterns:
      - '^./src/.*\.go$'

Jump to

Keyboard shortcuts

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