diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..bac0b830 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,120 @@ +name: Release + +on: + # Allow manual trigger + workflow_dispatch: + inputs: + tag: + description: "Tag to apply to image" + required: true + default: "latest" + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + packages: write + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.24.5" + + - name: Build cross-platform binaries + env: + GOFLAGS: -mod=vendor + run: | + # Get version info + GIT_HASH=$(git rev-parse --short HEAD) + FULL_GIT_HASH=${{ github.sha }} + BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) + + # Set ldflags for version information + LDFLAGS="-s -w -X github.com/carlmjohnson/versioninfo.Version=${GIT_HASH} -X github.com/carlmjohnson/versioninfo.Revision=${FULL_GIT_HASH}" + + # Create binaries directory + mkdir -p binaries + + GOOS=linux GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o binaries/smokescreen-linux-amd64 . + + GOOS=linux GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o binaries/smokescreen-linux-arm64 . + + GOOS=darwin GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o binaries/smokescreen-darwin-amd64 . + + GOOS=darwin GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o binaries/smokescreen-darwin-arm64 . + + # Create checksums + cd binaries + sha256sum * > checksums.txt + cd .. + + # List built binaries + ls -la binaries/ + + - name: Setup ko + uses: ko-build/setup-ko@v0.9 + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push multi-platform image + id: build + env: + KO_DOCKER_REPO: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + GOFLAGS: -mod=vendor + run: | + # Get git hash for tagging + GIT_HASH=$(git rev-parse --short HEAD) + FULL_GIT_HASH=${{ github.sha }} + + # Determine tags based on trigger type + if [[ "${{ github.ref_type }}" == "tag" ]]; then + # For version tags, use the tag name + TAG_NAME=${GITHUB_REF#refs/tags/} + TAGS="${GIT_HASH},${FULL_GIT_HASH},${TAG_NAME},latest" + else + # For manual dispatch, use the input tag + TAGS="${GIT_HASH},${FULL_GIT_HASH},${{ inputs.tag }}" + fi + + # Build and push multi-platform image with git hash tags + # Note: platforms are defined in .ko.yaml as defaultPlatforms + IMAGE_URI=$(ko build . --tags=${TAGS} --bare) + echo "image-uri=$IMAGE_URI" >> $GITHUB_OUTPUT + echo "Built and pushed: $IMAGE_URI" + echo "Tagged with: ${TAGS}" + + - name: Install Cosign + uses: sigstore/cosign-installer@v3.9.1 + with: + cosign-release: "v2.5.2" + + - name: Sign container image + run: | + # Sign the container image + cosign sign --yes ${{ steps.build.outputs.image-uri }} + + - name: Create GitHub Release + if: startsWith(github.ref, 'refs/tags/') + # v2.3.2 + uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 + with: + files: | + binaries/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index dde12ee0..a0d9b9ed 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ *.swo *.swn *debug.test* +/binaries \ No newline at end of file diff --git a/.ko.yaml b/.ko.yaml new file mode 100644 index 00000000..27a6d6bf --- /dev/null +++ b/.ko.yaml @@ -0,0 +1,12 @@ +builds: + - id: smokescreen + main: ./main.go + env: + - CGO_ENABLED=0 + flags: + - -mod=vendor + +defaultBaseImage: gcr.io/distroless/static:nonroot +defaultPlatforms: + - linux/amd64 + - linux/arm64 diff --git a/Development.md b/Development.md index 13b007a7..fda1d453 100644 --- a/Development.md +++ b/Development.md @@ -306,3 +306,27 @@ curl --proxytunnel -x https://localhost:4750 --cacert vendor/github.com/stripe/g # Curl with HTTPS_PROXY HTTPS_PROXY=https://localhost:4750 curl --cacert vendor/github.com/stripe/goproxy/ca.pem --proxy-cacert mtls_setup/server-ca.crt --proxy-cert mtls_setup/client.crt --proxy-key mtls_setup/client.key https://wttr.in ``` + +## Working with container images locally + +### Building Locally + +To build the container image outside of CI: + +```bash +# Install ko +go install github.com/ko-build/ko@latest + +# Build for multiple platforms +ko build . --platform=linux/amd64,linux/arm64 --local +``` + +### Verification + +To verify the signatures of published images: + +```bash +cosign verify ghcr.io/stripe/smokescreen:latest \ + --certificate-identity-regexp="https://github.com/stripe/smokescreen" \ + --certificate-oidc-issuer="https://token.actions.githubusercontent.com" +``` diff --git a/README.md b/README.md index 1ab88070..b4532ded 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,48 @@ If a domain matches both the `global_allow_list` and the `global_deny_list`, the See [Development.md](Development.md) +# Binary Releases + +This project provides both pre-built container images and native binaries for smokescreen that are automatically built and published. + +## Standalone binaries + +Pre-compiled binaries are available for download from the [GitHub Releases](https://github.com/stripe/smokescreen/releases) page: + +- **Linux**: `smokescreen-linux-amd64`, `smokescreen-linux-arm64` +- **macOS**: `smokescreen-darwin-amd64`, `smokescreen-darwin-arm64` + +### Download and Install + +```bash +# Download the latest binary (replace with your platform) +curl -L -o smokescreen https://github.com/stripe/smokescreen/releases/latest/download/smokescreen-linux-amd64 + +# Make it executable +chmod +x smokescreen + +# Run +./smokescreen --help + ``` + +## Container Images + +The container images are available at: +- `ghcr.io/stripe/smokescreen:latest` + +### Supported Platforms + +- `linux/amd64` - Intel/AMD 64-bit +- `linux/arm64` - ARM 64-bit + +### Running the Container + +```bash +docker run -p 4750:4750 ghcr.io/stripe/smokescreen:latest --listen-ip 0.0.0.0 --listen-port 4750 +``` + +Smokescreen can then be used like in `curl --proxy localhost:4750 http://example.com`. + # Contributors - Aditya Mukerjee