From 7a5992fe181b3a535cd2e001b4e759229045d2cb Mon Sep 17 00:00:00 2001
From: Alex Goodman <wagoodman@gmail.com>
Date: Sat, 9 Nov 2019 12:27:52 -0500
Subject: [PATCH 1/2] enhance gha pipeline for release

---
 .github/workflows/pipeline.yml | 130 +++++++++++++++++++++++++++++++++
 .github/workflows/push.yml     |  38 ----------
 .goreleaser.docker.yml         |  25 -------
 .goreleaser.yml                |  27 +++++--
 Dockerfile                     |   2 +-
 Makefile                       |  72 +++++++++---------
 docker.sh                      |  25 -------
 7 files changed, 186 insertions(+), 133 deletions(-)
 create mode 100644 .github/workflows/pipeline.yml
 delete mode 100644 .github/workflows/push.yml
 delete mode 100644 .goreleaser.docker.yml
 delete mode 100755 docker.sh

diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml
new file mode 100644
index 0000000..5899279
--- /dev/null
+++ b/.github/workflows/pipeline.yml
@@ -0,0 +1,130 @@
+name: 'app-pipeline'
+on: [ push, pull_request ]
+env:
+  DOCKER_CLI_VERSION: "19.03.1"
+jobs:
+  unit-test:
+    strategy:
+      matrix:
+        go-version: [1.12.x, 1.13.x]
+        # todo: support windows
+        platform: [ubuntu-latest, macos-latest]
+        # platform: [ubuntu-latest, macos-latest, windows-latest]
+    runs-on: ${{ matrix.platform }}
+    steps:
+
+      - uses: actions/setup-go@v1
+        with:
+          go-version: ${{ matrix.go-version }}
+
+      - uses: actions/checkout@v1
+
+      - name: Cache go dependencies
+        id: unit-cache-go-dependencies
+        uses: actions/cache@v1
+        with:
+          path: ~/go/pkg/mod
+          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+          restore-keys: |
+            ${{ runner.os }}-go-
+
+      - name: Install go dependencies
+        if: steps.unit-cache-go-dependencies.outputs.cache-hit != 'true'
+        run: go get ./...
+
+      - name: Test
+        run: make ci-test
+
+  build-artifacts:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/setup-go@v1
+        with:
+          go-version: '1.13.x'
+
+      - uses: actions/checkout@v1
+
+      - name: Install go tools
+        run: make ci-install-go-tools
+
+      - name: Cache go dependencies
+        id: package-cache-go-dependencies
+        uses: actions/cache@v1
+        with:
+          path: ~/go/pkg/mod
+          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+          restore-keys: |
+            ${{ runner.os }}-go-
+
+      - name: Install dependencies
+        if: steps.package-cache-go-dependencies.outputs.cache-hit != 'true'
+        run: go get ./...
+
+      # todo: test gofmt
+
+      - name: Lint
+        run: golangci-lint run -v
+
+      - name: Build snapshot artifacts
+        uses: goreleaser/goreleaser-action@v1
+        with:
+          version: latest
+          args: release --snapshot --skip-publish --rm-dist
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+      - run: docker images wagoodman/dive
+
+      # todo: compare against known json output in shared volume
+      - name: Test production image
+        run: make ci-test-production-image
+
+      - uses: actions/upload-artifact@master
+        with:
+          name: artifacts
+          path: dist
+
+  release:
+    needs: [ build-artifacts, unit-test  ]
+    runs-on: ubuntu-latest
+    if: startsWith(github.ref, 'refs/tags/v')
+    steps:
+
+      - uses: actions/setup-go@v1
+        with:
+          go-version: '1.13.x'
+
+      - uses: actions/checkout@v1
+
+      - name: Cache go dependencies
+        id: release-cache-go-dependencies
+        uses: actions/cache@v1
+        with:
+          path: ~/go/pkg/mod
+          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+          restore-keys: |
+            ${{ runner.os }}-go-
+
+      - name: Install dependencies
+        if: steps.release-cache-go-dependencies.outputs.cache-hit != 'true'
+        run: go get ./...
+
+      - name: Docker login
+        run: make ci-docker-login
+        env:
+          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
+          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
+
+      - name: Publish GitHub release
+        uses: goreleaser/goreleaser-action@v1
+        with:
+          version: latest
+          args: release --rm-dist
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Docker logout
+        run: make ci-docker-logout
+
+      - name: Smoke test published image
+        run: make ci-test-production-image
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
deleted file mode 100644
index 0e771d2..0000000
--- a/.github/workflows/push.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: 'snapshot'
-on: [ push, pull_request ]
-jobs:
-  pkg:
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/setup-go@v1
-      with:
-        go-version: '1.13.x'
-    - uses: actions/checkout@v1
-    - name: install deps
-      run: |
-        curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sudo sh -s -- -b /usr/local/bin/ latest
-        curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sudo sh -s -- -b /usr/local/bin/ latest
-        sudo apt-get update
-        sudo apt-get install -y libdevmapper-dev libgpgme11-dev
-    - run: go get ./...
-    - run: golangci-lint run -v
-    - run: goreleaser --snapshot --skip-publish --rm-dist
-    - uses: actions/upload-artifact@master
-      with:
-        name: ubuntu
-        path: dist
-
-  docker:
-    needs: [ pkg ]
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/setup-go@v1
-      with:
-        go-version: '1.13.x'
-    - uses: actions/checkout@v1
-    - run: ./docker.sh
-    - run: docker images
-    - uses: actions/upload-artifact@master
-      with:
-        name: alpine
-        path: dist
diff --git a/.goreleaser.docker.yml b/.goreleaser.docker.yml
deleted file mode 100644
index 85f2153..0000000
--- a/.goreleaser.docker.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-release:
-  prerelease: true
-
-builds:
-  - binary: dive
-    goos:
-      - linux
-    goarch:
-      - amd64
-    ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.buildTime={{.Date}}`.
-
-dockers:
-  -
-    binaries:
-      - dive
-    dockerfile: Dockerfile
-    image_templates:
-      - "wagoodman/dive:{{ .Tag }}"
-      - "wagoodman/dive:v{{ .Major }}"
-      - "wagoodman/dive:v{{ .Major }}.{{ .Minor }}"
-      - "wagoodman/dive:latest"
-      - "quay.io/wagoodman/dive:{{ .Tag }}"
-      - "quay.io/wagoodman/dive:v{{ .Major }}"
-      - "quay.io/wagoodman/dive:v{{ .Major }}.{{ .Minor }}"
-      - "quay.io/wagoodman/dive:latest"
diff --git a/.goreleaser.yml b/.goreleaser.yml
index dd55109..e00b40d 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -13,6 +13,13 @@ builds:
       - amd64
     ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.buildTime={{.Date}}`.
 
+brews:
+  - github:
+      owner: wagoodman
+      name: homebrew-dive
+    homepage: "https://github.com/wagoodman/dive/"
+    description: "A tool for exploring each layer in a docker image"
+
 archives:
   - format: tar.gz
     format_overrides:
@@ -24,12 +31,18 @@ nfpms:
     maintainer: Alex Goodman
     homepage: https://github.com/wagoodman/dive/
     formats:
-      - deb
       - rpm
+      - deb
 
-brews:
-  - github:
-      owner: wagoodman
-      name: homebrew-dive
-    homepage: "https://github.com/wagoodman/dive/"
-    description: "A tool for exploring each layer in a docker image"
+dockers:
+  -
+    binaries:
+      - dive
+    dockerfile: Dockerfile
+    image_templates:
+      - "wagoodman/dive:latest"
+      - "wagoodman/dive:{{ .Tag }}"
+      - "wagoodman/dive:v{{ .Major }}"
+      - "wagoodman/dive:v{{ .Major }}.{{ .Minor }}"
+    build_flag_templates:
+      - "--build-arg=DOCKER_CLI_VERSION={{.Env.DOCKER_CLI_VERSION}}"
diff --git a/Dockerfile b/Dockerfile
index b2a865c..f913cda 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
 FROM alpine:3.10
 
-ARG DOCKER_CLI_VERSION=19.03.1
+ARG DOCKER_CLI_VERSION=${DOCKER_CLI_VERSION}
 RUN wget -O- https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_CLI_VERSION}.tgz | \
     tar -xzf - docker/docker --strip-component=1 && \
     mv docker /usr/local/bin
diff --git a/Makefile b/Makefile
index 34e6276..bdc5551 100644
--- a/Makefile
+++ b/Makefile
@@ -2,9 +2,40 @@ BIN = dive
 BUILD_DIR = ./dist/dive_linux_amd64
 BUILD_PATH = $(BUILD_DIR)/$(BIN)
 PWD := ${CURDIR}
+PRODUCTION_REGISTRY = docker.io
+TEST_IMAGE = busybox:latest
 
 all: clean build
 
+## For CI
+
+ci-test:
+	go test -cover -v -race ./...
+
+ci-install-go-tools:
+	curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sudo sh -s -- -b /usr/local/bin/ latest
+
+ci-docker-login:
+	echo '${DOCKER_PASSWORD}' | docker login -u '${DOCKER_USERNAME}' --password-stdin '${PRODUCTION_REGISTRY}'
+
+ci-docker-logout:
+	docker logout '${PRODUCTION_REGISTRY}'
+
+ci-publish-release:
+	goreleaser --rm-dist
+
+# todo: add --pull=never when supported by host box
+ci-test-production-image:
+	docker run \
+		--rm \
+		-t \
+		-v //var/run/docker.sock://var/run/docker.sock \
+		'${PRODUCTION_REGISTRY}/wagoodman/dive:latest' \
+			'${TEST_IMAGE}' \
+			--ci
+
+## For development
+
 run: build
 	$(BUILD_PATH) build -t dive-example:latest -f .data/Dockerfile.example .
 
@@ -12,15 +43,11 @@ run-large: build
 	$(BUILD_PATH) amir20/clashleaders:latest
 
 run-podman: build
-	$(BUILD_PATH)  localhost/dive-example:latest  --source podman
-
-run-podman-build: build
 	podman build -t dive-example:latest -f .data/Dockerfile.example .
-	$(BUILD_PATH) localhost/dive-example:latest --source podman
-
+	$(BUILD_PATH) localhost/dive-example:latest --engine podman
 
 run-podman-large: build
-	$(BUILD_PATH) docker.io/amir20/clashleaders:latest --source podman
+	$(BUILD_PATH) docker.io/amir20/clashleaders:latest --engine podman
 
 run-ci: build
 	CI=true $(BUILD_PATH) dive-example:latest --ci-config .data/.dive-ci
@@ -28,37 +55,8 @@ run-ci: build
 build:
 	go build -o $(BUILD_PATH)
 
-release: test-coverage validate
-	./.scripts/tag.sh
-	goreleaser --rm-dist
-
-install:
-	go install ./...
-
-ci: clean validate test-coverage
-
-test: build
-	go test -cover -v -race ./...
-
-test-coverage: build
-	./.scripts/test-coverage.sh
-
-validate:
-	grep -R 'const allowTestDataCapture = false' runtime/ui/viewmodel
-	go vet ./...
-	@! gofmt -s -l . 2>&1 | grep -vE '^\.git/' | grep -vE '^\.cache/'
-	golangci-lint run
-
-lint: build
-	golint -set_exit_status $$(go list ./...)
-
 generate-test-data:
-	docker build -t dive-test:latest -f .data/Dockerfile.test-image . && docker image save -o .data/test-docker-image.tar dive-test:latest && echo "Exported test data!"
-
-setup-ci:
-	sudo apt update && sudo apt install -y libgpgme-dev libbtrfs-dev libdevmapper-dev
-	go get ./...
-	curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b /go/bin v1.18.0
+	docker build -t dive-test:latest -f .data/Dockerfile.test-image . && docker image save -o .data/test-docker-image.tar dive-test:latest && echo 'Exported test data!'
 
 dev:
 	docker run -ti --rm -v $(PWD):/app -w /app -v dive-pkg:/go/pkg/ golang:1.13 bash
@@ -67,4 +65,4 @@ clean:
 	rm -rf dist
 	go clean
 
-.PHONY: build install test lint clean release validate generate-test-data test-coverage ci dev
+
diff --git a/docker.sh b/docker.sh
deleted file mode 100755
index 3be04b4..0000000
--- a/docker.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env sh
-
-set -e
-
-cd "$(dirname $0)"
-
-docker build -t wagoodman/dive:dev - <<EOF
-FROM golang:alpine AS build
-RUN apk add -U --no-cache gpgme-dev gcc musl-dev btrfs-progs-dev lvm2-dev curl git \
- && curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sh \
- && curl -L https://download.docker.com/linux/static/stable/x86_64/docker-19.03.1.tgz | tar -xzf - docker/docker --strip-component=1 -C /usr/local/bin
-EOF
-
-docker run --rm \
-  -v //var/run/docker.sock://var/run/docker.sock \
-  -v /$(pwd)://src \
-  -w //src \
-  wagoodman/dive:dev \
-  goreleaser \
-    -f .goreleaser.docker.yml \
-    --snapshot \
-    --skip-publish \
-    --rm-dist
-
-sudo chown -R $USER:$USER dist

From 873f5783e7cd22f15c4aea34eda60eecde0bd0e4 Mon Sep 17 00:00:00 2001
From: Alex Goodman <wagoodman@gmail.com>
Date: Sat, 9 Nov 2019 14:49:42 -0500
Subject: [PATCH 2/2] fix/improve circle tests

---
 .circleci/config.yml           | 65 ++++++++++++++--------------------
 .github/workflows/pipeline.yml | 10 +++---
 .goreleaser.yml                |  1 +
 Makefile                       |  9 ++++-
 4 files changed, 41 insertions(+), 44 deletions(-)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index 74ad8fd..120a605 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,70 +1,59 @@
-version: 2
+version: 2.1
 
 jobs:
-  golang-1.11:
+  run-static-analyses:
+    parameters:
+      version:
+        type: string
     working_directory: /home/circleci/app
     docker:
-      - image: circleci/golang:1.11
+      - image: circleci/golang:<< parameters.version >>
         environment:
           GO111MODULE: "on"
     steps:
       - checkout
       - restore_cache:
           keys:
-            - golang-1.11-{{ checksum "go.sum" }}
-      - run: make setup-ci
+            - golang-<< parameters.version >>-{{ checksum "go.sum" }}
+      - run: make ci-install-go-tools
       - save_cache:
-          key: golang-1.11-{{ checksum "go.sum" }}
+          key: golang-<< parameters.version >>-{{ checksum "go.sum" }}
           paths:
             - "/go/pkg/mod"
       - run:
-          name: run static analysis & tests
-          command: make ci
+          name: run static analysis
+          command: make ci-static-analyses
 
-  golang-1.12:
+  run-tests:
+    parameters:
+      version:
+        type: string
     working_directory: /home/circleci/app
     docker:
-      - image: circleci/golang:1.12
+      - image: circleci/golang:<< parameters.version >>
         environment:
           GO111MODULE: "on"
     steps:
       - checkout
       - restore_cache:
           keys:
-            - golang-1.12-{{ checksum "go.sum" }}
-      - run: make setup-ci
+            - golang-<< parameters.version >>-{{ checksum "go.sum" }}
+      - run: make ci-install-go-tools
       - save_cache:
-          key: golang-1.12-{{ checksum "go.sum" }}
+          key: golang-<< parameters.version >>-{{ checksum "go.sum" }}
           paths:
             - "/go/pkg/mod"
       - run:
-          name: run static analysis & tests
-          command: make ci
+          name: run unit tests
+          command: make ci-unit-test
 
-  golang-1.13:
-    working_directory: /home/circleci/app
-    docker:
-      - image: circleci/golang:1.13
-        environment:
-          GO111MODULE: "on"
-    steps:
-      - checkout
-      - restore_cache:
-          keys:
-            - golang-1.13-{{ checksum "go.sum" }}
-      - run: make setup-ci
-      - save_cache:
-          key: golang-1.13-{{ checksum "go.sum" }}
-          paths:
-            - "/go/pkg/mod"
-      - run:
-          name: run static analysis & tests
-          command: make ci
 
 workflows:
-  version: 2
   commit:
     jobs:
-      - golang-1.11
-      - golang-1.12
-      - golang-1.13
+      - run-static-analyses:
+          version: "1.13"
+      - run-tests:
+          version: "1.12"
+      - run-tests:
+          version: "1.13"
diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml
index 5899279..373b303 100644
--- a/.github/workflows/pipeline.yml
+++ b/.github/workflows/pipeline.yml
@@ -3,6 +3,8 @@ on: [ push, pull_request ]
 env:
   DOCKER_CLI_VERSION: "19.03.1"
 jobs:
+  # This will run on merge to master, and for PRs with folks that also are part of the GHA beta.
+  # Circle ci will also run for redundancy until GHA is out of beta, since circle checks will always run.
   unit-test:
     strategy:
       matrix:
@@ -33,7 +35,7 @@ jobs:
         run: go get ./...
 
       - name: Test
-        run: make ci-test
+        run: make ci-unit-test
 
   build-artifacts:
     runs-on: ubuntu-latest
@@ -60,10 +62,8 @@ jobs:
         if: steps.package-cache-go-dependencies.outputs.cache-hit != 'true'
         run: go get ./...
 
-      # todo: test gofmt
-
-      - name: Lint
-        run: golangci-lint run -v
+      - name: Linting, formatting, and other static code analyses
+        run: make ci-static-analyses
 
       - name: Build snapshot artifacts
         uses: goreleaser/goreleaser-action@v1
diff --git a/.goreleaser.yml b/.goreleaser.yml
index e00b40d..92440a2 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -39,6 +39,7 @@ dockers:
     binaries:
       - dive
     dockerfile: Dockerfile
+    # todo: on 1.0 remove 'v' prefix
     image_templates:
       - "wagoodman/dive:latest"
       - "wagoodman/dive:{{ .Tag }}"
diff --git a/Makefile b/Makefile
index bdc5551..0ace2e1 100644
--- a/Makefile
+++ b/Makefile
@@ -9,9 +9,15 @@ all: clean build
 
 ## For CI
 
-ci-test:
+ci-unit-test:
 	go test -cover -v -race ./...
 
+ci-static-analyses:
+	grep -R 'const allowTestDataCapture = false' runtime/ui/viewmodel
+	go vet ./...
+	@! gofmt -s -l . 2>&1 | grep -vE '^\.git/' | grep -vE '^\.cache/'
+	golangci-lint run
+
 ci-install-go-tools:
 	curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sudo sh -s -- -b /usr/local/bin/ latest
 
@@ -34,6 +40,7 @@ ci-test-production-image:
 			'${TEST_IMAGE}' \
 			--ci
 
+
 ## For development
 
 run: build