🏭 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
buildafter 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.
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
| Method | Signature | Description |
|---|---|---|
| 🏗️ CreateSatisConfig | func (c *Composer) CreateSatisConfig(configPath string, name string, homepage string) error | Write the initial satis.json |
| ➕ AddSatisRepository | func (c *Composer) AddSatisRepository(configPath string, type_ string, url string) error | Append a repository |
| 🏭 BuildSatis | func (c *Composer) BuildSatis(configPath string, outputDir string) (string, error) | Run satis build |
| 🚀 InitSatis | func (c *Composer) InitSatis(name string, homepage string, dir string) error | Create the directory and write the config |
| 🎚️ UpdateSatisStability | func (c *Composer) UpdateSatisStability(configPath string, stability string) error | Update minimum stability |
| 🗜️ EnableSatisArchive | func (c *Composer) EnableSatisArchive(configPath string, format string) error | Enable the archive feature |
| 📌 AddSatisRequire | func (c *Composer) AddSatisRequire(configPath string, packageName string, version string) error | Append a dependency and turn off require-all |
Parameters
CreateSatisConfig / InitSatis
| Parameter | Type | Description |
|---|---|---|
configPath / dir | string | Config file path / output directory (InitSatis creates satis.json under it) |
name | string | Repository name, e.g., acme/private-packages |
homepage | string | Repository homepage URL, also the root address packages are referenced from |
AddSatisRepository
| Parameter | Type | Description |
|---|---|---|
type_ | string | Repository type, e.g., vcs, git, composer |
url | string | Repository address |
UpdateSatisStability
| Parameter | Type | Description |
|---|---|---|
stability | string | Must be one of dev / alpha / beta / RC / stable |
EnableSatisArchive
| Parameter | Type | Description |
|---|---|---|
format | string | Archive format; empty defaults to zip |
Examples
Initialize and Build from Scratch
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)
// 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.