name: Build/Release Corso env: IMAGE_NAME: ghcr.io/alcionai/corso on: workflow_dispatch: pull_request: push: branches: [main] tags: ["v*.*.*"] repository_dispatch: types: [ok-to-test-command] 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@v4 # 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.websitefileschanged == 'true' with: go-version-file: src/go.mod # SetM365App will decide which M365 app to use for this CI run SetM365App: uses: alcionai/corso/.github/workflows/accSelector.yaml@main SetEnv: environment: Testing runs-on: ubuntu-latest outputs: environment: ${{ steps.environment.outputs.environment }} version: ${{ steps.version.outputs.version }} website-bucket: ${{ steps.website-bucket.outputs.website-bucket }} website-cfid: ${{ steps.website-cfid.outputs.website-cfid }} steps: - uses: actions/checkout@v4 - name: Figure out environment id: environment run: | if ${{ startsWith(github.ref, 'refs/tags/') }}; then echo "environment=Production" | tee -a $GITHUB_OUTPUT else echo "environment=Testing" | tee -a $GITHUB_OUTPUT fi - name: Get version string id: version run: | if ${{ startsWith(github.ref, 'refs/tags/') }}; then echo "version=$(git describe --exact-match --tags $(git rev-parse HEAD))" | tee -a $GITHUB_OUTPUT else echo "version=$(echo unreleased-$(git rev-parse --short HEAD))" | tee -a $GITHUB_OUTPUT fi - name: Get bucket name for website id: website-bucket run: | if ${{ startsWith(github.ref, 'refs/tags/') }}; then echo "website-bucket=corsobackup.io" | tee -a $GITHUB_OUTPUT else echo "website-bucket=test-corso-docs" | tee -a $GITHUB_OUTPUT fi - name: Get cfid for website id: website-cfid run: | if ${{ startsWith(github.ref, 'refs/tags/') }}; then echo "website-cfid=E1W9NGI9YTVZ1A" | tee -a $GITHUB_OUTPUT else echo "website-cfid=ESFTEIYTIP7Y3" | tee -a $GITHUB_OUTPUT fi # ---------------------------------------------------------------------------------------------------- # --- Website Linting ----------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- Website-Linting: needs: [Precheck, Checkout, SetEnv] environment: Testing runs-on: ubuntu-latest timeout-minutes: 30 if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || needs.precheck.outputs.websitefileschanged == 'true' # websitefileschanged also includes srcfileschanged steps: - uses: actions/checkout@v4 - name: Lint Website uses: ./.github/actions/website-linting with: version: ${{ needs.SetEnv.outputs.version }} # ---------------------------------------------------------------------------------------------------- # --- Integration and Unit Testing ------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- Test-Suite-Trusted: needs: [Precheck, Checkout, SetM365App] environment: Testing runs-on: ubuntu-latest timeout-minutes: 120 if: (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main') || (needs.precheck.outputs.srcfileschanged == 'true' && github.event.pull_request.head.repo.full_name == github.repository) defaults: run: working-directory: src env: # Resolve the name of the secret that contains the Azure client ID/secret AZURE_CLIENT_ID_NAME: ${{ needs.SetM365App.outputs.client_id_env }} AZURE_CLIENT_SECRET_NAME: ${{ needs.SetM365App.outputs.client_secret_env }} CLIENT_APP_SLOT: ${{ needs.SetM365App.outputs.client_app_slot }} CORSO_LOG_FILE: ${{ github.workspace }}/src/testlog/run-ci.log LOG_GRAPH_REQUESTS: true steps: - uses: actions/checkout@v4 - name: Setup Golang with cache uses: magnetikonline/action-golang-cache@v4 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@v4 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[env.AZURE_CLIENT_ID_NAME] }} AZURE_CLIENT_SECRET: ${{ secrets[env.AZURE_CLIENT_SECRET_NAME] }} AZURE_TENANT_ID: ${{ secrets.TENANT_ID }} CORSO_CI_TESTS: true CORSO_M365_TEST_USER_ID: ${{ vars.CORSO_M365_TEST_USER_ID }} CORSO_SECONDARY_M365_TEST_USER_ID: ${{ vars.CORSO_SECONDARY_M365_TEST_USER_ID }} CORSO_PASSPHRASE: ${{ secrets.INTEGRATION_TEST_CORSO_PASSPHRASE }} S3_BUCKET: ${{ secrets.CI_TESTS_S3_BUCKET }} run: | set -euo pipefail go test \ -tags testing \ -json \ -v \ -failfast \ -p 1 \ -timeout 20m \ ./... \ 2>&1 | tee ./testlog/gotest-ci.log | gotestfmt -hide successful-tests # Upload the original go test output as an artifact for later review. - name: Upload test log if: failure() uses: actions/upload-artifact@v4 with: name: ci-test-log path: src/testlog/* if-no-files-found: error retention-days: 14 Retention-Test-Suite-Trusted: needs: [Precheck, Checkout, SetM365App] environment: Testing runs-on: ubuntu-latest timeout-minutes: 30 if: (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main') || (needs.precheck.outputs.srcfileschanged == 'true' && github.event.pull_request.head.repo.full_name == github.repository) defaults: run: working-directory: src env: # Resolve the name of the secret that contains the Azure client ID/secret AZURE_CLIENT_ID_NAME: ${{ needs.SetM365App.outputs.client_id_env }} AZURE_CLIENT_SECRET_NAME: ${{ needs.SetM365App.outputs.client_secret_env }} CLIENT_APP_SLOT: ${{ needs.SetM365App.outputs.client_app_slot }} CORSO_LOG_FILE: ${{ github.workspace }}/src/testlog/run-ci-retention.log LOG_GRAPH_REQUESTS: true steps: - uses: actions/checkout@v4 - name: Setup Golang with cache uses: magnetikonline/action-golang-cache@v4 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@v4 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} role-session-name: integration-testing aws-region: us-east-1 # run the tests - name: Retention Tests env: AZURE_CLIENT_ID: ${{ secrets[env.AZURE_CLIENT_ID_NAME] }} AZURE_CLIENT_SECRET: ${{ secrets[env.AZURE_CLIENT_SECRET_NAME] }} AZURE_TENANT_ID: ${{ secrets.TENANT_ID }} CORSO_RETENTION_TESTS: true CORSO_M365_TEST_USER_ID: ${{ vars.CORSO_M365_TEST_USER_ID }} CORSO_SECONDARY_M365_TEST_USER_ID: ${{ vars.CORSO_SECONDARY_M365_TEST_USER_ID }} CORSO_PASSPHRASE: ${{ secrets.INTEGRATION_TEST_CORSO_PASSPHRASE }} S3_BUCKET: ${{ secrets.CI_RETENTION_TESTS_S3_BUCKET }} run: | set -euo pipefail go test \ -tags testing \ -json \ -v \ -failfast \ -p 1 \ -timeout 10m \ ./... \ 2>&1 | tee ./testlog/gotest-ci.log | gotestfmt -hide successful-tests # Upload the original go test output as an artifact for later review. - name: Upload test log if: failure() uses: actions/upload-artifact@v4 with: name: ci-retention-test-log path: src/testlog/* if-no-files-found: error retention-days: 14 Unit-Test-Suite: needs: [Precheck, Checkout] environment: Testing runs-on: ubuntu-latest timeout-minutes: 30 if: needs.precheck.outputs.srcfileschanged == 'true' defaults: run: working-directory: src env: CORSO_LOG_FILE: ${{ github.workspace }}/src/testlog/run-unit.log LOG_GRAPH_REQUESTS: true steps: - uses: actions/checkout@v4 - name: Setup Golang with cache uses: magnetikonline/action-golang-cache@v4 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 # run the tests - name: Unit Tests env: # Set these to a bad value so we don't accidentally fall back to # something elsewhere. CORSO_M365_TEST_USER_ID: 'foo' CORSO_SECONDARY_M365_TEST_USER_ID: 'foo' run: | set -euo pipefail go test \ -tags testing \ -json \ -v \ -failfast \ -p 1 \ -timeout 20m \ ./... \ 2>&1 | tee ./testlog/gotest-unit.log | gotestfmt -hide successful-tests # Upload the original go test output as an artifact for later review. - name: Upload test log if: failure() uses: actions/upload-artifact@v4 with: name: unit-test-log path: src/testlog/* if-no-files-found: error retention-days: 14 Test-Suite-Fork: needs: [Precheck] environment: Testing if: (!startsWith(github.ref , 'refs/tags/') && github.ref != 'refs/heads/main') && (needs.precheck.outputs.srcfileschanged == 'true' && github.event.pull_request.head.repo.full_name != github.repository) runs-on: ubuntu-latest defaults: run: working-directory: src env: CORSO_LOG_FILE: ${{ github.workspace }}/testlog/run-fork.log LOG_GRAPH_REQUESTS: true steps: - name: Fail check if not repository_dispatch if: github.event_name != 'repository_dispatch' run: | echo "Workflow requires approval from a maintainer to run. It will be automatically rerun on approval." exit 1 - uses: marocchino/sticky-pull-request-comment@v2 if: github.event.client_payload.slash_command.args.named.sha != '' && contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.args.named.sha) with: message: | Workflow run sha specified via `ok-to-test` is not the latest commit on PR. Run canceled. - name: Fail check if not head of PR if: github.event.client_payload.slash_command.args.named.sha != '' && contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.args.named.sha) run: | echo "Workflow run sha specified is not the latest commit on PR. Exiting." exit 1 # add comment to PR with link to workflow run - uses: marocchino/sticky-pull-request-comment@v2 with: message: | Test suite run will be available at https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID # Check out merge commit - name: Fork based /ok-to-test checkout uses: actions/checkout@v4 with: ref: "refs/pull/${{ github.event.client_payload.pull_request.number }}/merge" - name: Setup Golang with cache uses: magnetikonline/action-golang-cache@v4 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@v4 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_M365_TEST_USER_ID: ${{ vars.CORSO_M365_TEST_USER_ID }} CORSO_PASSPHRASE: ${{ secrets.INTEGRATION_TEST_CORSO_PASSPHRASE }} run: | set -euo pipefail go test \ -json \ -v \ -timeout 15m \ ./... \ 2>&1 | tee ./testlog/gotest-fork.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@v4 with: name: fork-test-log path: src/testlog/* if-no-files-found: error retention-days: 14 # Update check run called "Test-Suite-Fork" - uses: actions/github-script@v7 id: update-check-run if: failure() env: number: ${{ github.event.client_payload.pull_request.number }} job: ${{ github.job }} # Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run conclusion: ${{ job.status }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const { data: pull } = await github.rest.pulls.get({ ...context.repo, pull_number: process.env.number }); const ref = pull.head.sha; const { data: checks } = await github.rest.checks.listForRef({ ...context.repo, ref }); const check = checks.check_runs.filter(c => c.name === process.env.job); const { data: result } = await github.rest.checks.update({ ...context.repo, check_run_id: check[0].id, status: 'completed', conclusion: process.env.conclusion }); return result; # ---------------------------------------------------------------------------------------------------- # --- Source Code Linting ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- Source-Code-Linting: needs: [Precheck, Checkout] environment: Testing runs-on: ubuntu-latest timeout-minutes: 30 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@v4 - name: Setup Golang with cache uses: magnetikonline/action-golang-cache@v4 with: go-version-file: src/go.mod - name: Go Lint uses: golangci/golangci-lint-action@v4 with: # Keep pinned to a verson as sometimes updates will add new lint # failures in unchanged code. version: v1.54.2 working-directory: src skip-pkg-cache: true skip-build-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 - name: Run staticcheck uses: dominikh/staticcheck-action@v1.3.0 with: install-go: false working-directory: src - name: Run allowtags run: | go install github.com/ashmrtn/allowtags@latest allowtags --allow-key json --allow-key uriparametername ./... # I could not find a way to install tree-grepper without nix # https://github.com/BrianHicks/tree-grepper/issues/293 - uses: cachix/install-nix-action@v25 - uses: cachix/cachix-action@v14 with: name: tree-grepper - run: nix-env -if https://github.com/BrianHicks/tree-grepper/archive/refs/heads/main.tar.gz - name: Run trailing comma lint rule run: | # Using `grep .` as the exit codes are always true for correct grammar if tree-grepper -q go '(argument_list "," @no-trailing-comma .)' | grep .; then echo "No trailing commas for function calls" exit 1 fi - name: Check for empty string comparison run: | # Using `grep .` as the exit codes are always true for correct grammar if tree-grepper -q go '((binary_expression (identifier) ["==" "!="] (interpreted_string_literal) @_ri) @exp (#eq? @_ri "\"\""))' | grep .; then echo "Use len check instead of empty string comparison" exit 1 fi - name: Check for cases where errors are not propagated run: | # Using `grep .` as the exit codes are always true for correct grammar if tree-grepper -q go '((if_statement (binary_expression) @_if (block (return_statement (expression_list (call_expression (selector_expression) @_fun ) @ret .)))) (#match? @_if "err != nil") (#match? @_fun "clues.NewWC"))' | grep .; then echo "Make sure to propagate errors with clues" exit 1 fi - name: Check if clues without context are used when context is passed in run: | # Using `grep .` as the exit codes are always true for correct grammar if tree-grepper -q go '((function_declaration (parameter_list . (parameter_declaration (identifier) @_octx)) body: (block (short_var_declaration left: (expression_list (identifier) @_err . ) right: (expression_list (call_expression (argument_list . (identifier) @_ctx)))) . (if_statement (binary_expression) @_exp consequence: (block (return_statement (expression_list (call_expression (selector_expression (call_expression (selector_expression) @clue))) . )))))) (#eq? @_err "err") (#eq? @_octx "ctx") (#eq? @_ctx "ctx") (#eq? @_exp "err != nil") (#match? @clue "^clues\.") (#match? @clue "WC$"))' | grep .; then echo "Do not use clues.*WC when context is passed in" exit 1 fi - name: Check clues with context is used when context is not passed in run: | # Using `grep .` as the exit codes are always true for correct grammar if tree-grepper -q go '((function_declaration (parameter_list . (parameter_declaration (identifier) @_octx)) body: (block (short_var_declaration left: (expression_list (identifier) @_err . ) right: (expression_list (call_expression (argument_list . (identifier) @_ctx)))) . (if_statement (binary_expression) @_exp consequence: (block (return_statement (expression_list (call_expression (selector_expression (call_expression (selector_expression) @clue))) . )))))) (#eq? @_err "err") (#eq? @_octx "ctx") (#not-eq? @_ctx "ctx") (#eq? @_exp "err != nil") (#match? @clue "^clues\.") (#not-match? @clue "WC$"))' | grep .; then echo "Use clues.*WC when context is not passed in" exit 1 fi # ---------------------------------------------------------------------------------------------------- # --- GitHub Actions Linting ------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- Actions-Lint: needs: [Precheck] environment: Testing runs-on: ubuntu-latest if: needs.precheck.outputs.actionsfileschanged == 'true' steps: - uses: actions/checkout@v4 - name: actionlint uses: raven-actions/actionlint@v1 with: fail-on-error: true cache: true # Ignore # * combining commands into a subshell and using single output # redirect # * various variable quoting patterns # * possible ineffective echo commands flags: "-ignore SC2129 -ignore SC2086 -ignore SC2046 -ignore 2116" # ---------------------------------------------------------------------------------------------------- # --- Publish steps ---------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- Publish-Binary: needs: [Test-Suite-Trusted, Source-Code-Linting, Website-Linting, SetEnv] environment: ${{ needs.SetEnv.outputs.environment }} runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - name: Publish Binary uses: ./.github/actions/publish-binary with: version: ${{ needs.SetEnv.outputs.version }} github_token: ${{ secrets.GITHUB_TOKEN }} rudderstack_write_key: ${{ secrets.RUDDERSTACK_CORSO_WRITE_KEY }} rudderstack_data_plane_url: ${{ secrets.RUDDERSTACK_CORSO_DATA_PLANE_URL }} Publish-Image: needs: [Test-Suite-Trusted, Source-Code-Linting, Website-Linting, SetEnv] environment: ${{ needs.SetEnv.outputs.environment }} runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') defaults: run: working-directory: build env: PLATFORMS: linux/amd64,linux/arm64 steps: - uses: actions/checkout@v4 # Setup buildx - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 # retrieve credentials for ghcr.io - name: Login to Github Packages uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v5 with: images: ${{ env.IMAGE_NAME }} tags: | type=ref,event=tag type=sha,format=short,prefix= type=raw,value=nightly # deploy the image - name: Build image and push to GitHub Container Registry uses: docker/build-push-action@v5 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/internal/version.Version=${{ needs.SetEnv.outputs.version }}' # use the github cache cache-from: type=gha cache-to: type=gha,mode=max Validate-Linux-Artifacts: needs: [Publish-Binary, Publish-Image, SetEnv] environment: Testing runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') env: CORSO_VERSION: ${{ needs.SetEnv.outputs.version }} steps: - name: Validate x86_64 binary artifacts run: | set -ex curl -L https://github.com/alcionai/corso/releases/download/${{ env.CORSO_VERSION }}/corso_${{ env.CORSO_VERSION }}_Linux_x86_64.tar.gz > corso.tar.gz tar -xf corso.tar.gz ./corso --help ./corso --version 2>&1 | grep -E "version: ${{ env.CORSO_VERSION }}$" - name: Validate arm64 binary artifacts uses: uraimo/run-on-arch-action@v2 with: arch: armv7 distro: ubuntu18.04 install: | apt-get -y update && apt-get -y install curl run: | set -ex sudo apt-get update && sudo apt-get install curl curl -L https://github.com/alcionai/corso/releases/download/${{ env.CORSO_VERSION }}/corso_${{ env.CORSO_VERSION }}_Linux_arm64.tar.gz > corso.tar.gz tar -xf corso.tar.gz ./corso --help ./corso --version 2>&1 | grep -E "version: ${{ env.CORSO_VERSION }}$" Validate-Docker-Artifacts: needs: [Publish-Binary, Publish-Image, SetEnv] environment: Testing runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') env: CORSO_VERSION: ${{ needs.SetEnv.outputs.version }} steps: - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Validate amd64 container images run: | docker run --platform linux/amd64 ${{ env.IMAGE_NAME }}:${{ env.CORSO_VERSION }} --help docker run --platform linux/amd64 ${{ env.IMAGE_NAME }}:${{ env.CORSO_VERSION }} --version | grep -E "version: ${{ env.CORSO_VERSION }}$" - name: Validate arm64 container images run: | docker run --platform linux/arm64 ${{ env.IMAGE_NAME }}:${{ env.CORSO_VERSION }} --help docker run --platform linux/amd64 ${{ env.IMAGE_NAME }}:${{ env.CORSO_VERSION }} --version | grep -E "version: ${{ env.CORSO_VERSION }}$" Validate-MacOS-Artifacts: needs: [Publish-Binary, Publish-Image, SetEnv] environment: Testing runs-on: macos-latest if: startsWith(github.ref, 'refs/tags/') env: CORSO_VERSION: ${{ needs.SetEnv.outputs.version }} steps: - name: Validate x86_64 binary artifacts run: | set -ex curl -L https://github.com/alcionai/corso/releases/download/${{ env.CORSO_VERSION }}/corso_${{ env.CORSO_VERSION }}_Darwin_x86_64.tar.gz > corso.tar.gz tar -xf corso.tar.gz ./corso --help ./corso --version 2>&1 | grep -E "version: ${{ env.CORSO_VERSION }}$" - name: Validate arm64 binary artifacts run: | set -ex curl -L https://github.com/alcionai/corso/releases/download/${{ env.CORSO_VERSION }}/corso_${{ env.CORSO_VERSION }}_Darwin_arm64.tar.gz > corso.tar.gz tar -xf corso.tar.gz # TODO: test/validate arm64 executable once we have arm64 CI Validate-Windows-Artifacts: needs: [Publish-Binary, Publish-Image, SetEnv] environment: Testing runs-on: windows-latest if: startsWith(github.ref, 'refs/tags/') env: CORSO_VERSION: ${{ needs.SetEnv.outputs.version }} steps: - name: Validate x86_64 binary artifacts run: | curl -L https://github.com/alcionai/corso/releases/download/${{ env.CORSO_VERSION }}/corso_${{ env.CORSO_VERSION }}_Windows_x86_64.zip -o corso.zip 7z x corso.zip ./corso.exe --help ./corso.exe --version 2>&1 | grep -E "version: ${{ env.CORSO_VERSION }}$" Publish-Website-Test: needs: [Test-Suite-Trusted, Source-Code-Linting, Website-Linting, SetEnv] environment: ${{ needs.SetEnv.outputs.environment }} runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 # need to checkout to make the action available - name: Publish website uses: ./.github/actions/publish-website with: aws-iam-role: ${{ secrets.AWS_IAM_ROLE }} bucket: ${{ needs.SetEnv.outputs.website-bucket }} cfid: ${{ needs.SetEnv.outputs.website-cfid }} Publish-Website-Prod: needs: [SetEnv, Validate-Linux-Artifacts, Validate-MacOS-Artifacts, Validate-Docker-Artifacts, Validate-Windows-Artifacts] environment: ${{ needs.SetEnv.outputs.environment }} runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') steps: - uses: actions/checkout@v4 # need to checkout to make the action available - name: Publish website uses: ./.github/actions/publish-website with: aws-iam-role: ${{ secrets.AWS_IAM_ROLE }} bucket: ${{ needs.SetEnv.outputs.website-bucket }} cfid: ${{ needs.SetEnv.outputs.website-cfid }} Validate-Website-Artifacts: needs: [Publish-Website-Prod, SetEnv] environment: Testing runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') env: CORSO_VERSION: ${{ needs.SetEnv.outputs.version }} steps: - name: Validate docs run: | curl https://corsobackup.io/docs/quickstart/ | grep https://github.com/alcionai/corso/releases/download/${{ env.CORSO_VERSION }}/corso_${{ env.CORSO_VERSION }}_Linux_x86_64.tar.gz