diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d5eb29..6e1c237 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,8 +1,8 @@ -name: Build and publish Container Image +name: Build on: push: - branches: ["main"] + workflow_dispatch: env: REGISTRY: ghcr.io @@ -10,12 +10,13 @@ env: jobs: build-and-push-image: + name: Docker Image runs-on: ubuntu-latest permissions: contents: read packages: write outputs: - imageTag: ${{ steps.meta.outputs.tags }} + deployImage: ${{ fromJSON(steps.meta.outputs.json).tags[0] }} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -41,7 +42,12 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=sha + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha,priority=850 + type=ref,event=branch + type=ref,event=pr - name: Build and push Docker image uses: docker/build-push-action@v5 @@ -51,17 +57,39 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + + cli-binary: + name: CLI + runs-on: ubuntu-latest + permissions: + contents: write + if: github.ref_type == 'tag' + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} deploy: - name: Deploy backend + name: Deploy Backend runs-on: ubuntu-latest concurrency: deploy-group # ensure only one action runs at a time needs: build-and-push-image + if: github.ref_type == 'branch' && github.ref_name == 'main' steps: - uses: actions/checkout@v4 - uses: superfly/flyctl-actions/setup-flyctl@1.5 - - run: flyctl deploy --image ${{ needs.build-and-push-image.outputs.imageTag }} + - run: flyctl deploy --image ${{ needs.build-and-push-image.outputs.deployImage }} env: FLY_API_TOKEN: ${{ secrets.FLY_DEPLOY_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index daa9276..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Release Container Image - -on: - push: - tags: ["*"] - workflow_dispatch: - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - publish-image: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=semver,pattern={{version}} - type=raw,value=latest - type=sha - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..38a5da9 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,40 @@ +# yaml-language-server: $schema=https://goreleaser.com/static/schema.json +builds: + - id: tf-preview-gh + main: ./cmd/tf-preview-gh + binary: tf-preview-gh + + env: + - CGO_ENABLED=0 + + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + +archives: + - id: tf-preview-gh + builds: + - tf-preview-gh + format: binary + name_template: >- + {{ .Binary }}_{{ .Os }}- + {{- if eq .Arch "arm64" -}} + {{- if eq .Os "linux" -}} + aarch64 + {{- else -}} + {{ .Arch }} + {{- end -}} + {{- else if eq .Arch "amd64" -}} + x86_64 + {{- else -}} + {{ .Arch }} + {{- end }} + +checksum: + name_template: "checksums.txt" + +release: + prerelease: auto diff --git a/Dockerfile b/Dockerfile index 5b3769b..5c581ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,25 @@ # build binary -FROM golang:1.22 AS builder +FROM --platform=$BUILDPLATFORM ghcr.io/crazy-max/xgo:latest AS builder -COPY . /go/src/github.com/nimbolus/terraform-backend +COPY . /source +WORKDIR /source -WORKDIR /go/src/github.com/nimbolus/terraform-backend - -RUN GOOS=linux CGO_ENABLED=1 go build ./cmd/terraform-backend +ARG TARGETPLATFORM +ENV TARGETS=$TARGETPLATFORM +ENV PACK=cmd/terraform-backend +ENV OUT=terraform-backend +ENV GO111MODULE=on +RUN xgo-build . # start clean for final image FROM debian:12 +ENV DEBIAN_FRONTEND=noninteractive RUN apt-get -q update && \ apt-get -yq install ca-certificates && \ apt-get autoclean -COPY --from=builder /go/src/github.com/nimbolus/terraform-backend/terraform-backend /terraform-backend +ARG TARGETPLATFORM +COPY --from=builder /build/terraform-backend-${TARGETPLATFORM/\//-} /terraform-backend ENTRYPOINT ["/terraform-backend"] diff --git a/README.md b/README.md index 434d303..fb6acba 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,24 @@ A state backend server which implements the Terraform HTTP backend API with plug > :warning: **Disclaimer**: This code is in an early development state and not tested extensively for bugs and security issues. If you find some, please raise an issue or merge request. Supported authentication methods: + - HTTP basic auth - JSON Web Tokens Supported storage backends: + - local file system - S3 - Postgres Supported lock backends: + - local map - Redis - Postgres Supported KMS (encryption) backends: + - local AES key - AES from HashiCorp Vault Key/Value store (v2) - HashiCorp Vault Transit engine @@ -26,11 +30,13 @@ Supported KMS (encryption) backends: ## Deployment Run locally for development: + ```sh LOG_LEVEL=debug go run ./cmd/terraform-backend ``` or use [docker-compose](./docker-compose.yml): + ```sh docker-compose up -d ``` @@ -40,7 +46,7 @@ docker-compose up -d The following table describes the default configuration, although the backend server will run with these values, it's not scalable and therefore only for testing purposes. | Environment Variable | Type | Default | Description | -|----------------------|--------|------------|---------------------------------------------------------------------------------------------------| +| -------------------- | ------ | ---------- | ------------------------------------------------------------------------------------------------- | | LOG_LEVEL | string | `info` | Log level (options are: `fatal`, `info`, `warning`, `debug`, `trace`) | | LISTEN_ADDR | string | `:8080` | Address the HTTP server listens on | | TLS_KEY | string | -- | Path to TLS key file for listening with TLS (fallback to HTTP if not specified) | @@ -57,6 +63,7 @@ The following table describes the default configuration, although the backend se The path to the state is: `/state//`. **Example Terraform backend configuration** + ```hcl terraform { backend "http" { @@ -74,12 +81,41 @@ For more information about username and password checkout [docs/auth.md](./docs/ ## Tests Run unit tests: + ```sh go test ./... ``` Run integration tests: + ```sh docker-compose up -d redis postgres minio go test ./... --tags integration -count=1 ``` + +## Speculative Runs in GitHub Actions + +This project includes a CLI to trigger speculative runs via GitHub Actions, similar to how Terraform Cloud works. + +### Install + +To install the binary on your system, download the binary from the latest release and make it executable: + +```sh +curl -L "https://github.com/ffddorf/terraform-backend/releases/latest/download/tf-preview-gh_$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m)" > tf-preview-gh +sudo mv tf-preview-gh /usr/local/bin/tf-preview-gh +sudo chmod +x /usr/local/bin/tf-preview-gh +``` + +### Usage + +Run the CLI in the directory for which you want to run a remote plan. + +The tool will pick its context from the environment: + +- Address of the Terraform Backend from your backend config +- Repository to use from the git remote called `origin` + +``` +tf-preview-gh +``` diff --git a/go.mod b/go.mod index 1560039..638773b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/nimbolus/terraform-backend -go 1.22 +// warning: upgrading this might break the release flow (xgo) +go 1.21 require ( github.com/cenkalti/backoff v2.2.1+incompatible