From 6f0c407dbc4f9c152647718d0b9e9c24ebb6c82b Mon Sep 17 00:00:00 2001
From: Excavator Bot <33266368+svc-excavator-bot@users.noreply.github.com>
Date: Tue, 23 Nov 2021 20:40:20 +0000
Subject: [PATCH] Excavator: Manages GitHub action that publishes artifacts to
 GitHub using godel (#60)

---
 .github/actions/go-dist-info/action.yml       | 87 +++++++++++++++++++
 .github/actions/go-dist-setup/action.yml      | 67 ++++++++++++++
 .github/workflows/publish-godel-artifacts.yml | 25 +++++-
 3 files changed, 177 insertions(+), 2 deletions(-)
 create mode 100644 .github/actions/go-dist-info/action.yml
 create mode 100644 .github/actions/go-dist-setup/action.yml

diff --git a/.github/actions/go-dist-info/action.yml b/.github/actions/go-dist-info/action.yml
new file mode 100644
index 00000000..710d3a68
--- /dev/null
+++ b/.github/actions/go-dist-info/action.yml
@@ -0,0 +1,87 @@
+name: 'Get information for Go distribution'
+description: |
+  Determines the Go distribution version that should be used based on the provided parameter, the go-version file in the
+  repository, and the fallback value. Sets outputs that indicate the version of Go that should be used and whether or
+  not the directory for that distribution exists.
+inputs:
+  gopath:
+    description: |
+      The value of GOPATH.
+    required: true
+  go-version:
+    description: |
+      If non-empty, this value is written as the Go version (files in the repository/image are not consulted). The
+      version should be of the form specified in a Go distribution's VERSION file (for example, "go1.16.5").
+    required: false
+    default: ""
+  go-version-file:
+    description: |
+      The path to the file that specifies the version of Go that should be used for the project.
+    required: false
+    default: ".palantir/go-version"
+  go-prev-version:
+    description: |
+      If greater than 0, modifies the version of Go that would be used to be the first release of the version of Go that
+      is go-prev-version minor versions smaller. For example, if the version of Go that would be used is "go1.16.5" and
+      go-prev-version is 1, the version of Go that will be used will be "go1.15". An error is raised if the subtraction
+      would make the minor version less than 0.
+    required: false
+    default: "0"
+outputs:
+  go-dist-version:
+    description: "Version of Go distribution that should be used."
+    value: ${{ steps.determine-go-dist-version.outputs.go-dist-version }}
+  go-dist-exists:
+    description: "'true' if the desired Go distribution exists, 'false' otherwise."
+    value: ${{ steps.go-dist-exists.outputs.go-dist-exists }}
+runs:
+  using: "composite"
+  steps:
+    - id: determine-go-dist-version
+      shell: bash
+      run: |
+        PARAM_GO_VERSION="${{ inputs.go-version }}"
+        PARAM_GO_VERSION_FILE="${{ inputs.go-version-file }}"
+        PARAM_GO_PREV_VERSION="${{ inputs.go-prev-version }}"
+        FALLBACK_GO_VERSION_FILE="$(go env GOROOT)"/VERSION
+        # set Go version
+        GO_VERSION=${PARAM_GO_VERSION}
+        if [ ! -z "${GO_VERSION}" ]; then
+          echo "Go version specified as parameter is ${GO_VERSION}"
+        elif [ -f "${PARAM_GO_VERSION_FILE}" ]; then
+          GO_VERSION=$(cat "${PARAM_GO_VERSION_FILE}")
+          echo "Go version specified in ${PARAM_GO_VERSION_FILE} is ${GO_VERSION}"
+        elif [ -f "${FALLBACK_GO_VERSION_FILE}" ]; then
+          GO_VERSION=$(cat "${FALLBACK_GO_VERSION_FILE}")
+          echo "Go version specified in ${FALLBACK_GO_VERSION_FILE} is ${GO_VERSION}"
+        else
+          echo "Error: Go version was not specified as a parameter and neither ${PARAM_GO_VERSION_FILE} nor ${FALLBACK_GO_VERSION_FILE} exist"
+          exit 1
+        fi
+        if (( PARAM_GO_PREV_VERSION > 0 )); then
+          GO_MINOR_VERSION=$(echo "${GO_VERSION}" | sed 's/^go[0-9][0-9]*\.\([0-9][0-9]*\).*$/\1/')
+          if (( GO_MINOR_VERSION == 0 )); then
+            echo "Decrement operation not supported when minor version is 0"
+            exit 1
+          fi
+          (( GO_MINOR_VERSION = GO_MINOR_VERSION - PARAM_GO_PREV_VERSION ))
+          if (( GO_MINOR_VERSION < 0 )); then
+            echo "Minor version cannot be less than 0; was: ${GO_MINOR_VERSION}"
+            exit 1
+          fi
+          GO_MAJOR_VERSION=$(echo "${GO_VERSION}" | sed 's/^go\([0-9][0-9]*\).*$/\1/')
+          GO_VERSION="go${GO_MAJOR_VERSION}.${GO_MINOR_VERSION}"
+        fi
+        echo "::set-output name=go-dist-version::$(echo $GO_VERSION)"
+    - id: go-dist-exists
+      shell: bash
+      run: |
+        GO_DIST_EXISTS="false"
+        GO_DIST_DIR_PATH="${{ steps.gopath.outputs.gopath }}/go-dists/${{ steps.determine-go-dist-version.outputs.go-dist-version }}"
+        if [ -d "${GO_DIST_DIR_PATH}" ]; then
+          echo "Found directory at ${GO_DIST_DIR_PATH}: setting GO_DIST_EXISTS=true"
+          GO_DIST_EXISTS="true"
+        else
+          echo "No directory found at ${GO_DIST_DIR_PATH}"
+        fi
+        echo "::set-output name=go-dist-exists::$GO_DIST_EXISTS"
diff --git a/.github/actions/go-dist-setup/action.yml b/.github/actions/go-dist-setup/action.yml
new file mode 100644
index 00000000..c2d0580f
--- /dev/null
+++ b/.github/actions/go-dist-setup/action.yml
@@ -0,0 +1,67 @@
+name: Set up Go distribution
+description: |
+  Sets up the Go distribution by creating a symlink from /usr/local/go to the Go distribution and updating the PATH
+  accordingly. Downloads the Go distribution of the specified version if it does not already exist.
+inputs:
+  gopath:
+    description: |
+      The $GOPATH value.
+    required: true
+  go-version:
+    description: |
+      The version of the Go distribution to download and set up.
+    required: true
+  go-dist-download-url-prefix:
+    description: |
+      Prefix of the download URL that should be used to download the Golang distribution. The prefix is joined with
+      the desired Go distribution file (for example, "go1.16.5.linux-amd64.tar.gz").
+    required: false
+    default: "https://golang.org/dl/"
+  go-dist-os-arch:
+    description: |
+      The os-arch value for the distribution to be downloaded.
+    required: false
+    default: "linux-amd64"
+runs:
+  using: "composite"
+  steps:
+    - id: download-go-dist
+      shell: bash
+      run: |
+        PARAM_GOPATH="${{ inputs.gopath }}"
+        PARAM_GO_VERSION="${{ inputs.go-version }}"
+        PARAM_GO_DIST_DOWNLOAD_URL_PREFIX="${{ inputs.go-dist-download-url-prefix }}"
+        PARAM_GO_DIST_OS_ARCH="${{ inputs.go-dist-os-arch }}"
+        # set Go version
+        GO_VERSION="${PARAM_GO_VERSION}"
+        GO_DIST_DIR="${PARAM_GOPATH}/go-dists/${GO_VERSION}"
+        # desired distribution already exists: nothing to do
+        if [ -d "${GO_DIST_DIR}" ]; then
+          echo "${GO_DIST_DIR} exists: nothing to do"
+          exit
+        fi
+        # Desired distribution does not already exist and is not in cache: download and ensure that it exists in
+        # location that will be cached and in expected location
+        echo "${GO_DIST_DIR} does not exist"
+        echo "Downloading golang distribution from ${PARAM_GO_DIST_DOWNLOAD_URL_PREFIX}${GO_VERSION}.${PARAM_GO_DIST_OS_ARCH}.tar.gz..." && wget -q "${PARAM_GO_DIST_DOWNLOAD_URL_PREFIX}${GO_VERSION}.${PARAM_GO_DIST_OS_ARCH}.tar.gz"
+        echo "Expanding archive" && tar xf "${GO_VERSION}.${PARAM_GO_DIST_OS_ARCH}.tar.gz"
+        echo "Removing archive" && rm "${GO_VERSION}.${PARAM_GO_DIST_OS_ARCH}.tar.gz"
+        echo "Creating ${PARAM_GOPATH}/go-dists directory" && mkdir -p "${PARAM_GOPATH}/go-dists"
+        echo "Moving expanded Go distribution to ${GO_DIST_DIR}" && mv go "${GO_DIST_DIR}"
+        echo "Setting working directory to ${PARAM_GOPATH} to ensure that 'install std' command doesn't use local go.mod file" && cd "${PARAM_GOPATH}"
+        echo "Running go install std for linux-amd64" && GOOS=linux GOARCH=amd64 "${GO_DIST_DIR}/bin/go" install std
+        echo "Running go install std for linux-arm64" && GOOS=linux GOARCH=arm64 "${GO_DIST_DIR}/bin/go" install std
+        echo "Running go install std for darwin-amd64" && GOOS=darwin GOARCH=amd64 "${GO_DIST_DIR}/bin/go" install std
+        echo "Running go install std for darwin-arm64" && GOOS=darwin GOARCH=arm64 "${GO_DIST_DIR}/bin/go" install std
+        echo "Running go install std for windows-amd64" && GOOS=windows GOARCH=amd64 "${GO_DIST_DIR}/bin/go" install std
+    - id: set-up-symlinks
+      shell: bash
+      run: |
+        which go
+        sudo rm -f /usr/bin/go
+        sudo rm -f /usr/local/bin/go
+        sudo ln -s "${{ inputs.gopath }}/go-dists/${{ inputs.go-version }}" /usr/local/go
+        echo "/usr/local/go/bin" >> $GITHUB_PATH
+    - id: go-version
+      shell: bash
+      run: go version
diff --git a/.github/workflows/publish-godel-artifacts.yml b/.github/workflows/publish-godel-artifacts.yml
index 25c72455..6041ffa5 100644
--- a/.github/workflows/publish-godel-artifacts.yml
+++ b/.github/workflows/publish-godel-artifacts.yml
@@ -8,9 +8,30 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: actions/setup-go@v2
+      #####################
+      # START Go dist setup
+      #####################
+      - id: set-gopath
+        run: echo "::set-output name=GOPATH::$(go env GOPATH)"
+      - id: go-dist-info
+        uses: ./.github/actions/go-dist-info
         with:
-          go-version: '1.16.0'
+          gopath: ${{ steps.set-gopath.outputs.gopath }}
+      - id: restore-go-dist-from-cache
+        if: steps.go-dist-info.outputs.go-dist-exists != 'true'
+        uses: actions/cache@v2
+        with:
+          path: |
+            ${{ steps.set-gopath.outputs.gopath }}/go-dists/${{ steps.go-dist-info.outputs.go-dist-version }}
+          key: ${{ runner.os }}-${{ steps.go-dist-info.outputs.go-dist-version }}
+      - id: go-dist-setup
+        uses: ./.github/actions/go-dist-setup
+        with:
+          gopath: ${{ steps.set-gopath.outputs.gopath }}
+          go-version: ${{ steps.go-dist-info.outputs.go-dist-version }}
+      #####################
+      # END Go dist setup
+      #####################
       - uses: actions/cache@v2
         with:
           path: |