Shipper CLI Build and Distribution
This document explains the complete build and distribution system for the Shipper CLI.
Overview
The Shipper CLI can be distributed and used in three ways:
- Local Development: Run from source with
./shipper - Pre-built Binary: Download from GitHub releases
- GitHub Action: Use in workflows via the reusable action
Build System
Box Configuration (box.json)
The build system uses Box to create a PHAR (PHP Archive) binary:
- Input: PHP source code + dependencies
- Output: Single executable file (
builds/shipper) - Compression: GZ compression for smaller file size
- Contents: All app code, config, routes, and vendor dependencies
Build Process
Local Build
composer build
This will:
- Download Box if not present
- Compile the PHAR using box.json configuration
- Output to
builds/shipper
CI Build (GitHub Actions)
The .github/workflows/build-release.yml workflow automatically builds and releases binaries when a version tag is pushed:
- Trigger: Push a tag like
v1.0.0 - Process:
- Install PHP 8.3
- Install composer dependencies (production only)
- Download Box
- Build PHAR
- Test the binary
- Create GitHub release
- Attach binary to release
Example:
git tag v1.0.0
git push origin v1.0.0
This creates a release at: https://github.com/ulties/shipper/releases/tag/v1.0.0
Distribution
GitHub Releases
Each tagged version creates a release with the binary attached. Users can download with:
# Latest version
curl -LSso shipper https://github.com/ulties/shipper/releases/latest/download/shipper
chmod +x shipper
curl -LSso shipper https://github.com/ulties/shipper/releases/download/v1.0.0/shipper
chmod +x shipper
Reusable GitHub Action
The .github/actions/shipper/action.yml provides a reusable action that:
- Downloads the binary from releases
- Verifies it's executable and valid
- Runs the specified shipper command
- Returns the exit code
Usage in other repositories:
- uses: ulties/shipper/.github/actions/shipper@main
with:
command: apply
project: api
profile: production
force: true
env:
PLOI_API_KEY: ${{ secrets.PLOI_API_KEY }}
Security
Build Process
- Dependencies are locked via
composer.lock - Production dependencies only (--no-dev)
- Code is compressed but not obfuscated
Action Security
- No eval or shell injection vulnerabilities
- User inputs handled with bash arrays
- Binary verification before execution
- Downloads from official GitHub releases only
File Structure
.
├── box.json # Box configuration
├── composer.json # Build script
├── .github/
│ ├── workflows/
│ │ └── build-release.yml # Build automation
│ └── actions/
│ └── shipper/
│ ├── action.yml # Reusable action
│ └── README.md # Action documentation
└── builds/ # Build output (gitignored)
└── shipper # Compiled binary
Version Management
Semantic Versioning
Use semantic versioning for releases:
- Major (v2.0.0): Breaking changes
- Minor (v1.1.0): New features, backward compatible
- Patch (v1.0.1): Bug fixes
Tagging Process
# Create and push tag
git tag v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
# The build-release.yml workflow automatically:
# 1. Builds the binary
# 2. Creates a GitHub release
# 3. Uploads the binary
Action Versioning
Users can reference the action by:
- Branch:
@main(latest development) - Tag:
@v1.0.0(specific version) - Commit:
@939e086(specific commit)
Recommendation: Use tags for stability in production workflows.
Troubleshooting
Build Failures
Problem: Build fails with missing dependencies
Class "LaravelZero\Framework\Application" not found
Solution: Ensure composer install runs successfully first. The vendor directory must be complete before building.
Problem: Box validation fails
The configuration file failed validation
Solution: Validate the configuration:
php box.phar validate
Action Failures
Problem: Binary download fails
Error: Failed to download or make shipper executable
Solution:
- Check the release exists at the specified version
- Verify GitHub Actions has internet access
- Check if the release has the binary attached
Problem: Command fails with wrong arguments
Command "aplpy" is not defined
Solution: Check the command name is correct (validate, plan, apply)
Development Workflow
Making Changes
- Make code changes
- Test locally:
./shipper validate - Commit and push
- CI runs tests and linting
- Merge to main
Creating a Release
- Update version in
config/app.phpif needed - Update CHANGELOG (if maintained)
- Create and push tag:
git tag v1.x.x git push origin v1.x.x - GitHub Actions builds and releases automatically
- Verify release appears with binary attached
Testing the Action
Create a test workflow in any repository:
name: Test Shipper Action
on: workflow_dispatch
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ulties/shipper/.github/actions/shipper@main
with:
command: validate
Future Enhancements
Potential improvements to the build system:
- Checksums: Generate and publish SHA256 checksums for binaries
- Code Signing: Sign binaries for additional trust
- Multi-platform: Build for different PHP versions or architectures
- Homebrew: Create a Homebrew formula for easy installation
- Docker: Provide Docker images with the binary pre-installed
- Versioning in Binary: Embed git commit hash in --version output