|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +The Upsun CLI is a Go-based command-line interface for Upsun (formerly Platform.sh). The CLI is a hybrid system that wraps a legacy PHP CLI while providing new Go-based commands. It supports multiple vendors through build tags and configuration files. |
| 8 | + |
| 9 | +## Build and Test Commands |
| 10 | + |
| 11 | +Build a single binary for your platform: |
| 12 | +```bash |
| 13 | +make single |
| 14 | +``` |
| 15 | + |
| 16 | +Build a snapshot for all platforms: |
| 17 | +```bash |
| 18 | +make snapshot |
| 19 | +``` |
| 20 | + |
| 21 | +Run tests: |
| 22 | +```bash |
| 23 | +make test |
| 24 | +# or directly: |
| 25 | +GOEXPERIMENT=jsonv2 go test -v -race -cover -count=1 ./... |
| 26 | +``` |
| 27 | + |
| 28 | +Run linters: |
| 29 | +```bash |
| 30 | +make lint |
| 31 | +# or individual linters: |
| 32 | +make lint-gomod |
| 33 | +make lint-golangci |
| 34 | +``` |
| 35 | + |
| 36 | +Format code: |
| 37 | +```bash |
| 38 | +go fmt ./... |
| 39 | +``` |
| 40 | + |
| 41 | +Tidy dependencies: |
| 42 | +```bash |
| 43 | +go mod tidy |
| 44 | +``` |
| 45 | + |
| 46 | +Run a single test: |
| 47 | +```bash |
| 48 | +go test -v -run TestName ./path/to/package |
| 49 | +``` |
| 50 | + |
| 51 | +## Architecture |
| 52 | + |
| 53 | +### Hybrid CLI System |
| 54 | + |
| 55 | +The CLI operates as a wrapper around a legacy PHP CLI: |
| 56 | +- Go layer: Handles new commands (init, list, version, config:install, project:convert) and core infrastructure |
| 57 | +- PHP layer: Legacy commands are proxied through `internal/legacy/CLIWrapper` |
| 58 | +- The PHP CLI (platform.phar) is embedded at build time via go:embed |
| 59 | + |
| 60 | +### Key Components |
| 61 | + |
| 62 | +**Entry Point**: `cmd/platform/main.go` |
| 63 | +- Loads configuration from YAML (embedded or external) |
| 64 | +- Sets up Viper for environment variable handling |
| 65 | +- Delegates to commands package |
| 66 | + |
| 67 | +**Commands**: `commands/` |
| 68 | +- `root.go`: Root command that sets up the Cobra CLI and delegates to legacy CLI when needed |
| 69 | +- Native Go commands: init, list, version, config:install, project:convert, completion |
| 70 | +- Unrecognized commands are passed to the legacy PHP CLI |
| 71 | + |
| 72 | +**Configuration**: `internal/config/` |
| 73 | +- `schema.go`: Config struct definition with validation tags |
| 74 | +- Supports vendorization through embedded YAML configs (config_upsun.go, config_platformsh.go, config_vendor.go) |
| 75 | +- Uses build tags to select which config is embedded |
| 76 | +- Config can be loaded from external files for testing/development |
| 77 | + |
| 78 | +**Legacy Integration**: `internal/legacy/` |
| 79 | +- `legacy.go`: CLIWrapper that manages PHP binary and phar execution |
| 80 | +- PHP binaries are embedded per platform via go:embed and build tags |
| 81 | +- Uses file locking to prevent concurrent initialization |
| 82 | +- Copies PHP binary and phar to cache directory on first run |
| 83 | + |
| 84 | +**API Client**: `internal/api/` |
| 85 | +- HTTP client for interacting with Platform.sh/Upsun API |
| 86 | +- Handles authentication, organizations, and resource management |
| 87 | + |
| 88 | +**Authentication**: `internal/auth/` |
| 89 | +- JWT handling and OAuth2 flow |
| 90 | +- Custom transport for API authentication |
| 91 | + |
| 92 | +**Project Initialization**: `internal/init/` |
| 93 | +- AI-powered project configuration generation |
| 94 | +- Integrates with whatsun library for codebase analysis |
| 95 | + |
| 96 | +### Build System |
| 97 | + |
| 98 | +**Multi-Vendor Support**: |
| 99 | +- Uses Go build tags (platform, upsun, vendor) to compile different binaries |
| 100 | +- Configuration is embedded at compile time |
| 101 | +- GoReleaser builds multiple variants (platform, upsun, vendor-specific) |
| 102 | + |
| 103 | +**PHP Binary Handling**: |
| 104 | +- PHP binaries are downloaded from [upsun/cli-php-builds](https://github.com/upsun/cli-php-builds) releases |
| 105 | +- All platforms use static binaries built with [static-php-cli](https://github.com/crazywhalecc/static-php-cli) |
| 106 | +- Supported platforms: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64 |
| 107 | +- Extensions included: curl, filter, openssl, pcntl (Unix), phar, posix (Unix), zlib |
| 108 | +- Windows requires `cacert.pem` for OpenSSL (embedded separately) |
| 109 | + |
| 110 | +**Downloading PHP Binaries**: |
| 111 | +```bash |
| 112 | +# Download PHP for current platform only (for development) |
| 113 | +make php |
| 114 | + |
| 115 | +# Download all PHP binaries (for release builds) |
| 116 | +make download-php |
| 117 | +``` |
| 118 | + |
| 119 | +**Upgrading PHP Version**: |
| 120 | +1. Trigger the build workflow at [upsun/cli-php-builds](https://github.com/upsun/cli-php-builds/actions) with the new PHP version |
| 121 | +2. Update `PHP_VERSION` in the Makefile |
| 122 | +3. Run `make php` to download the new binary |
| 123 | +4. Test and release |
| 124 | + |
| 125 | +## Development Notes |
| 126 | + |
| 127 | +### Testing |
| 128 | + |
| 129 | +Tests use github.com/stretchr/testify for assertions. Table-driven tests are preferred with a "cases" slice containing simple test case structs. |
| 130 | + |
| 131 | +### Configuration |
| 132 | + |
| 133 | +The CLI uses Viper for configuration. Environment variables use the prefix defined in the config (UPSUN_CLI_ or PLATFORM_CLI_). The prefix is set in the config YAML. |
| 134 | + |
| 135 | +### Legacy CLI Interaction |
| 136 | + |
| 137 | +When the root command receives arguments it doesn't recognize, it passes them to the legacy PHP CLI via CLIWrapper.Exec(). The PHP binary and phar are extracted to a cache directory on first use. |
| 138 | + |
| 139 | +### Vendorization |
| 140 | + |
| 141 | +To build a vendor-specific CLI: |
| 142 | +```bash |
| 143 | +make vendor-snapshot VENDOR_NAME='Vendor Name' VENDOR_BINARY='vendorcli' |
| 144 | +make vendor-release VENDOR_NAME='Vendor Name' VENDOR_BINARY='vendorcli' |
| 145 | +``` |
| 146 | + |
| 147 | +This requires a config file at `internal/config/embedded-config.yaml` (downloaded at build time). |
| 148 | + |
| 149 | +### Version Information |
| 150 | + |
| 151 | +Version information is injected at build time via ldflags: |
| 152 | +- `internal/config.Version`: Git tag/version |
| 153 | +- `internal/config.Commit`: Git commit hash |
| 154 | +- `internal/config.Date`: Build date |
| 155 | +- `internal/legacy.PHPVersion`: PHP version embedded |
| 156 | +- `internal/legacy.LegacyCLIVersion`: Legacy CLI version embedded |
| 157 | + |
| 158 | +### Update Checks |
| 159 | + |
| 160 | +The CLI checks for updates from GitHub releases (when Wrapper.GitHubRepo is set in config). This runs in a background goroutine and prints a message after command execution. |
0 commit comments