Skip to content

Fix/make sure start date before end date #122036

Fix/make sure start date before end date

Fix/make sure start date before end date #122036

Workflow file for this run

name: Code Checks
on:
push:
branches: [master]
pull_request:
types: [opened, reopened, synchronize]
permissions:
id-token: write
contents: read
checks: write
jobs:
compare_sha:
runs-on: ubuntu-latest
name: Compare sha
steps:
- name: Compare commit ids
run: |
echo "github.sha: ${{ github.sha }}"
echo "github.event.push.head_commit.id: ${{ github.event.push.head_commit.id }}"
echo "github.event.pull_request.merge_commit_sha: ${{ github.event.pull_request.merge_commit_sha }}"
echo "github.event.head_commit.id: ${{ github.event.head_commit.id }}"
linting_and_security:
name: Linting and Security
env:
BUNDLE_ENTERPRISE__CONTRIBSYS__COM: ${{ secrets.BUNDLE_ENTERPRISE__CONTRIBSYS__COM }}
permissions: write-all
runs-on: ubuntu-32-cores-latest
steps:
- name: Checkout PR
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Checkout PR HEAD ref
if: ${{ github.event_name == 'pull_request' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 1
- name: Compute changed files for boundary check
if: ${{ github.event_name == 'pull_request' }}
run: |
git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.base.sha }}"
git diff --name-only --diff-filter=ACMR "${{ github.event.pull_request.base.sha }}" HEAD > /tmp/changed-files.txt
- name: Check runtime does not depend on spec code
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
CHANGED_FILES_FILE=/tmp/changed-files.txt bash script/ci/check_runtime_spec_dependencies.sh
else
bash script/ci/check_runtime_spec_dependencies.sh
fi
- uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1
with:
bundler-cache: true
- name: Check for Gemfile changes
id: gemfile_changes
if: github.event_name == 'pull_request'
uses: tj-actions/changed-files@v47.0.5
with:
files: |
Gemfile
Gemfile.lock
modules/*/Gemfile
- name: Run bundle-audit (checks gems for CVE issues)
id: bundle_audit
if: |
(
github.ref == 'refs/heads/master' ||
(github.event_name == 'pull_request' && steps.gemfile_changes.outputs.any_changed == 'true')
)
continue-on-error: true
run: bundle exec bundle-audit check --update
- name: Configure AWS Credentials
if: steps.bundle_audit.outcome == 'failure'
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
with:
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
aws-region: us-gov-west-1
- uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: steps.bundle_audit.outcome == 'failure'
with:
ssm_parameter: /devops/VA_VSP_BOT_GITHUB_TOKEN
env_variable_name: VA_VSP_BOT_GITHUB_TOKEN
- name: Checkout VSP actions
if: steps.bundle_audit.outcome == 'failure'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
repository: department-of-veterans-affairs/vsp-github-actions
ref: refs/heads/main
token: ${{ env.VA_VSP_BOT_GITHUB_TOKEN }}
persist-credentials: false
path: ./.github/actions/vsp-github-actions
- uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: steps.bundle_audit.outcome == 'failure'
with:
ssm_parameter: /devops/github_actions_slack_socket_token
env_variable_name: SLACK_APP_TOKEN
- uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: steps.bundle_audit.outcome == 'failure'
with:
ssm_parameter: /devops/github_actions_slack_bot_user_token
env_variable_name: SLACK_BOT_TOKEN
- name: Slack notify - bundle-audit CVE failure
if: |
steps.bundle_audit.outcome == 'failure' &&
(
github.ref == 'refs/heads/master' ||
(github.event_name == 'pull_request' && steps.gemfile_changes.outputs.any_changed == 'true')
)
uses: ./.github/actions/vsp-github-actions/slack-socket
with:
slack_app_token: ${{ env.SLACK_APP_TOKEN }}
slack_bot_token: ${{ env.SLACK_BOT_TOKEN }}
message: "Critical: Vets-API bundle-audit detected CVE vulnerabilities"
blocks: |
[
{ "type": "divider" },
{
"type": "header",
"text": {
"type": "plain_text",
"text": ":rotating_light: CRITICAL: CVE Vulnerability Detected",
"emoji": true
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*bundle-audit found gems with known CVE vulnerabilities in vets-api*"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": ":x: *Status*: Build Failed"
},
{
"type": "mrkdwn",
"text": ":git: *Branch*: `${{ github.ref_name }}`"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":bust_in_silhouette: *Author:* ${{ github.actor }}"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": ":mag_right: View Run",
"emoji": true
},
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"style": "danger"
}
]
},
{ "type": "divider" }
]
channel_id: "C0APA867M0V"
- name: Fail job if bundle-audit found CVEs
if: steps.bundle_audit.outcome == 'failure'
run: exit 1
- name: Run Rubocop
run: bundle exec rubocop --parallel --format github
- name: Run Brakeman
run: bundle exec brakeman --ensure-latest --confidence-level=2 --format github
- name: Run Reek
uses: reviewdog/action-reek@43d3a426ebcfd42aca089a877b60f8e6170c51e0 # v1.20.0
with:
reek_version: gemfile
reporter: github-pr-review
reek_flags: --smell DuplicateMethodCall
# Note: this is the default anyway but explicitly set to remind us we can change to hard-fail on reek warnings with `any`
# For now we just want to run in advisory mode to surface architectural smells as comments during review
# ...but _without_ blocking merges for now
fail_level: none
# Always add the "lint-failure" label on failure and remove it on success
- name: Add Lint Failure label
if: ${{ failure() && github.event_name == 'pull_request' }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: ['lint-failure'],
})
- name: Remove Lint Failure label
if: ${{ success() && github.event_name == 'pull_request' }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
name: 'lint-failure',
})
} catch (e) {
if (e.status !== 404) throw e
}
build:
name: Build and Cache Docker Image
runs-on: ubuntu-16-cores-latest
env:
BUNDLE_ENTERPRISE__CONTRIBSYS__COM: ${{ secrets.BUNDLE_ENTERPRISE__CONTRIBSYS__COM }}
DOCKER_BUILDKIT: 1
steps:
- name: Checkout PR
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Checkout PR HEAD ref
if: ${{ github.event_name == 'pull_request' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 1
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
with:
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
aws-region: us-gov-west-1
- name: Login to Amazon ECR
id: ecr-login
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
with:
mask-password: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
- name: Build and Cache Docker Image
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7
env:
DOCKER_BUILD_SUMMARY: false
with:
build-args: |
BUNDLE_ENTERPRISE__CONTRIBSYS__COM=${{ env.BUNDLE_ENTERPRISE__CONTRIBSYS__COM }}
USER_ID=1001
context: .
push: false
load: false
tags: vets-api
outputs: type=docker,dest=/tmp/vets-api.tar
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Compress Docker image
run: zstd -T0 /tmp/vets-api.tar -o /tmp/vets-api.tar.zst
- name: Save Docker image to cache
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: /tmp/vets-api.tar.zst
key: docker-image-${{ github.sha }}
tests:
name: Test (Group ${{ matrix.test_group }})
runs-on: ubuntu-16-cores-latest
permissions: write-all
needs: build
strategy:
fail-fast: false
matrix:
test_group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
env:
BUNDLE_ENTERPRISE__CONTRIBSYS__COM: ${{ secrets.BUNDLE_ENTERPRISE__CONTRIBSYS__COM }}
ECR_REGISTRY_WITH_SLASH: "${{ secrets.ECR_REGISTRY }}/"
CI: true
RAILS_ENV: test
TERM: xterm-256color
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
COMPOSE_BASH_CMD: docker compose -f docker-compose.test.yml run web bash -c
steps:
- name: Checkout PR
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Checkout PR HEAD ref
if: ${{ github.event_name == 'pull_request' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 1
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
with:
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
aws-region: us-gov-west-1
- name: Login to Amazon ECR
id: ecr-login
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
with:
mask-password: true
- name: Restore Docker image from cache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: /tmp/vets-api.tar.zst
key: docker-image-${{ github.sha }}
fail-on-cache-miss: true
- name: Load Docker image
run: zstd -d /tmp/vets-api.tar.zst --stdout | docker load
# Shard balancing: if a runtime log exists (cached from a previous run),
# parallel_test uses --group-by runtime to distribute specs by actual
# measured execution time. Otherwise it falls back to --group-by filesize.
# The runtime log is generated in publish_results from JUnit XML timing
# data and cached for subsequent runs.
#
# Cache key priority:
# 1. This branch's most recent run
# 2. master branch (so new PRs get balanced shards immediately)
# 3. Any previous run (catch-all fallback)
# If no cache exists at all (e.g. first-ever run), parallel_test uses
# filesize grouping automatically.
- name: Restore runtime log from cache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: tmp/parallel_runtime_rspec.log
key: parallel-runtime-log-${{ github.ref }}-${{ github.run_id }}
restore-keys: |
parallel-runtime-log-${{ github.ref }}-
parallel-runtime-log-refs/heads/master-
parallel-runtime-log-
- name: Determine shard grouping strategy
id: grouping
run: |
if [ -s tmp/parallel_runtime_rspec.log ]; then
echo "strategy=runtime" >> $GITHUB_OUTPUT
echo "Runtime log found, using runtime-based shard balancing"
else
echo "strategy=filesize" >> $GITHUB_OUTPUT
echo "No runtime log found, falling back to filesize grouping"
fi
- name: Setup Database
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
with:
timeout_minutes: 10
retry_wait_seconds: 3 # Seconds
max_attempts: 3
command: >
${{ env.COMPOSE_BASH_CMD }}
"bundle exec rails db:test:prepare"
- name: Setup system tmp dir
run: >
${{ env.COMPOSE_BASH_CMD }}
"mkdir -p tmp/systmp"
- name: Run Specs
timeout-minutes: 15
env:
TEST_ENV_NUMBER: ${{ matrix.test_group }}
run: >
${{ env.COMPOSE_BASH_CMD }}
"TEST_ENV_NUMBER=${{ matrix.test_group }} TMPDIR=tmp/systmp bundle exec parallel_test spec modules --group-by ${{ steps.grouping.outputs.strategy }} --type rspec --only-group ${{ matrix.test_group }} -n 24 -o '--profile 20'"
- name: Prepare SimpleCov shard payload
if: always()
run: |
mkdir -p simplecov-resultset-${{ matrix.test_group }}
if [ -f coverage/.resultset.json ]; then
mv coverage/.resultset.json simplecov-resultset-${{ matrix.test_group }}/.resultset.json
fi
- name: Upload SimpleCov raw resultset
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: simplecov-resultset-${{ matrix.test_group }}
path: simplecov-resultset-${{ matrix.test_group }}/.resultset.json
include-hidden-files: true
if-no-files-found: warn
- name: Upload Test Results (JUnit XMLs)
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: Test Results Group ${{ matrix.test_group }}
path: log/*.xml
if-no-files-found: ignore
- name: Upload Test Artifacts (log)
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
if: always()
with:
name: Test Artifacts (log directory) Group ${{ matrix.test_group }}
path: |
log
!log/*.xml
if-no-files-found: ignore
- name: Upload Test Artifacts (rails tmp)
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: Test Artifacts (rails tmp directory) Group ${{ matrix.test_group }}
path: tmp
if-no-files-found: ignore
retention-days: 14
publish_results:
name: Publish Test Results and Coverage
if: always()
needs: [build, tests]
permissions: write-all
runs-on: ubuntu-16-cores-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: ruby/setup-ruby@3ff19f5e2baf30647122352b96108b1fbe250c64 # v1
env:
BUNDLE_ENTERPRISE__CONTRIBSYS__COM: ${{ secrets.BUNDLE_ENTERPRISE__CONTRIBSYS__COM }}
with:
bundler-cache: ${{ needs.tests.result == 'success' }}
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
- name: Publish Test Results to GitHub
if: always()
uses: EnricoMi/publish-unit-test-result-action@c950f6fb443cb5af20a377fd0dfaa78838901040 # v2
with:
check_name: Test Results
comment_mode: off
files: Test Results Group*/*.xml
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Add Test Failure label
if: ${{ needs.tests.result == 'failure' && github.event_name == 'pull_request' }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: ['test-failure'],
})
- name: Fail job if tests failed
if: ${{ needs.tests.result == 'failure' }}
run: exit 1
- name: Remove Test Failure label
if: ${{ needs.tests.result == 'success' && github.event_name == 'pull_request' }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
name: 'test-failure',
})
} catch (e) {
if (e.status !== 404) throw e
}
# Convert JUnit XML test results into a parallel_test runtime log so that
# future runs can use --group-by runtime (runtime-based shard balancing).
# Each shard uploads JUnit XMLs as artifacts; the download-artifact step
# above already fetched them into "Test Results Group N/" directories.
# The generated log is cached (below) for the next workflow run.
- name: Generate parallel_test runtime log from JUnit XML
if: always()
run: |
mkdir -p tmp
ruby script/junit_to_runtime_log.rb tmp/parallel_runtime_rspec.log "Test Results Group*/*.xml"
- name: Save runtime log to cache
if: always()
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: tmp/parallel_runtime_rspec.log
key: parallel-runtime-log-${{ github.ref }}-${{ github.run_id }}
- name: Download coverage artifacts
if: needs.tests.result == 'success'
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: simplecov-resultset-*
path: .
- name: Collate coverage and generate report
if: needs.tests.result == 'success'
env:
BUNDLE_ENTERPRISE__CONTRIBSYS__COM: ${{ secrets.BUNDLE_ENTERPRISE__CONTRIBSYS__COM }}
run: bundle exec ruby script/coverage_collate.rb
- name: Upload Combined Coverage HTML
if: needs.tests.result == 'success'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: Coverage Report
path: coverage
if-no-files-found: ignore
- name: Fix up coverage report to work with coverage-check-action
id: coverage
if: needs.tests.result == 'success'
run: |
echo "=== Fixing coverage report format ==="
sed -i 's/"line"/"covered_percent"/g' 'coverage/.last_run.json'
echo "=== Verifying modified format ==="
pct=$(cat coverage/.last_run.json | jq '.result.covered_percent')
echo "percent=$pct" >> $GITHUB_OUTPUT
echo "Extracted coverage: $pct"
- name: Publish Coverage Report
if: needs.tests.result == 'success'
uses: devmasx/coverage-check-action@4a754f8957c6824e0a0d44bf9168fdbdf47e7e2f # v1.2.0
with:
type: simplecov
result_path: coverage/.last_run.json
min_coverage: 90
token: ${{ secrets.GITHUB_TOKEN }}
- name: Configure AWS Credentials
if: needs.tests.result == 'success' && github.event_name != 'pull_request'
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6
with:
role-to-assume: ${{ vars.AWS_ASSUME_ROLE }}
aws-region: us-gov-west-1
- uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: needs.tests.result == 'success' && github.event_name != 'pull_request'
with:
ssm_parameter: /devops/VA_VSP_BOT_GITHUB_TOKEN
env_variable_name: VA_VSP_BOT_GITHUB_TOKEN
- name: Checkout VSP actions
if: needs.tests.result == 'success' && github.event_name != 'pull_request'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
repository: department-of-veterans-affairs/vsp-github-actions
ref: refs/heads/main
token: ${{ env.VA_VSP_BOT_GITHUB_TOKEN }}
persist-credentials: false
path: ./.github/actions/vsp-github-actions
- uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: needs.tests.result == 'success' && github.event_name != 'pull_request'
with:
ssm_parameter: /devops/github_actions_slack_socket_token
env_variable_name: SLACK_APP_TOKEN
- uses: department-of-veterans-affairs/action-inject-ssm-secrets@d8e6de3bde4dd728c9d732baef58b3c854b8c4bb # latest
if: needs.tests.result == 'success' && github.event_name != 'pull_request'
with:
ssm_parameter: /devops/github_actions_slack_bot_user_token
env_variable_name: SLACK_BOT_TOKEN
- name: Slack notify - critical coverage alert
if: needs.tests.result == 'success' && github.event_name != 'pull_request' && fromJSON(steps.coverage.outputs.percent) < 90
uses: ./.github/actions/vsp-github-actions/slack-socket
with:
slack_app_token: ${{ env.SLACK_APP_TOKEN }}
slack_bot_token: ${{ env.SLACK_BOT_TOKEN }}
message: "Critical: Vets-API Testing Coverage Below 90% - Deployment Blocked"
blocks: |
[
{ "type": "divider" },
{
"type": "header",
"text": {
"type": "plain_text",
"text": ":rotating_light: CRITICAL: Test Coverage Too Low",
"emoji": true
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Vets-API deployment is BLOCKED until coverage reaches 90%*"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": ":chart_with_downwards_trend: *Current Coverage*: ${{ steps.coverage.outputs.percent }}%"
},
{
"type": "mrkdwn",
"text": ":dart: *Required Minimum*: 90%"
},
{
"type": "mrkdwn",
"text": ":x: *Status*: Deployment Blocked"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":bust_in_silhouette: *Author:* ${{ github.actor }}"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": ":mag_right: View Test Run",
"emoji": true
},
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"style": "danger"
}
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": ":bulb: *View detailed coverage:* <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|Open test run> → Scroll to *Artifacts* → Download *Coverage Report* → Open *index.html*"
}
]
},
{ "type": "divider" }
]
channel_id: "C0APA867M0V"
- name: Slack notify - warning low coverage alert
if: needs.tests.result == 'success' && github.event_name != 'pull_request' && fromJSON(steps.coverage.outputs.percent) >= 90 && fromJSON(steps.coverage.outputs.percent) < 93
uses: ./.github/actions/vsp-github-actions/slack-socket
with:
slack_app_token: ${{ env.SLACK_APP_TOKEN }}
slack_bot_token: ${{ env.SLACK_BOT_TOKEN }}
message: "Warning: Vets-API Testing Coverage Below 93%"
blocks: |
[
{ "type": "divider" },
{
"type": "header",
"text": {
"type": "plain_text",
"text": ":warning: Warning: Vets-API Coverage Below Target",
"emoji": true
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": ":chart_with_downwards_trend: *Current Coverage*: ${{ steps.coverage.outputs.percent }}%"
},
{
"type": "mrkdwn",
"text": ":dart: *Required Minimum*: 90%"
},
{
"type": "mrkdwn",
"text": ":large_green_circle: *Status*: Deployment Allowed"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":bust_in_silhouette: *Author:* ${{ github.actor }}"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": ":mag_right: View Test Run",
"emoji": true
},
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"style": "danger"
}
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": ":bulb: *View detailed coverage:* <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|Open test run> → Scroll to *Artifacts* → Download *Coverage Report* → Open *index.html*"
}
]
},
{ "type": "divider" }
]
channel_id: "C0APA867M0V"
- name: Comment Coverage on PR
if: needs.tests.result == 'success' && github.event_name == 'pull_request' && fromJSON(steps.coverage.outputs.percent) < 90
uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 # v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: coverage
message: |
## :x: Critical: Test Coverage Too Low
**Coverage:** ${{ steps.coverage.outputs.percent }}%
Your test coverage is **below the required minimum of 90%**.
Please add additional tests before this PR can be considered for merge.
Once coverage is improved, push another commit or rerun the workflow to update this report.
**View detailed coverage:** [Open test run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) → Scroll to **Artifacts** → Download **Coverage Report** → Open **index.html**
- name: Comment Coverage on PR
if: needs.tests.result == 'success' && github.event_name == 'pull_request' && fromJSON(steps.coverage.outputs.percent) >= 90 && fromJSON(steps.coverage.outputs.percent) < 93
uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 # v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: coverage
message: |
## :warning: Warning: Low Coverage Report
**Coverage:** ${{ steps.coverage.outputs.percent }}%
Please add or expand tests to improve coverage before merging.
**View detailed coverage:** [Open test run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) → Scroll to **Artifacts** → Download **Coverage Report** → Open **index.html**
- name: Remove coverage comment when coverage is healthy
if: needs.tests.result == 'success' && github.event_name == 'pull_request' && fromJSON(steps.coverage.outputs.percent) >= 93
uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 # v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: coverage
delete: true