diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 13d72950..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,170 +0,0 @@ -#file: noinspection YAMLSchemaValidation -version: 2.1 - -aliases: - - &environment - working_directory: ~/code - docker: - - image: cimg/android:2024.01 - resource_class: large - -# === Scheduled Pipeline Parameters === -parameters: - nightly-security-scan: - type: boolean - default: false - -jobs: - run-unit-test-and-build: - <<: *environment - steps: - - checkout - - run: - name: Fetch analytics submodule - command: git submodule init && git submodule update - - run: - name: Setup local variables - command: echo "VGS_VAULT_ID=$VGS_VAULT_ID" >> local.properties - - restore_cache: - key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} - - run: - name: Download Dependencies - command: | - sudo chmod +x gradlew - ./gradlew androidDependencies - - save_cache: - paths: - - ~/.gradle - key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} - - run: - name: Run Detekt - command: ./gradlew app:detekt vgsshow:detekt --continue --parallel - - run: - name: Run Unit tests - command: ./gradlew testDebugUnitTest - - run: - name: Generate Code Coverage Report - command: | - if [ "<< pipeline.git.branch >>" == "main" ]; then - ./gradlew koverHtmlReportDebug - else - echo "Code coverage will only be generated on the main branch." - fi - - run: - name: Publish Code Coverage Report - command: | - if [ "<< pipeline.git.branch >>" == "main" ]; then - COVERAGE=$(sed -n '51p' vgsshow/build/reports/kover/htmlDebug/index.html) - METRIC_VALUE=`echo ${COVERAGE//[[:space:]]/} | sed 's/.$//'` - - echo "$METRIC_VALUE" - - curl --fail-with-body \ - --request POST \ - --url https://verygoodsecurity.atlassian.net/gateway/api/compass/v1/metrics \ - --user "$COMPASS_USER_EMAIL:$COMPASS_API_KEY" \ - --header "Accept: application/json" \ - --header "Content-Type: application/json" \ - --data "{\"metricSourceId\":\"$COMPASS_METRIC_SOURCE_ID\",\"value\":\"$METRIC_VALUE\",\"timestamp\":\"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\"}" - else - echo "Code coverage will only be pushed to compass on the main branch." - fi - - run: - name: Generate apk - command: ./gradlew assembleDebug assembleAndroidTest - - persist_to_workspace: - root: ~/code - paths: - - app - run-ui-test: - <<: *environment - steps: - - attach_workspace: - at: ~/code - - run: - name: Check if release branch - command: | - if [[ "<< pipeline.git.branch >>" != *"release"* ]]; then - echo "UI tests should be running only on release branch!" - circleci-agent step halt - fi - - run: - name: Store Google Service Account - command: echo $GCLOUD_SERVICE_KEY | base64 -di > ${HOME}/gcloud-service-key.json - - run: - name: Authorize gcloud and set config defaults - command: | - sudo gcloud auth activate-service-account --key-file=${HOME}/gcloud-service-key.json - sudo gcloud --quiet config set project ${GOOGLE_PROJECT_ID} - - run: - name: Test with Firebase Test Lab - command: > - sudo gcloud firebase test android run \ - --app app/build/outputs/apk/debug/app-debug.apk \ - --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk \ - --device model=caiman,version=35,locale=en,orientation=portrait \ - --device model=bluejay,version=32,locale=en,orientation=portrait \ - scan-sast-pr: - parameters: - default_branch: - type: string - default: main - environment: - SEMGREP_REPO_URL: << pipeline.project.git_url >> - SEMGREP_BRANCH: << pipeline.git.branch >> - SEMGREP_BASELINE_REF: << parameters.default_branch >> - docker: - - image: returntocorp/semgrep - resource_class: large - steps: - - checkout - - run: - name: "Semgrep diff scan" - command: semgrep ci - - scan-sast-full: - parameters: - default_branch: - type: string - default: main - environment: - SEMGREP_REPO_URL: << pipeline.project.git_url >> - SEMGREP_BRANCH: << pipeline.git.branch >> - docker: - - image: returntocorp/semgrep - resource_class: large - steps: - - checkout - - run: - name: "Semgrep full scan" - command: semgrep ci -workflows: - main: - when: - not: << pipeline.parameters.nightly-security-scan >> - jobs: - - scan-sast-pr: - context: - - security-tools - - circleci - - scan-sast-full: - filters: - # ignore any commit on any branch by default - branches: - ignore: /.*/ - tags: - only: /^v\d+\.\d+\.\d+(?:-\w+){0,1}$/ - - run-unit-test-and-build: - context: - - frontend-deploy - - run-ui-test: - requires: - - run-unit-test-and-build - - scheduled-security-scan: - when: << pipeline.parameters.nightly-security-scan >> - jobs: - - scan-sast-full: - context: - - security-tools - - circleci \ No newline at end of file diff --git a/.github/actions/setup/action.yaml b/.github/actions/setup/action.yaml new file mode 100644 index 00000000..68582aad --- /dev/null +++ b/.github/actions/setup/action.yaml @@ -0,0 +1,24 @@ +runs: + using: composite + steps: + - name: Setup JDK 17 + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: 17 + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Cache Gradle + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper/dists + key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: gradle- + + - name: Setup local variables + shell: bash + run: echo "VGS_VAULT_ID=$VGS_VAULT_ID" >> local.properties \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..6fd45fed --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,114 @@ +--- +name: 'CI' + +on: + pull_request: + push: + branches: + - 'main' + tags: + - 'v*' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + checks: write # For publishing test results + +jobs: + run-unit-tests: + name: 'Run Unit Tests' + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + submodules: true + + - name: Setup environment + uses: ./.github/actions/setup + env: + VGS_VAULT_ID: ${{ secrets.VGS_VAULT_ID }} + + - name: Run Detekt + run: ./gradlew vgsshow:detekt --continue + + - name: Run Unit Tests + run: ./gradlew vgsshow:testDebugUnitTest --continue + + - name: (Compass) Generate Code Coverage Report + id: coverage + if: github.ref == 'refs/heads/main' + run: | + ./gradlew vgsshow:koverHtmlReportDebug + + COVERAGE=$(sed -n '51p' vgsshow/build/reports/kover/htmlDebug/index.html) + METRIC_VALUE=`echo ${COVERAGE//[[:space:]]/} | sed 's/.$//'` + + echo "metric_value=$METRIC_VALUE" >> $GITHUB_OUTPUT + +# - name: (Compass) Publish code coverage +# if: github.ref == 'refs/heads/main' +# uses: verygood-ops/cicd-shared/.github/actions/compass@compass-action-v1.0.0 +# with: +# metric_source_id: 'ari:cloud:compass:83673fa7-fd28-4f4a-9738-f584064570a7:component/db43f86d-85fe-42e1-954d-457f5a4082b8/444114a1-5d6c-4c2e-96c6-5895cd094e6a' +# metric_value: ${{ steps.coverage.outputs.metric_value }} +# api_key: ${{ secrets.COMPASS_API_KEY }} + + - name: Upload Test Results + uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: unit-test-results + path: | + **/build/test-results/**/*.xml + **/build/reports/** + retention-days: 30 + + - name: Publish Test Report + uses: mikepenz/action-junit-report@v4 + if: ${{ !cancelled() }} + with: + report_paths: '**/build/test-results/**/TEST-*.xml' + check_name: 'Unit Test Results' + fail_on_failure: true + + run-ui-tests: + name: 'Run UI Tests' + runs-on: ubuntu-latest + if: ${{ startsWith(github.head_ref, 'release/') }} + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + submodules: true + + - name: Setup environment + uses: ./.github/actions/setup + env: + VGS_VAULT_ID: ${{ secrets.VGS_VAULT_ID }} + + - name: Auth Google Cloud SDK + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }} + + - name: Set up Google Cloud SDK + uses: google-github-actions/setup-gcloud@v3 + + - name: Assemble debug & test APK + run: ./gradlew assembleDebug assembleAndroidTest + + - name: Run UI tests + run: | + gcloud firebase test android run \ + --type instrumentation \ + --app app/build/outputs/apk/debug/app-debug.apk \ + --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk \ + --device model=oriole,version=31,locale=en,orientation=portrait \ + --device model=blazer,version=36,locale=en,orientation=portrait \ No newline at end of file