Skip to content

🏭 Satis

Orchestrate Satis private package repository config generation and build flows in Go — create satis.json, append repositories, build the static repository, adjust stability, enable archiving, append dependencies.

Satis is Composer's official private package repository generator, packaging multiple VCS repositories into a static repository that composer can pull from. Satis itself is a standalone executable; this module assumes it has been installed via composer global require and can be invoked as composer satis.

When to Use

  • 🏢 An enterprise intranet needs to build a private Composer repository mirroring multiple GitLab projects.
  • 📦 CI brings Satis config changes under version control, auto-running build after each repository change.
  • 🔒 Offline environments pre-build archives (--archive) so deployment machines don't need access to source repositories.
  • 🎛️ Dynamically switch minimum stability (dev / RC / stable) to meet needs at different stages.

Structured Types

SatisConfig

The top-level structure written by CreateSatisConfig and read/modified by methods like AddSatisRepository.

go
type SatisConfig struct {
    Name                   string                 `json:"name"`
    Homepage               string                 `json:"homepage"`
    Repositories           []map[string]string    `json:"repositories"`
    OutputDir              string                 `json:"output-dir"`
    RequireAll             bool                   `json:"require-all,omitempty"`
    RequireDependencies    bool                   `json:"require-dependencies,omitempty"`
    RequireDevDependencies bool                   `json:"require-dev-dependencies,omitempty"`
    Require                map[string]string      `json:"require,omitempty"`
    Archive                map[string]interface{} `json:"archive,omitempty"`
    MinimumStability       string                 `json:"minimum-stability,omitempty"`
    Providers              bool                   `json:"providers,omitempty"`
    ProvidersURL           string                 `json:"providers-url,omitempty"`
    Config                 map[string]interface{} `json:"config,omitempty"`
    Notify                 map[string]interface{} `json:"notify,omitempty"`
    TwigTemplate           string                 `json:"twig-template,omitempty"`
}

Method Signatures

MethodSignatureDescription
🏗️ CreateSatisConfigfunc (c *Composer) CreateSatisConfig(configPath string, name string, homepage string) errorWrite the initial satis.json
➕ AddSatisRepositoryfunc (c *Composer) AddSatisRepository(configPath string, type_ string, url string) errorAppend a repository
🏭 BuildSatisfunc (c *Composer) BuildSatis(configPath string, outputDir string) (string, error)Run satis build
🚀 InitSatisfunc (c *Composer) InitSatis(name string, homepage string, dir string) errorCreate the directory and write the config
🎚️ UpdateSatisStabilityfunc (c *Composer) UpdateSatisStability(configPath string, stability string) errorUpdate minimum stability
🗜️ EnableSatisArchivefunc (c *Composer) EnableSatisArchive(configPath string, format string) errorEnable the archive feature
📌 AddSatisRequirefunc (c *Composer) AddSatisRequire(configPath string, packageName string, version string) errorAppend a dependency and turn off require-all

Parameters

CreateSatisConfig / InitSatis

ParameterTypeDescription
configPath / dirstringConfig file path / output directory (InitSatis creates satis.json under it)
namestringRepository name, e.g., acme/private-packages
homepagestringRepository homepage URL, also the root address packages are referenced from

AddSatisRepository

ParameterTypeDescription
type_stringRepository type, e.g., vcs, git, composer
urlstringRepository address

UpdateSatisStability

ParameterTypeDescription
stabilitystringMust be one of dev / alpha / beta / RC / stable

EnableSatisArchive

ParameterTypeDescription
formatstringArchive format; empty defaults to zip

Examples

Initialize and Build from Scratch

go
package main

import (
	"fmt"
	"log"

	"github.com/scagogogo/composer-skills/pkg/composer"
)

func main() {
	comp, err := composer.New(composer.DefaultOptions())
	if err != nil {
		log.Fatalf("Failed to initialize: %v", err)
	}

	// Initialize the satis directory and config
	if err := comp.InitSatis("acme/private-packages", "https://packages.acme.io", "satis"); err != nil {
		log.Fatal(err)
	}
	configPath := "satis/satis.json"

	// Append two VCS repositories
	if err := comp.AddSatisRepository(configPath, "vcs", "git@gitlab.acme.io:lib/logger.git"); err != nil {
		log.Fatal(err)
	}
	if err := comp.AddSatisRepository(configPath, "vcs", "git@gitlab.acme.io:lib/auth.git"); err != nil {
		log.Fatal(err)
	}

	// Enable archiving + lock stability
	if err := comp.EnableSatisArchive(configPath, "tar"); err != nil {
		log.Fatal(err)
	}
	if err := comp.UpdateSatisStability(configPath, "stable"); err != nil {
		log.Fatal(err)
	}

	// Build
	out, err := comp.BuildSatis(configPath, "satis/public")
	if err != nil {
		log.Fatalf("Build failed: %v", err)
	}
	fmt.Println(out)
}

Specify Dependencies Precisely (turn off require-all)

go
// AddSatisRequire automatically sets RequireAll to false
if err := comp.AddSatisRequire(configPath, "acme/logger", "^2.0"); err != nil {
	log.Fatal(err)
}
if err := comp.AddSatisRequire(configPath, "acme/auth", "^1.5"); err != nil {
	log.Fatal(err)
}

Advanced

UpdateSatisStability Value Validation

Passing a value that is not dev/alpha/beta/RC/stable returns an invalid stability: <value> error; the config file is not modified.

Side Effect of AddSatisRequire

A single call to AddSatisRequire sets RequireAll to false, meaning Satis only builds packages listed in Require rather than all of them. If you want "all + a few extra", don't use this method — manually edit Require and keep RequireAll=true.

BuildSatis with Empty outputDir

When outputDir is an empty string, BuildSatis runs satis build <configPath> (using the output-dir from the config file); when non-empty, it appends a second argument to override the output directory.

Released under the MIT License