Abin Simon a9acbc28f5
Rework build.sh script (#1167)
## Description

While trying to work on https://github.com/alcionai/corso/issues/1166, I ended up reworking parts of the build script ~, but I'm running into some issues with building it on CI. Pushing it here just for reference.~

The new one combines both `build.sh` and `build-container.sh` into a single script where you can specify what to build. Also, inorder setup a proper multi arch, build system locally, we will have to properly setup buildx which is explained in https://docs.docker.com/build/building/multi-platform/ or https://stackoverflow.com/a/70837025/2724649 . I'll add this instructions to docs.

The new build script looks something like this:

```
Usage: build.sh <binary|image> [--platforms ...] [--tag ...]

OPTIONS
 -p|--platforms  Platforms to build for (default: linux/amd64)
                 Specify multiple platforms using ',' (eg: linux/amd64,darwin/arm)
 -t|--tag        Tag for container image (default: alcionai/corso)
```

---
I've made sure the image and binary has the proper architecure and that the amd64 one runs properly in my system. It would be helpful if someone who has access to arm system can validate the arm image. You can use https://github.com/alcionai/corso/pkgs/container/corso/45878348?tag=84fc9d4 image to verify.

```
$ cat check-image.sh
imgid="$(docker create "$1")"
docker cp "$imgid:corso" /tmp/corso

echo Image: "$(docker inspect "$1" | jq '.[0].Architecture')"
echo Binary: "$(file /tmp/corso)"

$ ./check-image.sh ghcr.io/alcionai/corso:84fc9d4@sha256:2278a2b4f108e5dd2ae545f53da1d151b77171f969ffd9718e4bb9886e332ee2
WARNING: The requested image's platform (linux/arm64) does not match the detected host platform (linux/amd64) and no specific platform was requested
Image: "arm64"
Binary: /tmp/corso: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1, Go BuildID=7iTBXW0reyfIOS-b-ciS/a5K0Q1IjuA0m9DJxmuNk/Ju1lI6bUZeKn6M_xqon6/KNXwYSnL7e5RVtjAKW9A, not stripped

$ ./check-image.sh ghcr.io/alcionai/corso:84fc9d4@sha256:6320b95470014ca07b9cf1db98b73f5672870c2c53c22c3d13223d88fa621ee0
Image: "amd64"
Binary: /tmp/corso: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, Go BuildID=sBziMHPFI9K-G0et0WjJ/Pe9A2Vy8_xpV3FEDJUMo/p4UeMEzgheASvylZ1N3j/fnwmDeVif4rhneou-S6O, not stripped

$ docker run -it --rm ghcr.io/alcionai/corso:84fc9d4@sha256:6320b95470014ca07b9cf1db98b73f5672870c2c53c22c3d13223d88fa621ee0
[...help message...]
```

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [x] 💻 CI/Deployment
- [ ] 🐹 Trivial/Minor

## Issue(s)

<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* https://github.com/alcionai/corso/issues/1166

## Test Plan

<!-- How will this be tested prior to merging.-->
- [x] 💪 Manual
- [ ]  Unit test
- [ ] 💚 E2E
2022-10-18 05:28:44 +00:00

348 lines
12 KiB
YAML

name: Build/Release Corso
on:
workflow_dispatch:
pull_request:
branches: [ main ]
push:
branches: [ main ]
tags: [ 'v*.*.*' ]
permissions:
# required to retrieve AWS credentials
id-token: write
contents: write
packages: write
pull-requests: read
# cancel currently running jobs if a new version of the branch is pushed
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# ----------------------------------------------------------------------------------------------------
# --- Prechecks and Checkouts ------------------------------------------------------------------------
# ----------------------------------------------------------------------------------------------------
Precheck:
uses: alcionai/corso/.github/workflows/_filechange_checker.yml@main
Checkout:
needs: [Precheck]
environment: Testing
runs-on: ubuntu-latest
defaults:
run:
working-directory: src
steps:
- uses: actions/checkout@v3
# single setup and sum cache handling here.
# the results will cascade onto both testing and linting.
- name: Setup Golang with cache
uses: ./.github/actions/go-setup-cache
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.docfileschanged == 'true'
with:
go-version-file: src/go.mod
# ----------------------------------------------------------------------------------------------------
# --- Docs Linting -----------------------------------------------------------------------------------
# ----------------------------------------------------------------------------------------------------
Docs-Linting:
needs: [Precheck, Checkout]
environment: Testing
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.docfileschanged == 'true' # docsfileschanged also includes srcfileschanged
steps:
- uses: actions/checkout@v3
- name: Setup Golang with cache
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.srcfileschanged == 'true'
uses: magnetikonline/action-golang-cache@v3
with:
go-version-file: src/go.mod
- name: Generate CLI Docs
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.srcfileschanged == 'true'
working-directory: ./src
run: |
go run ./cmd/mdgen/mdgen.go generate
# migrate generated md files into /docs/docs/cli
- name: Move CLI .md to Docs
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.srcfileschanged == 'true'
run: |
mkdir -p ./docs/docs/cli
mv ./src/cmd/mdgen/cli_markdown/* ./docs/docs/cli/
rm -R ./src/cmd/mdgen/cli_markdown/
- uses: actions/upload-artifact@master
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.srcfileschanged == 'true'
name: Upload cli docs as artifacts
with:
name: cli-docs
path: docs/docs/cli
- name: Install dependencies for docs lint
run: |
wget https://github.com/errata-ai/vale/releases/download/v2.20.2/vale_2.20.2_Linux_64-bit.tar.gz # NOTE: update in Dockerfile when updating
mkdir bin && tar -xvzf vale_2.20.2_Linux_64-bit.tar.gz -C bin
echo "$PWD/bin" >> $GITHUB_PATH
npm i -g markdownlint-cli@0.32.2 # NOTE: update in Dockerfile when updating
- name: Run docs lint
env:
CORSO_USE_DOCKER: -1 # prevent using docker inside makefile
run: |
cd docs && make -o genclidocs check
# ----------------------------------------------------------------------------------------------------
# --- Integration and Unit Testing -------------------------------------------------------------------
# ----------------------------------------------------------------------------------------------------
Test-Suite:
needs: [Precheck, Checkout]
environment: Testing
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.srcfileschanged == 'true'
defaults:
run:
working-directory: src
steps:
- uses: actions/checkout@v3
- name: Setup Golang with cache
uses: magnetikonline/action-golang-cache@v3
with:
go-version-file: src/go.mod
- run: mkdir testlog
# Install gotestfmt
- name: Set up gotestfmt
run: go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
# AWS creds
- name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
role-session-name: integration-testing
aws-region: us-east-1
# run the tests
- name: Integration Tests
env:
AZURE_CLIENT_ID: ${{ secrets.CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ secrets.TENANT_ID }}
CORSO_CI_TESTS: true
CORSO_M356_TEST_USER_ID: ${{ secrets.CORSO_M356_TEST_USER_ID }}
CORSO_PASSPHRASE: ${{ secrets.INTEGRATION_TEST_CORSO_PASSPHRASE }}
run: |
set -euo pipefail
go test \
-json \
-v \
./... 2>&1 | tee ./testlog/gotest.log | gotestfmt -hide successful-tests
# Upload the original go test log as an artifact for later review.
- name: Upload test log
if: failure()
uses: actions/upload-artifact@v3
with:
name: test-log
path: src/testlog/gotest.log
if-no-files-found: error
retention-days: 14
# ----------------------------------------------------------------------------------------------------
# --- Source Code Linting ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------------------------------
Linting:
needs: [Precheck, Checkout]
environment: Testing
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.srcfileschanged == 'true'
defaults:
run:
working-directory: src
steps:
- uses: actions/checkout@v3
- name: Setup Golang with cache
uses: magnetikonline/action-golang-cache@v3
with:
go-version-file: src/go.mod
- name: Go Lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.45.2
working-directory: src
skip-cache: true
# check licenses
- name: Get go-licenses
run: go install github.com/google/go-licenses@latest
- name: Run go-licenses
run: go-licenses check github.com/alcionai/corso/src --ignore github.com/alcionai/corso/src
# ----------------------------------------------------------------------------------------------------
# --- Publish steps ----------------------------------------------------------------------------------
# ----------------------------------------------------------------------------------------------------
SetEnv:
environment: Testing
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
outputs:
environment: ${{ steps.set-env.outputs.environment }}
steps:
- name: Figure out environment
id: set-env
run: |
if ${{ startsWith(github.ref, 'refs/tags/') }}; then
echo "set-output name=environment::Production"
echo "::set-output name=environment::Production"
else
echo "set-output name=environment::Testing"
echo "::set-output name=environment::Testing"
fi
Publish-Binary:
needs: [Test-Suite, Linting, Docs-Linting, SetEnv]
environment: ${{ needs.SetEnv.outputs.environment }}
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main'
defaults:
run:
working-directory: src
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # needed to pull changelog
- name: Setup Golang with cache
uses: magnetikonline/action-golang-cache@v3
with:
go-version-file: src/go.mod
- id: version
run: echo "::set-output name=version::$(git describe --exact-match --tags $(git rev-parse HEAD) 2>/dev/null || echo unreleased)-$(git rev-parse --short HEAD)"
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3
with:
version: latest
args: release --rm-dist --timeout 500m
workdir: src
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUDDERSTACK_CORSO_WRITE_KEY: ${{ secrets.RUDDERSTACK_CORSO_WRITE_KEY }}
RUDDERSTACK_CORSO_DATA_PLANE_URL: ${{ secrets.RUDDERSTACK_CORSO_DATA_PLANE_URL }}
CORSO_VERSION: ${{ steps.version.outputs.version }}
- name: Upload assets
uses: actions/upload-artifact@v3
with:
name: corso
path: src/dist/*
Publish-Docs:
needs: [Test-Suite, Linting, Docs-Linting, SetEnv]
environment: ${{ needs.SetEnv.outputs.environment }}
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main'
defaults:
run:
working-directory: docs
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@master
name: Download cli docs from build step
with:
name: cli-docs
path: docs/docs/cli
- name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
role-session-name: integration-testing
aws-region: us-east-1
- name: Build docs
run: |
npm ci
CORSO_DOCS_BASEURL="/preview/" npm run build # TODO: update base url once finalized
- name: Push docs
run: |
echo "$DOCS_BUCKET" | base64
aws s3 sync build "s3://${{ secrets.DOCS_S3_BUCKET }}/preview"
- name: Invalidate cloudfront
run: |
aws cloudfront create-invalidation --distribution-id ${{ secrets.DOCS_CF_DISTRIBUTION }} --paths "/*"
Publish-Image:
needs: [Test-Suite, Linting, Docs-Linting, SetEnv]
environment: ${{ needs.SetEnv.outputs.environment }}
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main'
defaults:
run:
working-directory: build
env:
imageName: ghcr.io/alcionai/corso
PLATFORMS: linux/amd64,linux/arm64
steps:
- uses: actions/checkout@v3
# Setup buildx
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# retrieve credentials for ghcr.io
- name: Login to Github Packages
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.imageName }}
tags: |
type=ref,event=tag
type=sha,format=short,prefix=
# deploy the image
- name: Build image and push to GitHub Container Registry
uses: docker/build-push-action@v3
with:
context: .
file: ./build/Dockerfile
platforms: ${{ env.PLATFORMS }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
CORSO_BUILD_LDFLAGS=-X 'github.com/alcionai/corso/src/internal/events.RudderStackWriteKey=${{ secrets.RUDDERSTACK_CORSO_WRITE_KEY }}' -X 'github.com/alcionai/corso/src/internal/events.RudderStackDataPlaneURL=${{ secrets.RUDDERSTACK_CORSO_DATA_PLANE_URL }}' -X 'github.com/alcionai/corso/src/cli.version=$(git describe --exact-match --tags $(git rev-parse HEAD) 2>/dev/null || echo unreleased)-$(git rev-parse --short HEAD)'
# use the github cache
cache-from: type=gha
cache-to: type=gha,mode=max