From 6ba57aaa155e9d74fd23c76fdc0c646e0460f245 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Thu, 7 Sep 2023 17:45:03 +0200 Subject: [PATCH] ci: add basic build Signed-off-by: Mark Sagi-Kazar --- .github/.editorconfig | 2 + .github/dependabot.yaml | 17 ++ .github/renovate.json | 16 ++ .github/workflows/analysis-scorecard.yaml | 47 +++++ .github/workflows/artifacts.yaml | 195 ++++++++++++++++++++ .github/workflows/ci.yaml | 205 ++++++++++++++++++++++ .github/workflows/release.yaml | 23 +++ .golangci.yaml | 27 +++ .goreleaser.yaml | 27 +++ .yamllint.yaml | 2 +- Dockerfile | 36 ++++ flake.nix | 1 + 12 files changed, 597 insertions(+), 1 deletion(-) create mode 100644 .github/.editorconfig create mode 100644 .github/dependabot.yaml create mode 100644 .github/renovate.json create mode 100644 .github/workflows/analysis-scorecard.yaml create mode 100644 .github/workflows/artifacts.yaml create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/release.yaml create mode 100644 .golangci.yaml create mode 100644 .goreleaser.yaml create mode 100644 Dockerfile diff --git a/.github/.editorconfig b/.github/.editorconfig new file mode 100644 index 0000000..0902c6a --- /dev/null +++ b/.github/.editorconfig @@ -0,0 +1,2 @@ +[{*.yml,*.yaml}] +indent_size = 2 diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..e63ea97 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,17 @@ +version: 2 + +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..6edfd4f --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "schedule:earlyMondays", + ":disableDependencyDashboard" + ], + "enabledManagers": [ + "nix" + ], + "nix": { + "enabled": true + }, + "lockFileMaintenance": { + "enabled": true + } +} diff --git a/.github/workflows/analysis-scorecard.yaml b/.github/workflows/analysis-scorecard.yaml new file mode 100644 index 0000000..56f6753 --- /dev/null +++ b/.github/workflows/analysis-scorecard.yaml @@ -0,0 +1,47 @@ +name: OpenSSF Scorecard + +on: + branch_protection_rule: + push: + branches: [main] + schedule: + - cron: '30 0 * * 5' + +permissions: + contents: read + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + permissions: + actions: read + contents: read + id-token: write + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: Upload results as artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: OpenSSF Scorecard results + path: results.sarif + retention-days: 5 + + - name: Upload results to GitHub Security tab + uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.3.4 + with: + sarif_file: results.sarif diff --git a/.github/workflows/artifacts.yaml b/.github/workflows/artifacts.yaml new file mode 100644 index 0000000..d541e42 --- /dev/null +++ b/.github/workflows/artifacts.yaml @@ -0,0 +1,195 @@ +name: Artifacts + +on: + workflow_call: + inputs: + publish: + description: Publish artifacts to the artifact store + default: false + required: false + type: boolean + release: + description: Whether this is a release build + default: false + required: false + type: boolean + outputs: + container-image-name: + description: Container image name + value: ${{ jobs.container-image.outputs.name }} + container-image-digest: + description: Container image digest + value: ${{ jobs.container-image.outputs.digest }} + container-image-tag: + description: Container image tag + value: ${{ jobs.container-image.outputs.tag }} + container-image-ref: + description: Container image ref + value: ${{ jobs.container-image.outputs.ref }} + +permissions: + contents: read + +jobs: + container-image: + name: Container image + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + id-token: write + security-events: write + + outputs: + name: ${{ steps.image-name.outputs.value }} + digest: ${{ steps.build.outputs.digest }} + tag: ${{ steps.meta.outputs.version }} + ref: ${{ steps.image-ref.outputs.value }} + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Set up QEMU + uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 + + - name: Set image name + id: image-name + run: echo "value=ghcr.io/${{ github.repository }}" >> "$GITHUB_OUTPUT" + + - name: Gather build metadata + id: meta + uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4.6.0 + with: + images: ${{ steps.image-name.outputs.value }} + flavor: | + latest = false + tags: | + type=ref,event=branch + type=ref,event=pr,prefix=pr- + type=semver,pattern={{raw}} + type=raw,value=latest,enable={{is_default_branch}} + + # Multiple exporters are not supported yet + # See https://github.com/moby/buildkit/pull/2760 + - name: Determine build output + uses: haya14busa/action-cond@1d6e8a12b20cdb4f1954feef9aa475b9c390cab5 # v1.1.1 + id: build-output + with: + cond: ${{ inputs.publish }} + if_true: type=image,push=true + if_false: type=oci,dest=image.tar + + - name: Login to GitHub Container Registry + uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + if: inputs.publish + + - name: Build and push image + id: build + uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1 + with: + context: . + platforms: linux/amd64,linux/arm64,linux/arm/v7 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + outputs: ${{ steps.build-output.outputs.value }} + # push: ${{ inputs.publish }} + + - name: Set image ref + id: image-ref + run: echo "value=${{ steps.image-name.outputs.value }}@${{ steps.build.outputs.digest }}" >> "$GITHUB_OUTPUT" + + - name: Fetch image + run: skopeo --insecure-policy copy docker://${{ steps.image-name.outputs.value }}:${{ steps.meta.outputs.version }} oci-archive:image.tar + if: inputs.publish + + - name: Upload image as artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "[${{ github.job }}] OCI tarball" + path: image.tar + + - name: Extract OCI tarball + run: | + mkdir -p image + tar -xf image.tar -C image + + # See https://github.com/anchore/syft/issues/1545 + - name: Extract image from multi-arch image + run: skopeo --override-os linux --override-arch amd64 --insecure-policy copy --additional-tag ${{ steps.image-name.outputs.value }}:${{ steps.meta.outputs.version }} oci:image docker-archive:docker.tar + + - name: Upload image as artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "[${{ github.job }}] Docker tarball" + path: docker.tar + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@fbd16365eb88e12433951383f5e99bd901fc618f # 0.12.0 + with: + input: image + format: sarif + output: trivy-results.sarif + + - name: Upload Trivy scan results as artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "[${{ github.job }}] Trivy scan results" + path: trivy-results.sarif + retention-days: 5 + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + with: + sarif_file: trivy-results.sarif + + binary: + name: Binary + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Set up Nix + uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + + - name: Prepare Nix shell + run: nix develop --impure .#ci + + - name: Determine build command + uses: haya14busa/action-cond@1d6e8a12b20cdb4f1954feef9aa475b9c390cab5 # v1.1.1 + id: build-command + with: + cond: ${{ inputs.release }} + if_true: goreleaser release + if_false: goreleaser release --skip-publish --snapshot + + - name: Build + run: nix develop --impure .#ci -c ${{ steps.build-command.outputs.value }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload artifacts + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "${{ github.job }}" + path: | + build/dist/*.tar.gz + build/dist/checksums.txt diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..2cb8d5e --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,205 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + build: + name: Build + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Set up Nix + uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + + - name: Set up magic Nix cache + uses: DeterminateSystems/magic-nix-cache-action@8a218f9e264e9c3803c9a1ee1c30d8e4ab55be63 # v2 + + - name: Set up Go cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ github.job }}-${{ runner.os }}-go- + + - name: Prepare Nix shell + run: nix develop --impure .#ci + + - name: Build + run: nix develop --impure .#ci -c make build + + test: + name: Test + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Set up Nix + uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + + - name: Set up magic Nix cache + uses: DeterminateSystems/magic-nix-cache-action@8a218f9e264e9c3803c9a1ee1c30d8e4ab55be63 # v2 + + - name: Set up Go cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ github.job }}-${{ runner.os }}-go- + + - name: Prepare Nix shell + run: nix develop --impure .#ci + + - name: Test + run: nix develop --impure .#ci -c make test + + lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Set up Nix + uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + + - name: Set up magic Nix cache + uses: DeterminateSystems/magic-nix-cache-action@8a218f9e264e9c3803c9a1ee1c30d8e4ab55be63 # v2 + + - name: Set up Go cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ github.job }}-${{ runner.os }}-go- + + - name: Prepare Nix shell + run: nix develop --impure .#ci + + - name: Lint + run: nix develop --impure .#ci -c make lint + + license-check: + name: License check + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Set up Nix + uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + + - name: Set up magic Nix cache + uses: DeterminateSystems/magic-nix-cache-action@8a218f9e264e9c3803c9a1ee1c30d8e4ab55be63 # v2 + + - name: Set up Go cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ github.job }}-${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ github.job }}-${{ runner.os }}-go- + + - name: Cache license information + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + path: .licensei.cache + key: licensei-v1-${{ github.ref_name }}-${{ hashFiles('go.sum') }} + restore-keys: | + licensei-v1-${{ github.ref_name }} + licensei-v1-main + licensei-v1 + + - name: Prepare Nix shell + run: nix develop --impure .#ci + + - name: Populate license cache + run: nix develop --impure .#ci -c licensei cache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check licenses + run: nix develop --impure .#ci -c make license-check + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + dev: + name: Developer environment + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Set up Nix + uses: cachix/install-nix-action@6a9a9e84a173d90b3ffb42c5ddaf9ea033fad011 # v23 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + + - name: Set up magic Nix cache + uses: DeterminateSystems/magic-nix-cache-action@8a218f9e264e9c3803c9a1ee1c30d8e4ab55be63 # v2 + + - name: Check + run: nix flake check --impure + + - name: Dev shell + run: nix develop --impure + + artifacts: + name: Artifacts + uses: ./.github/workflows/artifacts.yaml + with: + publish: ${{ github.event_name == 'push' }} + permissions: + contents: write + packages: write + id-token: write + security-events: write + + dependency-review: + name: Dependency review + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + + steps: + - name: Checkout repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Dependency Review + uses: actions/dependency-review-action@f6fff72a3217f580d5afd49a46826795305b63c7 # v3.0.8 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..791eeca --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,23 @@ +name: Release + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+" + +permissions: + contents: read + +jobs: + artifacts: + name: Artifacts + uses: ./.github/workflows/artifacts.yaml + with: + publish: true + release: true + permissions: + contents: write + packages: write + id-token: write + security-events: write diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..539dc61 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,27 @@ +run: + timeout: 10m + +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/bank-vaults/secret-sync) + goimports: + local-prefixes: github.com/bank-vaults/secret-sync + misspell: + locale: US + nolintlint: + allow-leading-space: false # require machine-readable nolint directives (with no leading space) + allow-unused: false # report any unused nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + revive: + confidence: 0 + +linters: + enable: + - gci + - goimports + - misspell + - nolintlint + - revive diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..554dfb9 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,27 @@ +dist: build/dist + +builds: + - main: . + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: "-s -w -X main.version={{ .Version }}" + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + +archives: + - name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" + format_overrides: + - goos: windows + format: zip + +checksum: + name_template: "checksums.txt" + +changelog: + skip: false diff --git a/.yamllint.yaml b/.yamllint.yaml index bac19ce..9278ed2 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -1,4 +1,4 @@ -ignore-from-file: [.gitignore, .yamlignore] +ignore-from-file: [.gitignore] extends: default diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a1e15db --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.2.1@sha256:8879a398dedf0aadaacfbd332b29ff2f84bc39ae6d4e9c0a1109db27ac5ba012 AS xx + +FROM --platform=$BUILDPLATFORM golang:1.21.0-alpine3.18@sha256:445f34008a77b0b98bf1821bf7ef5e37bb63cc42d22ee7c21cc17041070d134f AS builder + +COPY --from=xx / / + +RUN apk add --update --no-cache ca-certificates make git curl clang lld + +ARG TARGETPLATFORM + +RUN xx-apk --update --no-cache add musl-dev gcc + +RUN xx-go --wrap + +WORKDIR /usr/local/src/secret-sync + +ARG GOPROXY + +ENV CGO_ENABLED=0 + +COPY go.* ./ +RUN go mod download + +COPY . . + +RUN go build -o /usr/local/bin/secret-sync . +RUN xx-verify /usr/local/bin/secret-sync + + +FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a + +RUN apk add --update --no-cache ca-certificates tzdata + +COPY --from=builder /usr/local/bin/secret-sync /usr/local/bin/secret-sync + +USER 65534 diff --git a/flake.nix b/flake.nix index b3ebd3b..1e091eb 100644 --- a/flake.nix +++ b/flake.nix @@ -38,6 +38,7 @@ gnumake # golangci-lint + goreleaser yamllint # hadolint