diff --git a/.github/workflows/code-metrics.yml b/.github/workflows/code-metrics.yml new file mode 100644 index 000000000..5dbeded6c --- /dev/null +++ b/.github/workflows/code-metrics.yml @@ -0,0 +1,160 @@ +name: Code Metrics + +on: + # manual trigger + workflow_dispatch: + # scheduled trigger: every 2 weeks on Wednesday at 23:59 + schedule: + - cron: '59 23 * * 3/2' + +jobs: + count-lines-and-coverage: + runs-on: ubuntu-latest + + steps: + - name: Set Trigger Environment Variable + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "MANUALLY_TRIGGERED=true" >> $GITHUB_ENV + else + echo "MANUALLY_TRIGGERED=false" >> $GITHUB_ENV + fi + + # notify: Nicholas and Nileena using their Slack IDs + - name: Set Slack users to notify if this is a scheduled run + if: env.MANUALLY_TRIGGERED == 'false' + run: | + echo "SLACK_USERS=<@U017GV0LRAR> <@UKQ250V26>" >> $GITHUB_ENV + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Count lines of code + id: linecount + run: | + # Install cloc if not already installed + sudo apt-get update && sudo apt-get install -y cloc + + # Run cloc at the HEAD of the repository and capture JSON output + echo "Running cloc at HEAD..." + cloc --exclude-dir=node_modules,.git --json . > cloc_output.json + + # Install jq if not already installed + sudo apt-get install -y jq + + # Get total lines of code + TOTAL_LINES=$(jq -r '.SUM.code' cloc_output.json) + echo "TOTAL_LINES=$TOTAL_LINES" >> $GITHUB_ENV + + # Transform the JSON to the subset format for Slack + cat < transform.jq + { + "header": { + "number of files": .SUM.nFiles, + "number of lines": (.SUM.blank + .SUM.comment + .SUM.code) + }, + "XML": { + "number of Files": .XML.nFiles, + "code": .XML.code + }, + "JSON": { + "number of Files": .JSON.nFiles, + "code": .JSON.code + }, + "Java": { + "number of Files": .Java.nFiles, + "code": .Java.code + }, + "Maven": { + "number of Files": .Maven.nFiles, + "code": .Maven.code + }, + "YAML": { + "number of Files": .YAML.nFiles, + "code": .YAML.code + }, + "Markdown": { + "number of Files": .Markdown.nFiles, + "code": .Markdown.code + }, + "Cucumber": { + "number of Files": .Cucumber.nFiles, + "code": .Cucumber.code + }, + "Bourne Shell": { + "number of Files": ."Bourne Shell".nFiles, + "code": ."Bourne Shell".code + }, + "Python": { + "number of Files": .Python.nFiles, + "code": .Python.code + }, + "TOML": { + "number of Files": .TOML.nFiles, + "code": .TOML.code + }, + "Dockerfile": { + "number of Files": .Dockerfile.nFiles, + "code": .Dockerfile.code + }, + "Text": { + "number of Files": .Text.nFiles, + "code": .Text.code + }, + "Properties": { + "number of Files": .Properties.nFiles, + "code": .Properties.code + }, + "SUM": { + "blank": .SUM.blank, + "number of Files": .SUM.nFiles + } + } + EOF + + # Apply the transformation + jq -f transform.jq cloc_output.json > cloc_subset.json + + # Create a more readable format for the Slack message + echo "CLOC_JSON<> $GITHUB_ENV + cat cloc_subset.json >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + echo "Total lines of code: $TOTAL_LINES" + + # Display full cloc summary for debugging and information + echo "Full cloc JSON summary:" + cat cloc_output.json + + echo "Subset cloc JSON summary:" + cat cloc_subset.json + + - name: Format cloc data for Slack + run: | + # Get the values we need + FILES=$(jq -r '.header."number of files"' cloc_subset.json) + LINES=$(jq -r '.header."number of lines"' cloc_subset.json) + + # Create the breakdown text + BREAKDOWN=$(jq -r 'to_entries | sort_by(-(.value.code // 0)) | + map(select(.key != "header" and .key != "SUM")) | + map("• \(.key): \(.value.code // 0) lines in \(.value."number of Files" // 0) files") | + join("\\n")' cloc_subset.json) + + # Create the complete message + echo "CODE_METRICS_SUMMARY=*Code Metrics Summary*\\nTotal files: $FILES\\nTotal lines: $LINES\\n\\n*Language breakdown:*\\n$BREAKDOWN" >> $GITHUB_ENV + + - name: Slack notification + if: always() + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_QPPSF_ALERTS_WEBHOOK }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + uses: slackapi/slack-github-action@v1 + with: + payload: | + { + "text": "*Conversion Tool Code Metrics*\n\n${{ env.CODE_METRICS_SUMMARY }}\n\nTotal lines of code: ${{ env.TOTAL_LINES }}\n${{ env.SLACK_USERS }}" + } + # Continue even if Slack notification fails + continue-on-error: true + diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml new file mode 100644 index 000000000..9d67a0809 --- /dev/null +++ b/.github/workflows/sonarqube.yml @@ -0,0 +1,46 @@ +name: SonarQube Analysis (Java) + +on: + pull_request: + types: [opened, synchronize, reopened, closed] + branches: + - develop + +env: + PROJECT_NAME: qppa-repos-sonarqube-analysis + +jobs: + build: + name: Java Quality Gate + permissions: + id-token: write + contents: read + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + # 1) Check out the repository + - uses: actions/checkout@v2 + + # 2) Print the PR’s head‐branch + - name: Print branch name + run: | + echo "Current branch: ${GITHUB_HEAD_REF}" + + + # 3) Configure AWS credentials + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: arn:aws:iam::730335206644:role/delegatedadmin/developer/qppa-github-actions-role + aws-region: us-east-1 + + # 4) Kick off the CodeBuild project, passing the repo name into GITHUB_REPO_NAME + - name: Trigger CodeBuild SonarQube Scan + run: | + aws codebuild start-build \ + --project-name "${PROJECT_NAME}" \ + --source-type-override "GITHUB" \ + --source-location-override "${{ github.event.repository.html_url }}" \ + --source-version "${GITHUB_HEAD_REF}" \ + --environment-variables-override name=GITHUB_REPO_NAME,value="${{ github.event.repository.name }}",type=PLAINTEXT diff --git a/README.md b/README.md index 61aa15f14..d94d6d4e3 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ directory. ```shell # Build the Docker image and run the container using docker-compose. -docker-compose -f ./docker-compose.test.yaml up --build +docker compose -f ./docker-compose.test.yaml up --build ``` #### Invoking the Endpoint diff --git a/acceptance-tests/pom.xml b/acceptance-tests/pom.xml index 0b6a6303b..99f3089ca 100644 --- a/acceptance-tests/pom.xml +++ b/acceptance-tests/pom.xml @@ -3,7 +3,7 @@ 4.0.0 acceptance-tests gov.cms.qpp.conversion - 2024.2.12-RELEASE + 2024.2.13-RELEASE conversion-tests jar diff --git a/commandline/pom.xml b/commandline/pom.xml index 432bc8d69..8bff815e1 100644 --- a/commandline/pom.xml +++ b/commandline/pom.xml @@ -6,7 +6,7 @@ gov.cms.qpp.conversion qpp-conversion-tool-parent - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../pom.xml diff --git a/commons/pom.xml b/commons/pom.xml index 1120efd4c..120807f2e 100644 --- a/commons/pom.xml +++ b/commons/pom.xml @@ -6,7 +6,7 @@ gov.cms.qpp.conversion qpp-conversion-tool-parent - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../pom.xml diff --git a/commons/src/main/resources/measures-data.json b/commons/src/main/resources/measures-data.json index 5d4318200..5db57ff91 100644 --- a/commons/src/main/resources/measures-data.json +++ b/commons/src/main/resources/measures-data.json @@ -3585,7 +3585,7 @@ "reportingCategory": "required", "substitutes": [], "measureSpecification": { - "default": "https://qpp.cms.gov/docs/pi_specifications/Measure Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting.pdf" + "default": "https://qpp.cms.gov/docs/pi_specifications/Measure%20Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting-Updated-April-2025.pdf" }, "measureSets": [], "exclusion": [ @@ -3648,7 +3648,7 @@ "PI_PHCDRR_3_EX_3" ], "measureSpecification": { - "default": "https://qpp.cms.gov/docs/pi_specifications/Measure Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting.pdf" + "default": "https://qpp.cms.gov/docs/pi_specifications/Measure%20Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting-Updated-April-2025.pdf" }, "measureSets": [], "exclusion": null, @@ -3704,7 +3704,7 @@ "PI_PHCDRR_3_EX_3" ], "measureSpecification": { - "default": "https://qpp.cms.gov/docs/pi_specifications/Measure Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting.pdf" + "default": "https://qpp.cms.gov/docs/pi_specifications/Measure%20Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting-Updated-April-2025.pdf" }, "measureSets": [], "exclusion": null, @@ -3760,7 +3760,7 @@ "PI_PHCDRR_3_EX_2" ], "measureSpecification": { - "default": "https://qpp.cms.gov/docs/pi_specifications/Measure Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting.pdf" + "default": "https://qpp.cms.gov/docs/pi_specifications/Measure%20Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting-Updated-April-2025.pdf" }, "measureSets": [], "exclusion": null, @@ -4385,7 +4385,7 @@ "M1425" ], "measureSpecification": { - "default": "https://qpp.cms.gov/docs/pi_specifications/Measure Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting.pdf" + "default": "https://qpp.cms.gov/docs/pi_specifications/Measure%20Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting-Updated-April-2025.pdf" }, "allowedRegistrationTypes": [ "apm", @@ -4439,7 +4439,7 @@ "M1425" ], "measureSpecification": { - "default": "https://qpp.cms.gov/docs/pi_specifications/Measure Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting.pdf" + "default": "https://qpp.cms.gov/docs/pi_specifications/Measure%20Specifications/2025-MIPS-Promoting-Interoperability-Measure-Electronic-Case-Reporting-Updated-April-2025.pdf" }, "allowedRegistrationTypes": [ "apm", @@ -11136,7 +11136,7 @@ "pediatrics" ], "measureSpecification": { - "registry": "https://qpp.cms.gov/docs/QPP_quality_measure_specifications/CQM-Measures/2024_Measure_394_MIPSCQM.pdf" + "registry": "https://qpp.cms.gov/docs/QPP_quality_measure_specifications/CQM-Measures/2025_Measure_394_MIPSCQM.pdf" }, "overallAlgorithm": "overallStratumOnly", "strata": [ diff --git a/converter/pom.xml b/converter/pom.xml index 8876aa66a..2c10ccf2e 100644 --- a/converter/pom.xml +++ b/converter/pom.xml @@ -6,7 +6,7 @@ gov.cms.qpp.conversion qpp-conversion-tool-parent - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../pom.xml @@ -170,7 +170,7 @@ gov.cms.qpp.conversion commons - 2024.2.12-RELEASE + 2024.2.13-RELEASE compile diff --git a/generate-race-cpcplus/pom.xml b/generate-race-cpcplus/pom.xml index af29cf844..e71b5f0b9 100644 --- a/generate-race-cpcplus/pom.xml +++ b/generate-race-cpcplus/pom.xml @@ -5,7 +5,7 @@ qpp-conversion-tool-parent gov.cms.qpp.conversion - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../ 4.0.0 diff --git a/generate/pom.xml b/generate/pom.xml index d27e25bf9..ff3fcd3c0 100644 --- a/generate/pom.xml +++ b/generate/pom.xml @@ -5,7 +5,7 @@ qpp-conversion-tool-parent gov.cms.qpp.conversion - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 7cc9dac31..76f77e795 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ gov.cms.qpp.conversion qpp-conversion-tool-parent pom - 2024.2.12-RELEASE + 2024.2.13-RELEASE QPP Conversion Tool diff --git a/qrda3-update-measures/pom.xml b/qrda3-update-measures/pom.xml index a2cdf3877..fc57a7295 100644 --- a/qrda3-update-measures/pom.xml +++ b/qrda3-update-measures/pom.xml @@ -3,7 +3,7 @@ qpp-conversion-tool-parent gov.cms.qpp.conversion - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../ diff --git a/rest-api/pom.xml b/rest-api/pom.xml index 0aa660c98..06ccfa129 100644 --- a/rest-api/pom.xml +++ b/rest-api/pom.xml @@ -6,7 +6,7 @@ gov.cms.qpp.conversion qpp-conversion-tool-parent - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../pom.xml diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 000000000..72c070be4 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,86 @@ +# SonarQube Project Configuration for QPP Conversion Tool + +# ----------------------------------------------------------------------------- +# Project Metadata +# ----------------------------------------------------------------------------- +sonar.organization=cmsgov +sonar.projectKey=qpp-conversion-tool +sonar.projectName=qpp-conversion-tool +sonar.projectVersion=1.0 + +# ----------------------------------------------------------------------------- +# Quality Gate & SCM Integration +# ----------------------------------------------------------------------------- +# Wait for the quality gate result before finishing the scan +sonar.qualitygate.wait=true +# Use Git to detect changed files and SCM information +sonar.scm.provider=git + +# Disable automatic CI configuration detection (SonarCloud) +sonar.ci.autoconfig.disabled=true + +# ----------------------------------------------------------------------------- +# Source Code Encoding +# ----------------------------------------------------------------------------- +sonar.sourceEncoding=UTF-8 + +# ----------------------------------------------------------------------------- +# Source and Test Locations (All Maven Modules) +# ----------------------------------------------------------------------------- +# List of source directories to analyze +sonar.sources=\ + commons/src/main/java,\ + converter/src/main/java,\ + commandline/src/main/java,\ + rest-api/src/main/java,\ + generate/src/main/java + +# List of test directories to analyze +sonar.tests=\ + commons/src/test/java,\ + converter/src/test/java,\ + commandline/src/test/java,\ + rest-api/src/test/java,\ + generate/src/test/java + +# ----------------------------------------------------------------------------- +# Compiled Class Locations (All Maven Modules) +# ----------------------------------------------------------------------------- +# Paths to compiled bytecode for main sources +sonar.java.binaries=\ + commons/target/classes,\ + converter/target/classes,\ + commandline/target/classes,\ + rest-api/target/classes,\ + generate/target/classes + +# Paths to compiled bytecode for test sources +sonar.java.test.binaries=\ + commons/target/test-classes,\ + converter/target/test-classes,\ + commandline/target/test-classes,\ + rest-api/target/test-classes,\ + generate/target/test-classes + +# ----------------------------------------------------------------------------- +# Code Coverage and Test Reports +# ----------------------------------------------------------------------------- +# JaCoCo aggregate coverage report (from test-coverage module) +sonar.coverage.jacoco.xmlReportPaths=\ + test-coverage/target/site/jacoco-aggregate/jacoco.xml + +# JUnit test report directories for each module +sonar.junit.reportPaths=\ + commons/target/surefire-reports,\ + converter/target/surefire-reports,\ + commandline/target/surefire-reports,\ + rest-api/target/surefire-reports,\ + generate/target/surefire-reports + +# ----------------------------------------------------------------------------- +# File Exclusions +# ----------------------------------------------------------------------------- +# Exclude build artifacts and generated code +sonar.exclusions=\ + **/target/**,\ + **/*.generated.java diff --git a/test-commons/pom.xml b/test-commons/pom.xml index 88ce31d5a..4f82fd9f4 100644 --- a/test-commons/pom.xml +++ b/test-commons/pom.xml @@ -6,7 +6,7 @@ gov.cms.qpp.conversion qpp-conversion-tool-parent - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../pom.xml diff --git a/test-coverage/pom.xml b/test-coverage/pom.xml index dd76aa1cb..2c79e9188 100644 --- a/test-coverage/pom.xml +++ b/test-coverage/pom.xml @@ -6,7 +6,7 @@ gov.cms.qpp.conversion qpp-conversion-tool-parent - 2024.2.12-RELEASE + 2024.2.13-RELEASE ../pom.xml