Skip to content

🤖 Auto-Detect & Install in CI/CD

In 10 minutes, let a freshly initialized GitHub Actions runner automatically install Composer, then run composer install + security audit. Zero pre-installation, cross-platform.

Why Auto-Install?

CI runner images don't always have Composer pre-installed. Writing bash scripts for "detect → choose package manager → install → install extensions" is messy and fragile. The installer package wraps this chain into a smart installer, automatically choosing brew / apt / direct download by platform, and can also install PHP.

Step 1: Detect Current State

installer.IsComposerInstalled() returns a triple (bool, path, version), first confirm if installation is really needed.

go
ok, path, ver := installer.IsComposerInstalled()

Step 2: Smart Installation

installer.NewSmartInstaller(installer.DefaultInstallOptions()) creates a smart installer; InstallWithProgress() returns (*InstallResult, error), reporting progress by stage.

Step 3: Ready to Use After Installation

After installation completes, directly create a Composer instance with composer.New(composer.DefaultOptions()) — its AutoInstall is enabled by default, so it will self-heal even if Composer disappears later.

Go Code: ensure-and-audit.go

go
package main

import (
	"fmt"
	"log"

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

func main() {
	// 1️⃣ Detect
	if ok, path, ver := installer.IsComposerInstalled(); ok {
		fmt.Printf("✅ Composer already installed: %s (%s)\n", path, ver)
	} else {
		fmt.Println("⚠️  Composer not detected, starting smart installation...")
		si := installer.NewSmartInstaller(installer.DefaultInstallOptions())
		result, err := si.InstallWithProgress()
		if err != nil {
			log.Fatalf("Installation failed: %v", err)
		}
		fmt.Printf("🎉 Installation complete: %s\n", result.ComposerPath)
	}

	// 2️⃣ Get Composer instance
	comp, err := composer.New(composer.DefaultOptions())
	if err != nil {
		log.Fatal(err)
	}
	comp.SetWorkingDir(".")

	// 3️⃣ Install dependencies + audit
	if err := comp.Install(false, true); err != nil {
		log.Fatalf("install failed: %v", err)
	}
	audit, err := comp.AuditWithJSON()
	if err != nil {
		log.Fatal(err)
	}
	if audit.Found > 0 {
		log.Fatalf("❌ Found %d vulnerabilities, CI failed", audit.Found)
	}
	fmt.Println("✅ Dependencies installed, no vulnerabilities")
}

Step 4: GitHub Actions Workflow

Using the Go program above as the CI entry point, the workflow only needs to set up Go:

yaml
# .github/workflows/audit.yml
name: Install & Audit
on: [push, pull_request]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: Ensure Composer & Audit
        run: go run ./ensure-and-audit.go

Don't want to write Go?

You can use the ready-made CLI directly in the workflow, it also has built-in auto-install logic:

bash
go run ./cmd/composer-skills local install --working-dir .
go run ./cmd/composer-skills local audit --working-dir .

Expected Output (Fresh Runner)

⚠️  Composer not detected, starting smart installation...
[stage] detecting platform... (25%)
[stage] downloading composer... (60%)
[stage] verifying... (85%)
🎉 Installation complete: /usr/local/bin/composer
✅ Dependencies installed, no vulnerabilities

Advanced: Progress Callback & Functional Entry

go
// Subscribe to installation progress
opts := installer.DefaultInstallOptions()
opts.ProgressCallback = func(p installer.InstallProgress) {
	fmt.Printf("[%s] %s (%d%%)\n", p.Stage, p.Message, p.Percent)
}
si := installer.NewSmartInstaller(opts)
result, err := si.InstallWithProgress()
_ = result

// Or use one-shot function, suitable for ensuring dependencies inside a library
r, err := installer.EnsureComposerInstalled(nil)

InstallProgress contains Stage, Message, Percent, Timestamp fields; Stage values are constants like installer.StageDownloading, installer.StageInstalling.

Windows Runner

On Windows, the smart installer downloads the official .phar and places it in the user directory. Ensure the workflow has write permissions; actions/setup-go default runners all satisfy this.

Next Steps

Released under the MIT License