Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci(MM-63199): code coverage tracking #8642

Draft
wants to merge 74 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
aa4693b
ci(MM-63199): code coverage tracking
rahimrahman Feb 28, 2025
05847ce
try to download existing coverage file
rahimrahman Feb 28, 2025
ece130b
read coverage
rahimrahman Feb 28, 2025
137bee6
add token
rahimrahman Feb 28, 2025
88fdcc5
use github.token instead
rahimrahman Mar 1, 2025
22b2320
passing github token
rahimrahman Mar 1, 2025
12013da
github_token passing from workflow
rahimrahman Mar 1, 2025
6f4bc8e
remove download
rahimrahman Mar 1, 2025
a805c7f
re-add download
rahimrahman Mar 1, 2025
9040a95
wrong param
rahimrahman Mar 1, 2025
594bf0d
try download all artifacts
rahimrahman Mar 1, 2025
c67a2b1
add run-id so to retrieve with download later
rahimrahman Mar 10, 2025
2a77069
remove read coverage temp
rahimrahman Mar 10, 2025
0f02944
use run-id to download
rahimrahman Mar 10, 2025
74ed15f
put files into current-coverage
rahimrahman Mar 10, 2025
0a2e7f4
using last run id
rahimrahman Mar 10, 2025
362b3e0
temporary comment
rahimrahman Mar 10, 2025
4392803
can retrieve last run id?
rahimrahman Mar 10, 2025
680cf03
remove hard-coding
rahimrahman Mar 10, 2025
1f7237c
echo into github_env vs export
rahimrahman Mar 10, 2025
bda32c8
comparing new and old
rahimrahman Mar 10, 2025
deeb5a3
comparison improvement
rahimrahman Mar 10, 2025
81d3396
post to github
rahimrahman Mar 10, 2025
efa86a6
fix coverage text
rahimrahman Mar 10, 2025
a211c78
refactor to main from current-coverage
rahimrahman Mar 10, 2025
80c5ef0
formatting changes
rahimrahman Mar 10, 2025
e100fe0
fix missing content
rahimrahman Mar 10, 2025
f8ee286
small tweaking
rahimrahman Mar 10, 2025
68203a8
showing the Warning to make sure
rahimrahman Mar 10, 2025
f6a7678
formatting
rahimrahman Mar 10, 2025
1216620
remove +
rahimrahman Mar 10, 2025
3875f75
checking to see if the error shows via echo
rahimrahman Mar 10, 2025
45de653
revert the change to error
rahimrahman Mar 11, 2025
eef2593
separate to a new file
rahimrahman Mar 11, 2025
69c394d
comment the actual test for now
rahimrahman Mar 11, 2025
7da6cc7
prep node deps
rahimrahman Mar 11, 2025
2319e3c
only run certain things on main
rahimrahman Mar 11, 2025
86e573c
trying cache-hit
rahimrahman Mar 11, 2025
2375276
real trying cache-hit
rahimrahman Mar 11, 2025
55f1c08
testing to make sure cache-run-id runs
rahimrahman Mar 11, 2025
c2ef265
save-always true
rahimrahman Mar 11, 2025
6a7fa05
save-always deprecated
rahimrahman Mar 11, 2025
e2f5d19
let's try different strategy
rahimrahman Mar 11, 2025
3fe2f16
add key
rahimrahman Mar 11, 2025
9e2631b
restore-key adding a -
rahimrahman Mar 11, 2025
5d6a287
only perform on `main`
rahimrahman Mar 11, 2025
22fc24e
only run on main or if its a PR
rahimrahman Mar 11, 2025
aecc5b6
coverage_threshold
rahimrahman Mar 12, 2025
47992ea
remove comments
rahimrahman Mar 12, 2025
a38547b
add total
rahimrahman Mar 12, 2025
fb1088b
removing unneeded comments
rahimrahman Mar 12, 2025
199d8f6
calculate total
rahimrahman Mar 12, 2025
5095eae
run test in `release-*` only
rahimrahman Mar 12, 2025
957bd6c
making sure that only PR will run
rahimrahman Mar 12, 2025
4ad4846
only do more steps if upload-coverage successful
rahimrahman Mar 12, 2025
2398d58
trying thollander/actions-comment-pull-request
rahimrahman Mar 12, 2025
100e2ef
using diff way to comment.
rahimrahman Mar 12, 2025
893ea66
comment on how things work
rahimrahman Mar 12, 2025
62bb5a2
testing to trigger warning and see if comment is updated vs new comment
rahimrahman Mar 12, 2025
90a801c
omit echo messages
rahimrahman Mar 12, 2025
3732bd2
see if giving github token would work.
rahimrahman Mar 12, 2025
6e84d9d
wrong use of param
rahimrahman Mar 12, 2025
f1cd18e
try without github token
rahimrahman Mar 12, 2025
3645d88
adding a very simple change to see where it lands
rahimrahman Mar 12, 2025
9f625b3
using cache hit instead.
rahimrahman Mar 12, 2025
67e525e
creating the cache again. how did i lose it?
rahimrahman Mar 12, 2025
d432757
revert back
rahimrahman Mar 12, 2025
4439acb
cache-hit might be off
rahimrahman Mar 13, 2025
7ccc8d3
debug
rahimrahman Mar 13, 2025
b12812b
debug with failing cache restoration
rahimrahman Mar 13, 2025
a6da722
check for run-id.txt instead
rahimrahman Mar 13, 2025
bdf48f2
all into action
rahimrahman Mar 13, 2025
a2f0e1c
missing "
rahimrahman Mar 13, 2025
1a31efc
remove unneeded actions
rahimrahman Mar 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions .github/actions/test-coverage/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# This action is used to test the coverage of the mobile repo
# It will download the coverage result from the main branch and compare it with the current branch
# If the coverage is lower than the main branch (1% or more), it will post a warning along with
# the coverage report to the PR.
# If this action is run on the main branch, it will upload the coverage result to the main branch
# It will also generate a run id and cache it, so that the next time the action is run in the PR,
# it will use the cached run id to download the coverage result from the main branch

name: test-coverage
description: Test coverage tracking for mobile repo

inputs:
github_token:
description: The token to use to download the coverage result
required: true
run_id:
description: The run id to use to download the coverage result
required: true

runs:
using: composite
steps:
- name: ci/prepare-node-deps
uses: ./.github/actions/prepare-node-deps

- name: ci/get-last-run-id
if: github.event_name == 'pull_request'
id: get-last-run-id
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f
continue-on-error: true
with:
path: run-id.txt
key: last-run-id-${{ inputs.run_id }}
restore-keys: |
last-run-id-

- name: ci/set-pr-condition
if: github.event_name == 'pull_request'
shell: bash
run: |
echo "::group::set-pr-condition"
if [ -f "run-id.txt" ]; then
echo "IS_PR_WITH_CACHE=true" >> $GITHUB_ENV
echo "LAST_RUN_ID=$(cat run-id.txt)" >> $GITHUB_ENV
fi
echo "::endgroup::"

- name: ci/download-main-coverage
if: env.IS_PR_WITH_CACHE == 'true'
uses: actions/download-artifact@v4
with:
name: test-coverage-result-${{ env.LAST_RUN_ID }}
path: main-coverage/
github-token: ${{ inputs.github_token }}
run-id: ${{ env.LAST_RUN_ID }}

- name: ci/read-coverage
if: env.IS_PR_WITH_CACHE == 'true'
shell: bash
run: |
echo "::group::read-coverage"
./scripts/read-coverage.sh ./main-coverage/coverage-summary.json
echo "::endgroup::"

- name: ci/run-tests-with-coverage
shell: bash
run: |
echo "::group::run-tests"
npm run test:coverage
echo "::endgroup::"

- name: ci/compare-coverage
if: env.IS_PR_WITH_CACHE == 'true'
id: compare-coverage
shell: bash
run: |
echo "::group::compare-coverage"
output=$(./scripts/compare-coverage.sh \
./main-coverage \
./coverage \
${{ github.event.pull_request.number }} \
${{ inputs.github_token }})
echo "report<<EOF" >> $GITHUB_ENV
echo "$output" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "::endgroup::"

- name: Post coverage report
if: env.IS_PR_WITH_CACHE == 'true'
uses: thollander/actions-comment-pull-request@v3
with:
message: ${{ env.report }}
comment-tag: coverage-report
# github-token: ${{ inputs.github_token }}
create-if-not-exists: true

- name: ci/upload-coverage
if: github.ref_name == 'main'
id: upload-coverage
uses: actions/upload-artifact@v4
with:
name: test-coverage-result-${{ inputs.run_id }}
path: coverage/coverage-summary.json
overwrite: true

- name: Set upload success
if: github.ref_name == 'main' && steps.upload-coverage.outcome == 'success'
shell: bash
run: echo "UPLOAD_SUCCESS=true" >> $GITHUB_ENV

- name: ci/generate-run-id-file
if: env.UPLOAD_SUCCESS == 'true'
shell: bash
run: |
echo "::group::generate-last-run-id"
echo "${{ inputs.run_id }}" > run-id.txt
echo "::endgroup::"

- name: ci/cache-run-id-file
if: env.UPLOAD_SUCCESS == 'true'
uses: actions/cache/save@0c907a75c2c80ebcb7f088228285e798b750cf8f
with:
path: run-id.txt
key: last-run-id-${{ inputs.run_id }}
4 changes: 4 additions & 0 deletions .github/actions/test/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ runs:
echo "::group::check-styles"
npm run check
echo "::endgroup::"

- name: ci/run-tests
# main and PR will run test:coverage
if: startsWith(github.ref_name, 'release-')
shell: bash
run: |
echo "::group::run-tests"
npm test
echo "::endgroup::"

- name: ci/check-i18n
shell: bash
run: |
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: ci/test
uses: ./.github/actions/test
- name: ci/test-coverage
if: github.event_name == 'pull_request' || github.ref_name == 'main'
uses: ./.github/actions/test-coverage
with:
github_token: ${{ secrets.MM_MOBILE_GITHUB_TOKEN }}
run_id: ${{ github.run_id }}
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = {
clearMocks: true,
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
collectCoverageFrom: ['app/**/*.{js,jsx,ts,tsx}'],
coverageReporters: ['lcov', 'text-summary'],
coverageReporters: ['lcov', 'text-summary', 'json-summary'],
testPathIgnorePatterns: ['/node_modules/'],
coveragePathIgnorePatterns: ['/node_modules/', '/components/', '/screens/'],
transformIgnorePatterns: [
Expand Down
71 changes: 71 additions & 0 deletions scripts/compare-coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/bin/bash

COVERAGE_THRESHOLD=0.5
MAIN_COVERAGE_FILE="$1/coverage-summary.json"
RECENT_COVERAGE_FILE="$2/coverage-summary.json"
PR_NUMBER="$3"
GITHUB_TOKEN="$4"

if [ ! -f "$MAIN_COVERAGE_FILE" ] || [ ! -f "$RECENT_COVERAGE_FILE" ]; then
echo "One or both coverage files not found"
exit 0
fi

COMMENT_BODY="### Coverage Comparison Report

\`\`\`
+-----------------+------------+------------+-----------+
| Metric | Main | This PR | Diff |
+-----------------+------------+------------+-----------+"

HAS_DECREASE=0

# Initialize variables for calculating average total coverage
# since the coverage summary doesn't provide an overall total
main_total=0
pr_total=0
metric_count=0

for metric in lines statements branches functions; do
main=$(jq ".total.${metric}.pct" "$MAIN_COVERAGE_FILE")
pr=$(jq ".total.${metric}.pct" "$RECENT_COVERAGE_FILE")
diff=$(echo "$pr - $main" | bc)

# Add to totals for average calculation
main_total=$(echo "$main_total + $main" | bc)
pr_total=$(echo "$pr_total + $pr" | bc)
metric_count=$((metric_count + 1))

row=$(printf "| %-15s | %9.2f%% | %9.2f%% | %8.2f%% |" "${metric^}" "$main" "$pr" "$diff")
COMMENT_BODY+=$'\n'"$row"

if (( $(echo "$diff > -$COVERAGE_THRESHOLD" | bc -l) )); then
# Write error messages to stderr instead of stdout
echo "::error::${metric^} coverage has decreased by more than ${COVERAGE_THRESHOLD}% ($diff%)" >&2
HAS_DECREASE=1
fi
done

# Add separator line
COMMENT_BODY+=$'\n'"+-----------------+------------+------------+-----------+"

# Calculate the average coverage across all metrics
main_avg=$(echo "scale=2; $main_total / $metric_count" | bc)
pr_avg=$(echo "scale=2; $pr_total / $metric_count" | bc)
total_diff=$(echo "$pr_avg - $main_avg" | bc)

row=$(printf "| %-15s | %9.2f%% | %9.2f%% | %8.2f%% |" "Total" "$main_avg" "$pr_avg" "$total_diff")
COMMENT_BODY+=$'\n'"$row"

COMMENT_BODY+=$'\n'"+-----------------+------------+------------+-----------+
\`\`\`"

if [ "$HAS_DECREASE" -eq 1 ]; then
COMMENT_BODY+=$'\n\n'"⚠️ **Warning:** One or more coverage metrics have decreased by more than ${COVERAGE_THRESHOLD}%"
fi

# Only output the comment body to stdout
echo "$COMMENT_BODY"

# Not failing the build for now
# exit $HAS_DECREASE
37 changes: 37 additions & 0 deletions scripts/read-coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

set -e # Exit on any error

# Check if an argument is provided
if [ -z "$1" ]; then
echo "❌ Error: No coverage file provided."
echo "Usage: $0 <coverage-summary.json>"
exit 1
fi

COVERAGE_FILE="$1"

# Check if the coverage file exists
if [ ! -f "$COVERAGE_FILE" ]; then
echo "❌ Error: Coverage summary file not found: $COVERAGE_FILE"
exit 1
fi

# Extract coverage values from JSON
BRANCHES=$(jq '.total.branches.pct' $COVERAGE_FILE)
FUNCTIONS=$(jq '.total.functions.pct' $COVERAGE_FILE)
LINES=$(jq '.total.lines.pct' $COVERAGE_FILE)
STATEMENTS=$(jq '.total.statements.pct' $COVERAGE_FILE)

# Print extracted values
echo "📊 Extracted Coverage Values:"
echo " - Branches: $BRANCHES%"
echo " - Functions: $FUNCTIONS%"
echo " - Lines: $LINES%"
echo " - Statements: $STATEMENTS%"

# Export values for GitHub Actions (if needed)
echo "BRANCHES=$BRANCHES" >> $GITHUB_ENV
echo "FUNCTIONS=$FUNCTIONS" >> $GITHUB_ENV
echo "LINES=$LINES" >> $GITHUB_ENV
echo "STATEMENTS=$STATEMENTS" >> $GITHUB_ENV