Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 31 additions & 1 deletion .github/workflows/lint-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ jobs:
node-version: [20.x, 22.x, 24.x]
outputs:
child-workspace-package-names: ${{ steps.workspace-package-names.outputs.child-workspace-package-names }}
child-workspace-package-directories: ${{ steps.workspace-package-names.outputs.child-workspace-package-directories }}
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
Expand All @@ -103,7 +104,9 @@ jobs:
- name: Fetch workspace package names
id: workspace-package-names
run: |
echo "child-workspace-package-names=$(yarn workspaces list --no-private --json | jq --slurp --raw-output 'map(.name) | @json')" >> "$GITHUB_OUTPUT"
workspaces="$(yarn workspaces list --no-private --json)"
echo "child-workspace-package-names=$(echo "$workspaces" | jq --slurp --raw-output 'map(.name) | @json')" >> "$GITHUB_OUTPUT"
echo "child-workspace-package-directories=$(echo "$workspaces" | jq --slurp --raw-output 'map(.location | sub("^packages/"; "")) | @json')" >> "$GITHUB_OUTPUT"
shell: bash

lint:
Expand Down Expand Up @@ -215,6 +218,7 @@ jobs:
matrix:
node-version: [20.x, 22.x]
package-name: ${{ fromJson(needs.prepare.outputs.child-workspace-package-names) }}
package-directory: ${{ fromJson(needs.prepare.outputs.child-workspace-package-directories) }}
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
Expand All @@ -227,5 +231,31 @@ jobs:
name: package-dist-${{ github.sha }}
path: packages
- run: yarn workspace ${{ matrix.package-name }} run test
- name: Prepare coverage for SonarCloud
# Only one Node version uploads coverage so lcov files are not merged
# across runs. Jest writes "SF:" paths relative to the package, but
# SonarCloud resolves them against the repo root, so prefix them with
# the package directory.
if: matrix.node-version == '22.x'
env:
PACKAGE_DIRECTORY: ${{ matrix.package-directory }}
run: |
lcov_file="packages/${PACKAGE_DIRECTORY}/coverage/lcov.info"
if [ -f "$lcov_file" ]; then
sed -i.bak "s|^SF:|SF:packages/${PACKAGE_DIRECTORY}/|" "$lcov_file"
rm "$lcov_file.bak"
else
echo "No coverage report found at $lcov_file"
fi
shell: bash
- name: Upload coverage artifact
if: matrix.node-version == '22.x'
# This is actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: coverage-${{ matrix.package-directory }}
path: packages/${{ matrix.package-directory }}/coverage/lcov.info
if-no-files-found: ignore
retention-days: 1
- name: Require clean working directory
uses: ./.github/actions/require-clean-working-directory
26 changes: 26 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,32 @@ jobs:
STELLAR_RPC_URL_TESTNET: ${{ secrets.STELLAR_RPC_URL_TESTNET }}
STELLAR_HORIZON_URL_TESTNET: ${{ secrets.STELLAR_HORIZON_URL_TESTNET }}

sonarcloud:
name: SonarCloud
needs: lint-build-test
# Run on same-repo PRs and pushes to main. Skip merge queue commits (the PR
# was already scanned) and forks (no SONAR_TOKEN available). Not part of
# all-jobs-complete yet so a SonarCloud outage cannot block merges.
if: >-
${{
!cancelled() &&
needs.lint-build-test.result == 'success' &&
!github.event.repository.fork &&
(
(github.event_name == 'push' && github.ref_name == 'main') ||
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
)
}}
uses: ./.github/workflows/sonarcloud.yml
# The reusable workflow's job requests these scopes; a `uses:` caller must
# explicitly grant them or the workflow fails at startup.
permissions:
contents: read
pull-requests: write
checks: write
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

check-release:
name: Check release
needs: check-workflows
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: SonarCloud

on:
workflow_call:
secrets:
SONAR_TOKEN:
description: SonarCloud token
required: true

jobs:
sonarcloud-scan:
name: SonarCloud scan
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
checks: write
steps:
- name: Checkout and setup environment
# This is MetaMask/action-checkout-and-setup@v3
uses: MetaMask/action-checkout-and-setup@0543b5929698c71e3ccc6ed24eac87825669b5de
with:
is-high-risk-environment: false
# SonarCloud needs the full history for new-code and blame data
fetch-depth: 0

- name: Download coverage artifacts
# This is actions/download-artifact@v7
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131
with:
pattern: coverage-*
path: .coverage-artifacts

- name: Arrange coverage for SonarCloud
# Single-file artifact uploads do not preserve the source directory,
# and each artifact downloads into .coverage-artifacts/coverage-<dir>/.
# Move each lcov back to packages/<dir>/coverage/lcov.info to match
# sonar.javascript.lcov.reportPaths.
run: |
for dir in .coverage-artifacts/coverage-*/; do
pkg="${dir##*/coverage-}"
pkg="${pkg%/}"
if [ -f "${dir}lcov.info" ]; then
mkdir -p "packages/${pkg}/coverage"
mv "${dir}lcov.info" "packages/${pkg}/coverage/lcov.info"
fi
done
ls packages/*/coverage/lcov.info
shell: bash

- name: SonarCloud scan
# This is SonarSource/sonarqube-scan-action@v7.1.0
uses: SonarSource/sonarqube-scan-action@299e4b793aaa83bf2aba7c9c14bedbb485688ec4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
2 changes: 1 addition & 1 deletion packages/stellar-wallet-snap/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/
const config = {
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: false,
collectCoverage: true,

// An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: ['./src/**/*.ts', './src/**/*.tsx'],
Expand Down
31 changes: 31 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Note: Updating this file on feature branches or forks will not reflect changes in the SonarCloud scan results.
# The SonarCloud scan workflow always uses the latest version from the default branch.
# This means any changes made to this file in a feature branch will not be considered until they are merged.

sonar.projectKey=MetaMask_internal-snaps
sonar.organization=metamask

# Source
# This is a monorepo: a single SonarCloud project covers every snap under
# packages/, so new packages are analyzed without changes to this file.
sonar.sources=packages

# Exclude tests, build artifacts and assets from all analysis (to avoid code
# coverage, duplicate code, security issues, etc. being reported on them).
# sample-snap is a private hello-world package that is not part of the CI test
# matrix, so it is excluded from analysis.
sonar.exclusions=**/sample-snap/**,**/*.test.**,**/*.spec.**,**/dist/**,**/coverage/**,**/images/**,**/*.snap,**/__snapshots__/**,**/__mocks__/**

# Tests
sonar.tests=packages
sonar.test.inclusions=**/*.test.**,**/*.spec.**

# Jest writes lcov per package during CI (packages/<name>/coverage/lcov.info).
# The scan job rewrites the "SF:" paths to be relative to the repo root before
# uploading, so a single glob covers all packages.
sonar.javascript.lcov.reportPaths=packages/*/coverage/lcov.info

# Fail CI job if quality gate failures.
# Kept false during rollout: the gate is enforced by a dedicated CI job once
# the main branch baseline exists.
sonar.qualitygate.wait=false