name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  CONTROLLER_IMAGE: docker.io/bitnami/sealed-secrets-controller:latest

jobs:
  linter:
    name: Run linters
    runs-on: ubuntu-latest
    strategy:
      matrix:
        go: ["1.17.11", "1.18.3"]
        os: [ubuntu-latest]
        golangci-lint: ["1.44.2"]
    steps:
    - name: Set up Go 1.x
      uses: actions/setup-go@v2
      with:
        go-version: ${{ matrix.go }}
      id: go

    - name: Check out code into the Go module directory
      uses: actions/checkout@v2

    - name: Install dependencies
      run: |
        go install github.com/golangci/golangci-lint/cmd/golangci-lint@v${{ matrix.golangci-lint }}

    - name: Run linter
      run: make lint

  gosec:
    name: Run gosec
    runs-on: ubuntu-latest
    strategy:
      matrix:
        go: ["1.17.11", "1.18.3"]
        os: [ubuntu-latest]
        gosec: ["2.11.0"]
    steps:
    - name: Set up Go 1.x
      uses: actions/setup-go@v2
      with:
        go-version: ${{ matrix.go }}
      id: go

    - name: Check out code into the Go module directory
      uses: actions/checkout@v2

    - name: Install dependencies
      run: |
        go install github.com/securego/gosec/v2/cmd/gosec@v${{ matrix.gosec }}

    - name: Run gosec
      run: make lint-gosec

  test:
    name: Build
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        go: ["1.17.11", "1.18.3"]
        os: [macos-latest, windows-latest, ubuntu-latest]
    steps:

    - name: Set up Go 1.x
      uses: actions/setup-go@v2
      with:
        go-version: ${{ matrix.go }}
      id: go

    - name: Check out code into the Go module directory
      uses: actions/checkout@v2

    - name: Test
      run: make test

  container:
    name: Build Container
    runs-on: ubuntu-latest
    steps:

    - name: Check out code
      uses: actions/checkout@v2

    - name: Install Cosign
      uses: sigstore/cosign-installer@v2.3.0

    - name: Distroless verify
      run: |
        cosign verify --key /dev/stdin "$(grep FROM Dockerfile | awk '{print $2}')" <<EOF
        -----BEGIN PUBLIC KEY-----
        MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWZzVzkb8A+DbgDpaJId/bOmV8n7Q
        OqxYbK0Iro6GzSmOzxkn+N2AKawLyXi84WSwJQBK//psATakCgAQKkNTAA==
        -----END PUBLIC KEY-----
        EOF

    - name: Setup kubecfg
      run: |
        mkdir -p ~/bin
        curl -sLf https://github.com/kubecfg/kubecfg/releases/download/v0.25.0/kubecfg_Linux_X64 >~/bin/kubecfg
        chmod +x ~/bin/kubecfg

    - name: Set up Go 1.x
      uses: actions/setup-go@v2
      with:
        go-version: 1.18.3
      id: go

    - name: Docker build
      run: |
        export PATH=~/bin:$PATH
        make CONTROLLER_IMAGE=$CONTROLLER_IMAGE IMAGE_PULL_POLICY=Never controller.yaml
        make CONTROLLER_IMAGE=$CONTROLLER_IMAGE controller.image.linux-amd64
        docker tag $CONTROLLER_IMAGE-linux-amd64 $CONTROLLER_IMAGE
        docker save $CONTROLLER_IMAGE -o /tmp/controller-image.tar

    - name: Upload manifest artifact
      uses: actions/upload-artifact@v2
      with:
        name: controller-manifest
        path: controller.yaml

    - name: Upload container image artifact
      uses: actions/upload-artifact@v2
      with:
        name: controller-image
        path: /tmp/controller-image.tar

  integration:
    name: Integration
    runs-on: ubuntu-latest
    needs: container
    strategy:
      matrix:
        k8s: ["1.16.13", "1.17.11", "1.20.4", "1.22.5"]
    env:
      MINIKUBE_WANTUPDATENOTIFICATION: "false"
      MINIKUBE_WANTREPORTERRORPROMPT: "false"
      CHANGE_MINIKUBE_NONE_USER: "true"

    steps:

    - name: Set up Go 1.x
      uses: actions/setup-go@v2
      with:
        go-version: 1.18.3
      id: go

    - name: Set up Ginkgo
      run: |
        (cd /tmp; GO111MODULE=on go install github.com/onsi/ginkgo/ginkgo@v1.14.2)

    - name: Check out code into the Go module directory
      uses: actions/checkout@v2

    - uses: opsgang/ga-setup-minikube@v0.1.1
      env:
        ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
      with:
        minikube-version: 1.24.0
        k8s-version: ${{ matrix.k8s }}

    # need to delete old state of the cluster, see:
    # https://github.com/kubernetes/minikube/issues/8765
    - name: K8s setup
      run: |
        minikube delete
        minikube config set kubernetes-version v${{ matrix.k8s }}
        minikube start --vm-driver=docker
        minikube update-context
        kubectl cluster-info

    - name: Download manifest artifact
      uses: actions/download-artifact@v2
      with:
        name: controller-manifest

    - name: Download container image artifact
      uses: actions/download-artifact@v2
      with:
        name: controller-image

    - name: Load docker image
      run: |
        eval $(minikube docker-env)
        docker load -i controller-image.tar
        docker inspect $CONTROLLER_IMAGE

    - name: Testing environment setup
      run: |
        kubectl apply -f controller.yaml
        kubectl rollout status deployment/sealed-secrets-controller -n kube-system -w --timeout=1m || kubectl -n kube-system describe pod -lname=sealed-secrets-controller

    - name: Integration tests
      run: make integrationtest CONTROLLER_IMAGE=$CONTROLLER_IMAGE GINKGO="ginkgo -v --randomizeSuites --failOnPending --trace --progress --compilers=2 --nodes=4"
