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: runs-on: ${{ github.repository == 'hashicorp/vault' && 'ubuntu-latest' || fromJSON('["self-hosted","linux","small"]') }} outputs: app-changed: ${{ steps.changed-files.outputs.app-changed }} checkout-ref: ${{ steps.checkout.outputs.ref }} compute-small: ${{ steps.metadata.outputs.compute-small }} compute-test-go: ${{ steps.metadata.outputs.compute-test-go }} compute-test-ui: ${{ steps.metadata.outputs.compute-test-ui }} go-tags: ${{ steps.metadata.outputs.go-tags }} is-draft: ${{ steps.metadata.outputs.is-draft }} is-enterprise: ${{ steps.metadata.outputs.is-enterprise }} is-fork: ${{ steps.metadata.outputs.is-fork }} labels: ${{ steps.metadata.outputs.labels }} ui-changed: ${{ steps.changed-files.outputs.ui-changed }} workflow-trigger: ${{ steps.metadata.outputs.workflow-trigger }} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: ./.github/actions/changed-files id: changed-files - uses: ./.github/actions/checkout id: checkout # make sure we check out correct ref after checking changed files - uses: ./.github/actions/metadata id: metadata - 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 test-go: # Run Go tests if the vault app changed if: needs.setup.outputs.app-changed == 'true' name: Run Go tests needs: setup 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 checkout-ref: ${{ needs.setup.outputs.checkout-ref }} go-arch: amd64 go-tags: '${{ needs.setup.outputs.go-tags }},deadlock' name: standard runs-on: ${{ needs.setup.outputs.compute-test-go }} runs-on-small: ${{ needs.setup.outputs.compute-small }} test-timing-cache-key: go-test-timing-standard total-runners: 16 secrets: inherit test-go-testonly: # Run Go tests tagged with "testonly" if the vault app changed if: needs.setup.outputs.app-changed == 'true' name: Run Go tests tagged with testonly needs: setup uses: ./.github/workflows/test-go.yml with: checkout-ref: ${{ needs.setup.outputs.checkout-ref }} go-arch: amd64 go-tags: '${{ needs.setup.outputs.go-tags }},deadlock,testonly' name: testonly runs-on: ${{ needs.setup.outputs.compute-test-go }} runs-on-small: ${{ needs.setup.outputs.compute-small }} testonly: true test-timing-cache-enabled: false total-runners: 2 # test runners cannot be less than 2 secrets: inherit test-go-race: # Run Go test with the data race detector enabled if the vault app changed and we're out of # drafts mode. if: needs.setup.outputs.app-changed == 'true' && needs.setup.outputs.is-draft == 'false' name: Run Go tests with data race detection needs: setup uses: ./.github/workflows/test-go.yml with: checkout-ref: ${{ needs.setup.outputs.checkout-ref }} env-vars: | { "VAULT_CI_GO_TEST_RACE": 1 } extra-flags: '-race' name: race go-arch: amd64 go-tags: ${{ needs.setup.outputs.go-tags }} runs-on: ${{ needs.setup.outputs.compute-test-go }} runs-on-small: ${{ needs.setup.outputs.compute-small }} test-timing-cache-key: go-test-timing-race total-runners: 16 secrets: inherit test-go-fips: name: Run Go tests with FIPS configuration # Run the Go tests with fips if the vault app changed, we're in the context vault enterprise # and our trigger is a merge to main or releases/* or if the 'fips' label is present on a PR. if: | needs.setup.outputs.app-changed == 'true' && needs.setup.outputs.is-enterprise == 'true' && (needs.setup.outputs.workflow-trigger == 'push' || contains(needs.setup.outputs.labels, 'fips')) needs: setup uses: ./.github/workflows/test-go.yml with: checkout-ref: ${{ needs.setup.outputs.checkout-ref }} env-vars: | { "GOEXPERIMENT": "boringcrypto" } name: fips go-arch: amd64 go-tags: '${{ needs.setup.outputs.go-tags }},deadlock,cgo,fips,fips_140_2' runs-on: ${{ needs.setup.outputs.compute-test-go }} runs-on-small: ${{ needs.setup.outputs.compute-small }} test-timing-cache-key: go-test-timing-fips total-runners: 16 secrets: inherit test-ui: name: Test UI # Run the UI tests if our UI has changed, or a 'ui' label is present, or our workflow trigger # was triggered by a merge to main or releases/*. if: | needs.setup.outputs.ui-changed == 'true' || needs.setup.outputs.workflow-trigger == 'push' || contains(github.event.pull_request.labels.*.name, 'ui') needs: setup permissions: id-token: write contents: read runs-on: ${{ fromJSON(needs.setup.outputs.compute-test-ui) }} steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 name: status with: ref: ${{ needs.setup.outputs.checkout-ref }} - 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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: node-version-file: './ui/package.json' - run: npm install -g yarn # Setup node.js with caching using the yarn.lock file - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: node-version-file: './ui/package.json' cache: yarn cache-dependency-path: ui/yarn.lock - uses: browser-actions/setup-chrome@52f10de5479c69bcbbab2eab094c9d373148005e # v1.4.0 - name: ui-dependencies working-directory: ./ui run: | yarn install --frozen-lockfile npm rebuild node-sass - if: needs.setup.outputs.is-enterprise == 'true' id: vault-auth name: Authenticate to Vault run: vault-auth - if: needs.setup.outputs.is-enterprise == 'true' id: secrets name: Fetch secrets uses: hashicorp/vault-action@9f522b85981b491eab9a52c144d15aedbd0bf371 # v2.8.0 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 username-and-token | PRIVATE_REPO_GITHUB_TOKEN; kv/data/github/hashicorp/vault-enterprise/license license_1 | VAULT_LICENSE; - if: needs.setup.outputs.is-enterprise == 'true' name: Set up Git run: git config --global url."https://${{ steps.secrets.outputs.PRIVATE_REPO_GITHUB_TOKEN }}@github.com".insteadOf https://github.com - name: build-go-dev run: | rm -rf ./pkg mkdir ./pkg make prep dev - name: test-ui env: VAULT_LICENSE: ${{ steps.secrets.outputs.VAULT_LICENSE }} run: | export PATH="${PWD}/bin:${PATH}" # Run Ember tests cd ui mkdir -p test-results/qunit yarn ${{ needs.setup.outputs.is-enterprise == 'true' && 'test' || 'test:oss' }} - if: always() uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: test-results-ui path: ui/test-results - if: always() uses: test-summary/action@fee35d7df20790255fe6aa92cf0f6d28092ecf2f # v2.2 with: paths: "ui/test-results/qunit/results.xml" show: "fail" tests-completed: needs: - setup - test-go - test-go-testonly - test-go-race - test-go-fips - test-ui if: always() runs-on: ${{ github.repository == 'hashicorp/vault' && 'ubuntu-latest' || fromJSON('["self-hosted","linux","small"]') }} permissions: write-all # Ensure we have id-token:write access for vault-auth. steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 # Determine the overall status of our required test jobs. - name: Determine status id: status run: | # Determine the overall status of the job. We allow fips and race tests to fail so we # don't consider their result here. # # Encode the needs context into JSON, filter out unrequired workflows, shape the result # into a more useful schema. Determine the overall status by comparing the total number of # successful results with the number of required jobs. if results=$(jq -rec 'del(.["test-go-fips"], .["test-go-race"]) as $required | $required | keys as $jobs | reduce $jobs[] as $job ([]; . + [{job: $job}+$required[$job]])' <<< '${{ toJSON(needs) }}' ); then # Determine if all of our required jobs have succeeded. if jq -rec 'length as $expected | [.[] | select((.result == "success") or (.result == "skipped"))] | length as $got | $expected == $got' <<< "$results"; then msg="All required test jobs succeeded!" result="success" else msg="One or more required test jobs failed!" result="failed" fi else msg="Failed to decode and filter test results" result="failed" results="''" fi { echo "msg=${msg}" echo "result=${result}" echo "results<> "$GITHUB_OUTPUT" - if: | always() && needs.setup.outputs.workflow-trigger == 'push' && ( needs.test-go.result == 'failure' || needs.test-go-race.result == 'failure' || needs.test-go-race.outputs.data-race-result == 'failure' || needs.test-go-testonly.result == 'failure' || needs.test-ui.result == 'failure' ) name: Notify build failures in Slack uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.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: ${{ steps.slackbot-token.outputs.slackbot-token }} with: channel-id: "C05AABYEA9Y" # sent to #feed-vault-ci-official, use "C05Q4D5V89W"/test-vault-ci-slack-integration for testing payload: | { "text": "CE test failures on ${{ github.ref_name }}", "text": "${{ github.repository }} build failures on ${{ github.ref_name }}", "blocks": [ { "type": "header", "text": { "type": "plain_text", "text": ":rotating_light: ${{ github.repository }} test failures on ${{ github.ref_name }} :rotating_light:", "emoji": true } }, { "type": "divider" }, { "type": "section", "text": { "type": "mrkdwn", "text": "${{ needs.test-go.result != 'failure' && ':white_check_mark:' || ':x:' }} Go tests\n${{ needs.test-go-race.result != 'failure' && ':white_check_mark:' || ':x:' }} Go race tests\n\t\t${{ needs.test-go-race.outputs.data-race-result != 'success' && ':x:' || ':white_check_mark:' }} Data races detected\n${{ needs.test-go-testonly.result != 'failure' && ':white_check_mark:' || ':x:' }} Go testonly tests\n${{ needs.test-ui.result != 'failure' && ':white_check_mark:' || ':x:' }} UI tests" }, "accessory": { "type": "button", "text": { "type": "plain_text", "text": "View Failing Workflow", "emoji": true }, "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" } } ] } # Only create the PR summary if it's a pull request and it is not a fork as we need access # to secrets. - if: ${{ needs.setup.outputs.is-fork == 'false' }} name: Download failure summaries uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: pattern: failure-summary-*.md path: failure-summaries merge-multiple: true - if: ${{ needs.setup.outputs.is-fork == 'false' }} id: prepare-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-summaries/*.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 # Here we create the headings for the summary table { echo "| Test Type | Package | Test | Elapsed | Runner Index | Logs |" echo "| --------- | ------- | ---- | ------- | ------------ | ---- |" cat "$temp_file_name" } >> "$GITHUB_STEP_SUMMARY" else if [ "${{ steps.status.outputs.result }}" == 'success' ]; then echo "### All required Go tests passed! :white_check_mark:" >> "$GITHUB_STEP_SUMMARY" fi fi { echo 'table-test-results<