Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

160 changes: 160 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

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.

## Build and Test Commands

Build a single binary for your platform:
```bash
make single
```

Build a snapshot for all platforms:
```bash
make snapshot
```

Run tests:
```bash
make test
# or directly:
GOEXPERIMENT=jsonv2 go test -v -race -cover -count=1 ./...
```

Run linters:
```bash
make lint
# or individual linters:
make lint-gomod
make lint-golangci
```

Format code:
```bash
go fmt ./...
```

Tidy dependencies:
```bash
go mod tidy
```

Run a single test:
```bash
go test -v -run TestName ./path/to/package
```

## Architecture

### Hybrid CLI System

The CLI operates as a wrapper around a legacy PHP CLI:
- Go layer: Handles new commands (init, list, version, config:install, project:convert) and core infrastructure
- PHP layer: Legacy commands are proxied through `internal/legacy/CLIWrapper`
- The PHP CLI (platform.phar) is embedded at build time via go:embed

### Key Components

**Entry Point**: `cmd/platform/main.go`
- Loads configuration from YAML (embedded or external)
- Sets up Viper for environment variable handling
- Delegates to commands package

**Commands**: `commands/`
- `root.go`: Root command that sets up the Cobra CLI and delegates to legacy CLI when needed
- Native Go commands: init, list, version, config:install, project:convert, completion
- Unrecognized commands are passed to the legacy PHP CLI

**Configuration**: `internal/config/`
- `schema.go`: Config struct definition with validation tags
- Supports vendorization through embedded YAML configs (config_upsun.go, config_platformsh.go, config_vendor.go)
- Uses build tags to select which config is embedded
- Config can be loaded from external files for testing/development

**Legacy Integration**: `internal/legacy/`
- `legacy.go`: CLIWrapper that manages PHP binary and phar execution
- PHP binaries are embedded per platform via go:embed and build tags
- Uses file locking to prevent concurrent initialization
- Copies PHP binary and phar to cache directory on first run

**API Client**: `internal/api/`
- HTTP client for interacting with Platform.sh/Upsun API
- Handles authentication, organizations, and resource management

**Authentication**: `internal/auth/`
- JWT handling and OAuth2 flow
- Custom transport for API authentication

**Project Initialization**: `internal/init/`
- AI-powered project configuration generation
- Integrates with whatsun library for codebase analysis

### Build System

**Multi-Vendor Support**:
- Uses Go build tags (platform, upsun, vendor) to compile different binaries
- Configuration is embedded at compile time
- GoReleaser builds multiple variants (platform, upsun, vendor-specific)

**PHP Binary Handling**:
- PHP binaries are downloaded from [upsun/cli-php-builds](https://github.com/upsun/cli-php-builds) releases
- All platforms use static binaries built with [static-php-cli](https://github.com/crazywhalecc/static-php-cli)
- Supported platforms: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64
- Extensions included: curl, filter, openssl, pcntl (Unix), phar, posix (Unix), zlib
- Windows requires `cacert.pem` for OpenSSL (embedded separately)

**Downloading PHP Binaries**:
```bash
# Download PHP for current platform only (for development)
make php

# Download all PHP binaries (for release builds)
make download-php
```

**Upgrading PHP Version**:
1. Trigger the build workflow at [upsun/cli-php-builds](https://github.com/upsun/cli-php-builds/actions) with the new PHP version
2. Update `PHP_VERSION` in the Makefile
3. Run `make php` to download the new binary
4. Test and release

## Development Notes

### Testing

Tests use github.com/stretchr/testify for assertions. Table-driven tests are preferred with a "cases" slice containing simple test case structs.

### Configuration

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.

### Legacy CLI Interaction

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.

### Vendorization

To build a vendor-specific CLI:
```bash
make vendor-snapshot VENDOR_NAME='Vendor Name' VENDOR_BINARY='vendorcli'
make vendor-release VENDOR_NAME='Vendor Name' VENDOR_BINARY='vendorcli'
```

This requires a config file at `internal/config/embedded-config.yaml` (downloaded at build time).

### Version Information

Version information is injected at build time via ldflags:
- `internal/config.Version`: Git tag/version
- `internal/config.Commit`: Git commit hash
- `internal/config.Date`: Build date
- `internal/legacy.PHPVersion`: PHP version embedded
- `internal/legacy.LegacyCLIVersion`: Legacy CLI version embedded

### Update Checks

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.
80 changes: 0 additions & 80 deletions Dockerfile.php

This file was deleted.

70 changes: 35 additions & 35 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PHP_VERSION = 8.2.29
PHP_VERSION = 8.4.16
LEGACY_CLI_VERSION = 4.28.2

GORELEASER_ID ?= upsun
Expand All @@ -7,10 +7,6 @@ ifeq ($(GOOS), darwin)
GORELEASER_ID=$(GORELEASER_ID)-macos
endif

# The OpenSSL version must be compatible with the PHP version.
# See: https://www.php.net/manual/en/openssl.requirements.php
OPENSSL_VERSION = 1.1.1t

GOOS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
GOARCH := $(shell uname -m)
ifeq ($(GOARCH), x86_64)
Expand All @@ -20,51 +16,55 @@ ifeq ($(GOARCH), aarch64)
GOARCH=arm64
endif

PHP_BINARY_PATH := internal/legacy/archives/php_$(GOOS)_$(GOARCH)
VERSION := $(shell git describe --always)

# Tooling versions
GORELEASER_VERSION=v2.12.0

internal/legacy/archives/platform.phar:
curl -L https://github.com/platformsh/legacy-cli/releases/download/v$(LEGACY_CLI_VERSION)/platform.phar -o internal/legacy/archives/platform.phar
# PHP binaries are downloaded from cli-php-builds releases.
# See: https://github.com/upsun/cli-php-builds
PHP_BUILDS_REPO = upsun/cli-php-builds
PHP_RELEASE_URL = https://github.com/$(PHP_BUILDS_REPO)/releases/download/php-$(PHP_VERSION)

internal/legacy/archives/php_windows_amd64: internal/legacy/archives/php_windows.zip internal/legacy/archives/cacert.pem
internal/legacy/archives/platform.phar:
mkdir -p internal/legacy/archives
curl -fSL https://github.com/platformsh/legacy-cli/releases/download/v$(LEGACY_CLI_VERSION)/platform.phar -o internal/legacy/archives/platform.phar

# Download PHP binary for the current platform.
internal/legacy/archives/php_darwin_$(GOARCH):
bash build-php-brew.sh $(GOOS) $(PHP_VERSION) $(OPENSSL_VERSION)
mv -f $(GOOS)/php-$(PHP_VERSION)/sapi/cli/php $(PHP_BINARY_PATH)
rm -rf $(GOOS)
mkdir -p internal/legacy/archives
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-darwin-$(GOARCH)" -o $@
chmod +x $@

internal/legacy/archives/php_linux_$(GOARCH):
cp ext/extensions.txt ext/static-php-cli/docker
docker buildx build \
--build-arg GOARCH=$(GOARCH) \
--build-arg PHP_VERSION=$(PHP_VERSION) \
--build-arg USE_BACKUP_ADDRESS=yes \
--file=./Dockerfile.php \
--platform=linux/$(GOARCH) \
--output=type=local,dest=./internal/legacy/archives/ \
--progress=plain \
ext/static-php-cli/docker

PHP_WINDOWS_REMOTE_FILENAME := "php-$(PHP_VERSION)-nts-Win32-vs16-x64.zip"
internal/legacy/archives/php_windows.zip:
( \
set -e ;\
mkdir -p internal/legacy/archives ;\
cd internal/legacy/archives ;\
curl -f "https://windows.php.net/downloads/releases/$(PHP_WINDOWS_REMOTE_FILENAME)" > php_windows.zip ;\
curl -f https://windows.php.net/downloads/releases/sha256sum.txt | grep "$(PHP_WINDOWS_REMOTE_FILENAME)" | sed s/"$(PHP_WINDOWS_REMOTE_FILENAME)"/"php_windows.zip"/g > php_windows.zip.sha256 ;\
sha256sum -c php_windows.zip.sha256 ;\
)
mkdir -p internal/legacy/archives
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-linux-$(GOARCH)" -o $@
chmod +x $@

internal/legacy/archives/php_windows_amd64: internal/legacy/archives/php_windows.exe internal/legacy/archives/cacert.pem

internal/legacy/archives/php_windows.exe:
mkdir -p internal/legacy/archives
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-windows-amd64.exe" -o $@

.PHONY: internal/legacy/archives/cacert.pem
internal/legacy/archives/cacert.pem:
mkdir -p internal/legacy/archives
curl https://curl.se/ca/cacert.pem > internal/legacy/archives/cacert.pem
curl -fSL https://curl.se/ca/cacert.pem -o internal/legacy/archives/cacert.pem

php: $(PHP_BINARY_PATH)
# Download all PHP binaries (for release builds).
.PHONY: download-php
download-php:
mkdir -p internal/legacy/archives
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-linux-amd64" -o internal/legacy/archives/php_linux_amd64
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-linux-arm64" -o internal/legacy/archives/php_linux_arm64
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-darwin-amd64" -o internal/legacy/archives/php_darwin_amd64
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-darwin-arm64" -o internal/legacy/archives/php_darwin_arm64
curl -fSL "$(PHP_RELEASE_URL)/php-$(PHP_VERSION)-windows-amd64.exe" -o internal/legacy/archives/php_windows.exe
curl -fSL https://curl.se/ca/cacert.pem -o internal/legacy/archives/cacert.pem
chmod +x internal/legacy/archives/php_linux_* internal/legacy/archives/php_darwin_*

php: internal/legacy/archives/php_$(GOOS)_$(GOARCH)

.PHONY: goreleaser
goreleaser:
Expand Down
44 changes: 0 additions & 44 deletions build-php-brew.sh

This file was deleted.

Loading