open-vault/.github/workflows/ci.yml
2023-10-16 16:42:55 +00:00

436 lines
18 KiB
YAML

name: CI
on:
pull_request:
# The default types for pull_request are [ opened, synchronize, reopened ].
# This is insufficient for our needs, since we're skipping stuff on PRs in
# draft mode. By adding the ready_for_review type, when a draft pr is marked
# ready, we run everything, including the stuff we'd have skipped up until now.
types: [opened, synchronize, reopened, ready_for_review]
push:
branches:
- main
- release/**
workflow_dispatch:
concurrency:
group: ${{ github.head_ref || github.run_id }}-ci
cancel-in-progress: true
jobs:
setup:
name: Setup
runs-on: ubuntu-latest
outputs:
compute-small: ${{ steps.setup-outputs.outputs.compute-small }}
compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }}
compute-large: ${{ steps.setup-outputs.outputs.compute-large }}
compute-largem: ${{ steps.setup-outputs.outputs.compute-largem }}
compute-xlarge: ${{ steps.setup-outputs.outputs.compute-xlarge }}
enterprise: ${{ steps.setup-outputs.outputs.enterprise }}
go-tags: ${{ steps.setup-outputs.outputs.go-tags }}
checkout-ref: ${{ steps.checkout-ref-output.outputs.checkout-ref }}
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- id: setup-outputs
name: Setup outputs
run: |
github_repository="${{ github.repository }}"
if [ "${github_repository##*/}" == "vault-enterprise" ] ; then
# shellcheck disable=SC2129
echo 'compute-small=["self-hosted","ondemand","linux","type=c6a.large"]' >> "$GITHUB_OUTPUT" # 2x vCPUs, 4 GiB RAM,
echo 'compute-medium=["self-hosted","ondemand","linux","type=c6a.xlarge"]' >> "$GITHUB_OUTPUT" # 4x vCPUs, 8 GiB RAM,
echo 'compute-large=["self-hosted","ondemand","linux","type=c6a.2xlarge","disk_gb=64"]' >> "$GITHUB_OUTPUT" # 8x vCPUs, 16 GiB RAM,
echo 'compute-largem=["self-hosted","ondemand","linux","type=m6a.2xlarge"]' >> "$GITHUB_OUTPUT" # 8x vCPUs, 32 GiB RAM,
echo 'compute-xlarge=["self-hosted","ondemand","linux","type=c6a.4xlarge"]' >> "$GITHUB_OUTPUT" # 16x vCPUs, 32 GiB RAM,
echo 'enterprise=1' >> "$GITHUB_OUTPUT"
echo 'go-tags=ent,enterprise' >> "$GITHUB_OUTPUT"
else
# shellcheck disable=SC2129
echo 'compute-small="ubuntu-latest"' >> "$GITHUB_OUTPUT" # 2x vCPUs, 7 GiB RAM, 14 GB SSD
echo 'compute-medium="custom-linux-small-vault-latest"' >> "$GITHUB_OUTPUT" # 8x vCPUs, 32 GiB RAM, 300 GB SSD
echo 'compute-large="custom-linux-medium-vault-latest"' >> "$GITHUB_OUTPUT" # 16x vCPUs, 64 GiB RAM, 600 GB SSD
echo 'compute-largem="custom-linux-medium-vault-latest"' >> "$GITHUB_OUTPUT" # 16x vCPUs, 64 GiB RAM, 600 GB SSD
echo 'compute-xlarge="custom-linux-xl-vault-latest"' >> "$GITHUB_OUTPUT" # 32x vCPUs, 128 GiB RAM, 1200 GB SSD
echo 'enterprise=' >> "$GITHUB_OUTPUT"
echo 'go-tags=' >> "$GITHUB_OUTPUT"
fi
- name: Ensure Go modules are cached
uses: ./.github/actions/set-up-go
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
no-restore: true # don't download them on a cache hit
# control checking out head instead of default ref by a GH label
# if checkout-head label is added to a PR, checkout HEAD otherwise checkout ref
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'checkout-head') }}
run: echo "CHECKOUT_REF=${{ github.ref }}" >> "$GITHUB_ENV"
- if: ${{ contains(github.event.pull_request.labels.*.name, 'checkout-head') }}
run: echo "CHECKOUT_REF=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_ENV"
- id: checkout-ref-output
run: echo "checkout-ref=${{ env.CHECKOUT_REF }}" >> "$GITHUB_OUTPUT"
diff-oss-ci:
name: Diff OSS
needs:
- setup
if: ${{ needs.setup.outputs.enterprise != '' && github.base_ref != '' }}
runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }}
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
fetch-depth: 0
- id: determine-branch
run: |
branch="${{ github.base_ref }}"
if [[ $branch = release/* ]] ; then
branch=${branch%%+ent}
# Add OSS remote
git config --global user.email "github-team-secret-vault-core@hashicorp.com"
git config --global user.name "hc-github-team-secret-vault-core"
git remote add oss https://github.com/hashicorp/vault.git
git fetch oss "$branch"
branch="oss/$branch"
else
branch="origin/$branch"
fi
echo "BRANCH=$branch" >> "$GITHUB_OUTPUT"
- id: diff
run: |
./.github/scripts/oss-diff.sh ${{ steps.determine-branch.outputs.BRANCH }} HEAD
verify-changes:
name: Verify doc-ui only PRs
uses: ./.github/workflows/verify_changes.yml
test-go:
name: Run Go tests
needs:
- setup
- verify-changes
# Don't run this job for docs/ui only PRs
if: |
needs.verify-changes.outputs.is_docs_change == 'false' &&
needs.verify-changes.outputs.is_ui_change == 'false'
uses: ./.github/workflows/test-go.yml
with:
# The regular Go tests use an extra runner to execute the
# binary-dependent tests. We isolate them there so that the
# other tests aren't slowed down waiting for a binary build.
binary-tests: true
total-runners: 16
go-arch: amd64
go-tags: '${{ needs.setup.outputs.go-tags }},deadlock'
runs-on: ${{ needs.setup.outputs.compute-large }}
enterprise: ${{ needs.setup.outputs.enterprise }}
checkout-ref: ${{ needs.setup.outputs.checkout-ref }}
secrets: inherit
test-go-testonly:
name: Run Go tests tagged with testonly
needs:
- setup
- verify-changes
# Don't run this job for docs/ui only PRs
if: |
needs.verify-changes.outputs.is_docs_change == 'false' &&
needs.verify-changes.outputs.is_ui_change == 'false'
uses: ./.github/workflows/test-go.yml
with:
testonly: true
total-runners: 2 # test runners cannot be less than 2
go-arch: amd64
go-tags: '${{ needs.setup.outputs.go-tags }},deadlock,testonly'
runs-on: ${{ needs.setup.outputs.compute-large }}
enterprise: ${{ needs.setup.outputs.enterprise }}
secrets: inherit
test-go-race:
name: Run Go tests with data race detection
needs:
- setup
- verify-changes
# Don't run this job for docs/ui only PRs
if: |
github.event.pull_request.draft == false &&
needs.verify-changes.outputs.is_docs_change == 'false' &&
needs.verify-changes.outputs.is_ui_change == 'false'
uses: ./.github/workflows/test-go.yml
with:
total-runners: 16
env-vars: |
{
"VAULT_CI_GO_TEST_RACE": 1
}
extra-flags: '-race'
go-arch: amd64
go-tags: ${{ needs.setup.outputs.go-tags }}
runs-on: ${{ needs.setup.outputs.compute-large }}
enterprise: ${{ needs.setup.outputs.enterprise }}
name: "race"
checkout-ref: ${{ needs.setup.outputs.checkout-ref }}
secrets: inherit
test-go-fips:
name: Run Go tests with FIPS configuration
# Only run fips on the enterprise repo, and only if it's main or a release branch
# (i.e. not a PR), or is a PR with the label "fips"
if: |
needs.setup.outputs.enterprise == 1 &&
needs.verify-changes.outputs.is_docs_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
- verify-changes
uses: ./.github/workflows/test-go.yml
with:
total-runners: 16
env-vars: |
{
"GOEXPERIMENT": "boringcrypto"
}
go-arch: amd64
go-tags: '${{ needs.setup.outputs.go-tags }},deadlock,cgo,fips,fips_140_2'
runs-on: ${{ needs.setup.outputs.compute-large }}
enterprise: ${{ needs.setup.outputs.enterprise }}
name: "fips"
checkout-ref: ${{ needs.setup.outputs.checkout-ref }}
secrets: inherit
test-ui:
name: Test UI
# The test-ui job is only run on:
# - pushes to main and branches starting with "release/"
# - PRs where the branch starts with "ui/", "backport/ui/", "merge", or when base branch starts with "release/"
# - PRs with the "ui" label on GitHub
if: |
github.ref_name == 'main' ||
startsWith(github.ref_name, 'release/') ||
startsWith(github.head_ref, 'ui/') ||
startsWith(github.head_ref, 'backport/ui/') ||
startsWith(github.head_ref, 'merge') ||
contains(github.event.pull_request.labels.*.name, 'ui')
needs:
- setup
permissions:
id-token: write
contents: read
runs-on: ${{ fromJSON(needs.setup.outputs.compute-largem) }}
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- uses: ./.github/actions/set-up-go
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
# Setup node.js without caching to allow running npm install -g yarn (next step)
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
with:
node-version-file: './ui/package.json'
- id: install-yarn
run: |
npm install -g yarn
# Setup node.js with caching using the yarn.lock file
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
with:
node-version-file: './ui/package.json'
cache: yarn
cache-dependency-path: ui/yarn.lock
- id: install-browser
uses: browser-actions/setup-chrome@c485fa3bab6be59dce18dbc18ef6ab7cbc8ff5f1 # v1.2.0
- id: ui-dependencies
name: ui-dependencies
working-directory: ./ui
run: |
yarn install --frozen-lockfile
npm rebuild node-sass
- id: vault-auth
name: Authenticate to Vault
if: github.repository == 'hashicorp/vault-enterprise'
run: vault-auth
- id: secrets
name: Fetch secrets
if: github.repository == 'hashicorp/vault-enterprise'
uses: hashicorp/vault-action@130d1f5f4fe645bb6c83e4225c04d64cfb62de6e
with:
url: ${{ steps.vault-auth.outputs.addr }}
caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }}
token: ${{ steps.vault-auth.outputs.token }}
secrets: |
kv/data/github/hashicorp/vault-enterprise/github-token token | PRIVATE_REPO_GITHUB_TOKEN;
kv/data/github/hashicorp/vault-enterprise/license license_1 | VAULT_LICENSE;
- id: setup-git
name: Setup Git
if: github.repository == 'hashicorp/vault-enterprise'
run: |
git config --global url."https://${{ steps.secrets.outputs.PRIVATE_REPO_GITHUB_TOKEN }}@github.com".insteadOf https://github.com
- id: build-go-dev
name: build-go-dev
run: |
rm -rf ./pkg
mkdir ./pkg
make ci-bootstrap dev
- id: test-ui
name: test-ui
env:
VAULT_LICENSE: ${{ steps.secrets.outputs.VAULT_LICENSE }}
run: |
export PATH="${PWD}/bin:${PATH}"
if [ "${{ github.repository }}" == 'hashicorp/vault' ] ; then
export VAULT_LICENSE="${{ secrets.VAULT_LICENSE }}"
fi
# Run Ember tests
cd ui
mkdir -p test-results/qunit
yarn test:oss
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: test-results-ui
path: ui/test-results
if: success() || failure()
- uses: test-summary/action@62bc5c68de2a6a0d02039763b8c754569df99e3f # TSCCR: no entry for repository "test-summary/action"
with:
paths: "ui/test-results/qunit/results.xml"
show: "fail"
if: always()
tests-completed:
needs:
- setup
- test-go
- test-ui
if: always()
runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }}
steps:
- run: |
tr -d '\n' <<< '${{ toJSON(needs.*.result) }}' | grep -q -v -E '(failure|cancelled)'
notify-tests-completed-failures-oss:
if: |
always() &&
github.repository == 'hashicorp/vault' &&
(needs.test-go.result == 'failure' ||
needs.test-go-fips.result == 'failure' ||
needs.test-go-race.result == 'failure') &&
(github.ref_name == 'main' || startsWith(github.ref_name, 'release/'))
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
strategy:
fail-fast: false
needs:
- test-go
- test-go-fips
- test-go-race
steps:
- name: send-notification
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
# We intentionally aren't using the following here since it's from an internal repo
# uses: hashicorp/cloud-gha-slack-notifier@730a033037b8e603adf99ebd3085f0fdfe75e2f4 #v1
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
with:
channel-id: "C05AABYEA9Y" # sent to #feed-vault-ci-official
payload: |
{"text":"OSS test failures on ${{ github.ref_name }}","blocks":[{"type":"header","text":{"type":"plain_text","text":":rotating_light: OSS test failures :rotating_light:","emoji":true}},{"type":"divider"},{"type":"section","text":{"type":"mrkdwn","text":"test(s) failed on ${{ github.ref_name }}"},"accessory":{"type":"button","text":{"type":"plain_text","text":"View Failing Workflow","emoji":true},"url":"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}}]}
notify-tests-completed-failures-ent:
if: |
always() &&
github.repository == 'hashicorp/vault-enterprise' &&
(needs.test-go.result == 'failure' ||
needs.test-go-fips.result == 'failure' ||
needs.test-go-race.result == 'failure') &&
(github.ref_name == 'main' || startsWith(github.ref_name, 'release/'))
runs-on: ['self-hosted', 'linux', 'small']
permissions:
id-token: write
contents: read
strategy:
fail-fast: false
needs:
- test-go
- test-go-fips
- test-go-race
steps:
- id: vault-auth
name: Vault Authenticate
run: vault-auth
- id: secrets
name: Fetch Vault Secrets
uses: hashicorp/vault-action@130d1f5f4fe645bb6c83e4225c04d64cfb62de6e
with:
url: ${{ steps.vault-auth.outputs.addr }}
caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }}
token: ${{ steps.vault-auth.outputs.token }}
secrets: |
kv/data/github/${{ github.repository }}/github_actions_notifications_bot token | SLACK_BOT_TOKEN;
- name: send-notification
uses: hashicorp/cloud-gha-slack-notifier@730a033037b8e603adf99ebd3085f0fdfe75e2f4 #v1
with:
channel-id: "C05AABYEA9Y" # sent to #feed-vault-ci-official
slack-bot-token: ${{ steps.secrets.outputs.SLACK_BOT_TOKEN }}
payload: |
{"text":"Enterprise test failures on ${{ github.ref_name }}","blocks":[{"type":"header","text":{"type":"plain_text","text":":rotating_light: Enterprise test failures :rotating_light:","emoji":true}},{"type":"divider"},{"type":"section","text":{"type":"mrkdwn","text":"test(s) failed on ${{ github.ref_name }}"},"accessory":{"type":"button","text":{"type":"plain_text","text":"View Failing Workflow","emoji":true},"url":"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}}]}
test-summary:
name: Go test failures
runs-on: ubuntu-latest
if: |
always() &&
(needs.test-go.result == 'success' ||
needs.test-go.result == 'failure' ||
needs.test-go-fips.result == 'success' ||
needs.test-go-fips.result == 'failure' ||
needs.test-go-race.result == 'success' ||
needs.test-go-race.result == 'failure')
needs:
- test-go
- test-go-fips
- test-go-race
steps:
- name: Download failure summary
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: failure-summary
- name: Prepare failure summary
run: |
# Sort all of the summary table rows and push them to a temp file.
temp_file_name=temp-$(date +%s)
cat failure-summary-*.md | sort >> "$temp_file_name"
# If there are test failures, present them in a format of a GitHub Markdown table.
if [ -s "$temp_file_name" ]; then
# shellcheck disable=SC2129
# Here we create the headings for the summary table
echo "| Test Type | Package | Test | Elapsed | Runner Index | Logs |" >> "$GITHUB_STEP_SUMMARY"
echo "| --------- | ------- | ---- | ------- | ------------ | ---- |" >> "$GITHUB_STEP_SUMMARY"
# shellcheck disable=SC2002
cat "$temp_file_name" >> "$GITHUB_STEP_SUMMARY"
else
echo "### All Go tests passed! :white_check_mark:" >> "$GITHUB_STEP_SUMMARY"
fi
# the random EOF is needed for a multiline environment variable
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
# shellcheck disable=SC2129
echo "TABLE_TEST_RESULTS<<$EOF" >> "$GITHUB_ENV"
cat "$temp_file_name" >> "$GITHUB_ENV"
echo "$EOF" >> "$GITHUB_ENV"
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Create comment
if: github.head_ref != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
RUN_ID: ${{ github.run_id }}
REPO: ${{ github.event.repository.name }}
TABLE_DATA: ${{ env.TABLE_TEST_RESULTS }}
run: ./.github/scripts/report_failed_tests.sh