Skip to content

Commit

Permalink
[QT-645] Restructure dev tools (#24559) (#24740)
Browse files Browse the repository at this point in the history
We're on a quest to reduce our pipeline execution time to both enhance
our developer productivity but also to reduce the overall cost of the CI
pipeline. The strategy we use here reduces workflow execution time and
network I/O cost by reducing our module cache size and using binary
external tools when possible. We no longer download modules and build
many of the external tools thousands of times a day.

Our previous process of installing internal and external developer tools
was scattered and inconsistent. Some tools were installed via `go
generate -tags tools ./tools/...`,
others via various `make` targets, and some only in Github Actions
workflows. This process led to some undesirable side effects:
  * The modules of some dev and test tools were included with those
    of the Vault project. This leads to us having to manage our own
    Go modules with those of external tools. Prior to Go 1.16 this
    was the recommended way to handle external tools, but now
    `go install tool@version` is the recommended way to handle
    external tools that need to be build from source as it supports
    specific versions but does not modify the go.mod.
  * Due to Github cache constraints we combine our build and test Go
    module caches together, but having our developer tools as deps in
    our module results in a larger cache which is downloaded on every
    build and test workflow runner. Removing the external tools that were
    included in our go.mod reduced the expanded module cache by size
    by ~300MB, thus saving time and network I/O costs when downloading
    the module cache.
  * Not all of our developer tools were included in our modules. Some were
    being installed with `go install` or `go run`, so they didn't take
    advantage of a single module cache. This resulted in us downloading
    Go modules on every CI and Build runner in order to build our
    external tools.
  * Building our developer tools from source in CI is slow. Where possible
    we can prefer to use pre-built binaries in CI workflows. No more
    module download or tool compiles if we can avoid them.

I've refactored how we define internal and external build tools
in our Makefile and added several new targets to handle both building
the developer tools locally for development and verifying that they are
available. This allows for an easy developer bootstrap while also
supporting installation of many of the external developer tools from
pre-build binaries in CI. This reduces our network IO and run time
across nearly all of our actions runners.

While working on this I caught and resolved a few unrelated issue:
* Both our Go and Proto format checks we're being run incorrectly. In
  CI they we're writing changes but not failing if changes were
  detected. The Go was less of a problem as we have git hooks that
  are intended to enforce formatting, however we drifted over time.
* Our Git hooks couldn't handle removing a Go file without failing. I
  moved the diff check into the new Go helper and updated it to handle
  removing files.
* I combined a few separate scripts and into helpers and added a few
  new capabilities.
* I refactored how we install Go modules to make it easier to download
  and tidy all of the projects go.mod's.
* Refactor our internal and external tool installation and verification
  into a tools.sh helper.
* Combined more complex Go verification into `scripts/go-helper.sh` and
  utilize it in the `Makefile` and git commit hooks.
* Add `Makefile` targets for executing our various tools.sh helpers.
* Update our existing `make` targets to use new tool targets.
* Normalize our various scripts and targets output to have a consistent
  output format.
* In CI, install many of our external dependencies as binaries wherever
  possible. When not possible we'll build them from scratch but not mess
  with the shared module cache.
* [QT-641] Remove our external build tools from our project Go modules.
* [QT-641] Remove extraneous `go list`'s from our `set-up-to` composite
  action.
* Fix formatting and regen our protos

Signed-off-by: Ryan Cragun <[email protected]>
  • Loading branch information
hc-github-team-secure-vault-core authored Jan 9, 2024
1 parent fd52fc7 commit da714f3
Show file tree
Hide file tree
Showing 54 changed files with 977 additions and 424 deletions.
32 changes: 32 additions & 0 deletions .github/actions/install-external-tools/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

---
name: Install external tools for CI
description: Install external tools CI

# When possible, prefer installing pre-built external tools for speed. This allows us to avoid
# downloading modules and compiling external tools on CI runners.

runs:
using: composite
steps:
- uses: ./.github/actions/set-up-buf
with:
version: v1.25.0 # This should match the version in tools/tool.sh
- uses: ./.github/actions/set-up-gofumpt
- uses: ./.github/actions/set-up-gotestsum
- uses: ./.github/actions/set-up-misspell
- uses: ./.github/actions/set-up-staticcheck
# We assume that the Go toolchain will be managed by the caller workflow so we don't set one
# up here.
- run: go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
shell: bash
- run: go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
shell: bash
- run: go install github.com/favadi/protoc-go-inject-tag@latest
shell: bash
- run: go install golang.org/x/tools/cmd/goimports@latest
shell: bash
- run: go install github.com/golangci/revgrep/cmd/revgrep@latest
shell: bash
63 changes: 63 additions & 0 deletions .github/actions/set-up-buf/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

---
name: Set up buf from Github releases
description: Set up buf from Github releases

inputs:
destination:
description: "Where to install the buf binary (default: $HOME/bin/buf)"
type: boolean
default: "$HOME/bin/buf"
version:
description: "The version to install (default: latest)"
type: string
default: Latest

outputs:
destination:
description: Where the installed buf binary is
value: ${{ steps.install.outputs.destination }}
destination-dir:
description: The directory where the installed buf binary is
value: ${{ steps.install.outputs.destination-dir }}
version:
description: The installed version of buf
value: ${{ steps.install.outputs.version }}

runs:
using: composite
steps:
- id: install
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(gh release list -R bufbuild/buf --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
echo "destination=$DESTINATION" >> "$GITHUB_OUTPUT"
DESTINATION_DIR="$(dirname "$DESTINATION")"
echo "$DESTINATION_DIR" >> "$GITHUB_PATH"
echo "destination-dir=$DESTINATION_DIR" >> "$GITHUB_OUTPUT"
ARCH="$(echo "$RUNNER_ARCH" | tr '[:upper:]' '[:lower:]')"
OS="$RUNNER_OS"
if [ "$ARCH" = "x64" ]; then
export ARCH="x86_64"
fi
if [ "$ARCH" = "arm64" ] && [ "$OS" = "Linux" ]; then
export ARCH="aarch64"
fi
if [ "$OS" = "macOS" ]; then
export OS="Darwin"
fi
mkdir -p tmp
gh release download "$VERSION" -p "buf-${OS}-${ARCH}.tar.gz" -O tmp/buf.tgz -R bufbuild/buf
pushd tmp && tar -xvf buf.tgz && popd
mv tmp/buf/bin/buf "$DESTINATION"
rm -rf tmp
9 changes: 2 additions & 7 deletions .github/actions/set-up-go/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,5 @@ runs:
shell: bash
run: |
git config --global url."https://${{ inputs.github-token }}@github.com".insteadOf https://github.com
for mod in $(find . -type f -name go.mod); do
pushd "$(dirname $mod)"
go list ./...
go list -test ./...
go mod download
popd
done
make go-mod-download
du -h -d 1 ${{ steps.metadata.outputs.cache-path }}
58 changes: 58 additions & 0 deletions .github/actions/set-up-gofumpt/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

---
name: Set up gofumpt from Github releases
description: Set up gofumpt from Github releases

inputs:
destination:
description: "Where to install the gofumpt binary (default: $HOME/bin/gofumpt)"
type: boolean
default: "$HOME/bin/gofumpt"
version:
description: "The version to install (default: latest)"
type: string
default: Latest

outputs:
destination:
description: Where the installed gofumpt binary is
value: ${{ steps.install.outputs.destination }}
destination-dir:
description: The directory where the installed gofumpt binary is
value: ${{ steps.install.outputs.destination-dir }}
version:
description: The installed version of gofumpt
value: ${{ steps.install.outputs.version }}

runs:
using: composite
steps:
- id: install
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(gh release list -R mvdan/gofumpt --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
echo "destination=$DESTINATION" >> "$GITHUB_OUTPUT"
DESTINATION_DIR="$(dirname "$DESTINATION")"
echo "$DESTINATION_DIR" >> "$GITHUB_PATH"
echo "destination-dir=$DESTINATION_DIR" >> "$GITHUB_OUTPUT"
ARCH="$(echo "$RUNNER_ARCH" | tr '[:upper:]' '[:lower:]')"
OS="$(echo "$RUNNER_OS" | tr '[:upper:]' '[:lower:]')"
if [ "$ARCH" = "x64" ]; then
export ARCH="amd64"
fi
if [ "$OS" = "macos" ]; then
export OS="darwin"
fi
gh release download "$VERSION" -p "gofumpt_*_${OS}_${ARCH}" -O gofumpt -R mvdan/gofumpt
chmod +x gofumpt
mv gofumpt "$DESTINATION"
20 changes: 11 additions & 9 deletions .github/actions/set-up-gotestsum/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ inputs:
destination:
description: "Where to install the gotestsum binary (default: $HOME/bin/gotestsum)"
type: boolean
default: "$HOME/bin"
default: "$HOME/bin/gotestsum"
version:
description: "The version to install (default: latest)"
type: string
Expand All @@ -34,22 +34,24 @@ runs:
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(gh release list -R gotestyourself/gotestsum --exclude-drafts --exclude-pre-releases | grep Latest | cut -f1)
VERSION=$(gh release list -R gotestyourself/gotestsum --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
mkdir -p "$HOME/bin"
DESTINATION="$(readlink -f "$HOME/bin")"
echo "destination=$DESTINATION" >> "GITHUB_OUTPUT"
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
echo "destination=$DESTINATION" >> "$GITHUB_OUTPUT"
DESTINATION_DIR="$(dirname "$DESTINATION")"
echo "$DESTINATION_DIR" >> "$GITHUB_PATH"
echo "destination-dir=$DESTINATION_DIR" >> "GITHUB_OUTPUT"
echo "destination-dir=$DESTINATION_DIR" >> "$GITHUB_OUTPUT"
OS="$(echo "$RUNNER_OS" | tr '[:upper:]' '[:lower:]')"
ARCH="$(echo "$RUNNER_ARCH" | tr '[:upper:]' '[:lower:]')"
if [ "$ARCH" = "x64" ]; then
export ARCH="amd64"
fi
gh release download "$VERSION" -p "*${OS}_${ARCH}.tar.gz" -O gotestsum.tgz -R gotestyourself/gotestsum
tar -xvf gotestsum.tgz
mv gotestsum "${DESTINATION_DIR}/gotestsum"
mkdir -p tmp
gh release download "$VERSION" -p "*${OS}_${ARCH}.tar.gz" -O tmp/gotestsum.tgz -R gotestyourself/gotestsum
pushd tmp && tar -xvf gotestsum.tgz && popd
mv tmp/gotestsum "$DESTINATION"
rm -rf tmp
60 changes: 60 additions & 0 deletions .github/actions/set-up-misspell/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

---
name: Set up misspell from Github releases
description: Set up misspell from Github releases

inputs:
destination:
description: "Where to install the misspell binary (default: $HOME/bin/misspell)"
type: boolean
default: "$HOME/bin/misspell"
version:
description: "The version to install (default: latest)"
type: string
default: Latest

outputs:
destination:
description: Where the installed misspell binary is
value: ${{ steps.install.outputs.destination }}
destination-dir:
description: The directory where the installed misspell binary is
value: ${{ steps.install.outputs.destination-dir }}
version:
description: The installed version of misspell
value: ${{ steps.install.outputs.version }}

runs:
using: composite
steps:
- id: install
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(gh release list -R golangci/misspell --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -f1)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
echo "destination=$DESTINATION" >> "$GITHUB_OUTPUT"
DESTINATION_DIR="$(dirname "$DESTINATION")"
echo "$DESTINATION_DIR" >> "$GITHUB_PATH"
echo "destination-dir=$DESTINATION_DIR" >> "$GITHUB_OUTPUT"
ARCH="$(echo "$RUNNER_ARCH" | tr '[:upper:]' '[:lower:]')"
OS="$(echo "$RUNNER_OS" | tr '[:upper:]' '[:lower:]')"
if [ "$ARCH" = "x64" ]; then
export ARCH="64bit"
fi
if [ "$OS" = "macos" ]; then
export OS="mac"
fi
mkdir -p tmp
gh release download "$VERSION" -p "misspell_*_${OS}_${ARCH}.tar.gz" -O tmp/misspell.tgz -R golangci/misspell
pushd tmp && tar -xvf misspell.tgz && popd
mv tmp/misspell "$DESTINATION"
rm -rf tmp
60 changes: 60 additions & 0 deletions .github/actions/set-up-staticcheck/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1

---
name: Set up staticcheck from Github releases
description: Set up staticcheck from Github releases

inputs:
destination:
description: "Where to install the staticcheck binary (default: $HOME/bin/staticcheck)"
type: boolean
default: "$HOME/bin/staticcheck"
version:
description: "The version to install (default: latest)"
type: string
default: Latest

outputs:
destination:
description: Where the installed staticcheck binary is
value: ${{ steps.install.outputs.destination }}
destination-dir:
description: The directory where the installed staticcheck binary is
value: ${{ steps.install.outputs.destination-dir }}
version:
description: The installed version of staticcheck
value: ${{ steps.install.outputs.version }}

runs:
using: composite
steps:
- id: install
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(gh release list -R dominikh/go-tools --exclude-drafts --exclude-pre-releases | grep ${{ inputs.version }} | cut -d " " -f2)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
mkdir -p $(dirname ${{ inputs.destination }})
DESTINATION="$(readlink -f "${{ inputs.destination }}")"
echo "destination=$DESTINATION" >> "$GITHUB_OUTPUT"
DESTINATION_DIR="$(dirname "$DESTINATION")"
echo "$DESTINATION_DIR" >> "$GITHUB_PATH"
echo "destination-dir=$DESTINATION_DIR" >> "$GITHUB_OUTPUT"
ARCH="$(echo "$RUNNER_ARCH" | tr '[:upper:]' '[:lower:]')"
OS="$(echo "$RUNNER_OS" | tr '[:upper:]' '[:lower:]')"
if [ "$ARCH" = "x64" ]; then
export ARCH="amd64"
fi
if [ "$OS" = "macos" ]; then
export OS="darwin"
fi
mkdir -p tmp
gh release download "$VERSION" -p "staticcheck_${OS}_${ARCH}.tar.gz" -O tmp/staticcheck.tgz -R dominikh/go-tools
pushd tmp && tar -xvf staticcheck.tgz && popd
mv tmp/staticcheck/staticcheck "$DESTINATION"
rm -rf tmp
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
if: |
needs.setup.outputs.enterprise == 1 &&
needs.verify-changes.outputs.is_docs_change == 'false' &&
needs.verify-changes.outputs.is_ui_change == 'false' &&
needs.verify-changes.outputs.is_ui_change == 'false' &&
(contains(github.event.pull_request.labels.*.name, 'fips') || github.ref_name == 'main' || startsWith(github.ref_name, 'release/'))
needs:
- setup
Expand Down Expand Up @@ -243,8 +243,7 @@ jobs:
run: |
rm -rf ./pkg
mkdir ./pkg
make ci-bootstrap dev
make prep dev
- id: test-ui
name: test-ui
env:
Expand Down
Loading

0 comments on commit da714f3

Please sign in to comment.