diff --git a/composite-actions/nodejs-generic-api/test-unit/README.md b/composite-actions/nodejs-generic-api/test-unit/README.md index d8302dba..d89af4c6 100644 --- a/composite-actions/nodejs-generic-api/test-unit/README.md +++ b/composite-actions/nodejs-generic-api/test-unit/README.md @@ -6,9 +6,14 @@ This is typical action, to run tests in nodejs api application. ```yaml - uses: extenda/shared-workflows/composite-actions/nodejs-generic-api/test-unit@master + env: + IMAGE_NAME: eu.gcr.io/extenda/att-api with: GCLOUD_AUTH: ${{ secrets.GCLOUD_AUTH_STAGING }} SECRET_AUTH: ${{ secrets.SECRET_AUTH }} + # Optional + # slack-channel: team-ci-alerts + # notify-slack-on-fail: true ``` ### Requirements @@ -20,3 +25,9 @@ This is typical action, to run tests in nodejs api application. - You must set Node.js version in `.nvmrc` file. - You should have a ```npm run check-openapi-schema``` script, to test you openapi schema. - You should have a ```npm run ts:check``` script, to check, whether your typescript code is valid. +- You must commit `.npmrc` in the repository root. +- You should provide `npm run auth` in `package.json` (the action calls `npm run auth --if-present`). +- Set `IMAGE_NAME` in workflow `env`. +- The action builds one local image in the test job using `docker build --quiet -t "${IMAGE_NAME}:${GITHUB_SHA}" .`. +- Trivy scans this locally built image (`${IMAGE_NAME}:${GITHUB_SHA}`). +- The job fails if `IMAGE_NAME` is missing, `Dockerfile` is missing, or local image build fails. diff --git a/composite-actions/nodejs-generic-api/test-unit/action.yaml b/composite-actions/nodejs-generic-api/test-unit/action.yaml index e41f799a..c2e20675 100644 --- a/composite-actions/nodejs-generic-api/test-unit/action.yaml +++ b/composite-actions/nodejs-generic-api/test-unit/action.yaml @@ -1,5 +1,6 @@ name: "Run unit tests" description: "Run unit tests for the service" + inputs: SECRET_AUTH: description: "GCP Auth" @@ -15,6 +16,7 @@ inputs: default: false type: boolean required: false + runs: using: "composite" steps: @@ -34,6 +36,7 @@ runs: - name: Copy test .env files shell: bash run: cp test/example.env .env + - name: Copy .env files shell: bash run: find . -type f -name '*example.env' -execdir mv {} .env ';' @@ -41,7 +44,7 @@ runs: - uses: extenda/actions/setup-gcloud@v0 id: gcloud with: - service-account-key: ${{ inputs.GCLOUD_AUTH }} + service-account-key: ${{ inputs.GCLOUD_AUTH || inputs.SECRET_AUTH }} - name: GCloud configure-docker shell: bash @@ -56,7 +59,7 @@ runs: env: cache-name: cache-sonar-binary with: - path: /home/runner/.sonar/native-sonar-scanner + path: /home/runner/.sonar/cache key: ${{ runner.os }}-cache-sonar-binary restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }} @@ -69,8 +72,17 @@ runs: - name: Run NPM auth script shell: bash run: | - echo "@hiiretail:registry=https://europe-west1-npm.pkg.dev/extenda/npm/" > .npmrc - npm run auth -- --credential-config=./.npmrc + umask 077 + + # Use repository-owned npm config only. + if [ ! -f ".npmrc" ]; then + echo "Missing .npmrc in repository root." + echo "Please commit .npmrc and provide npm auth script in package.json." + exit 1 + fi + + # Service-owned auth hook (recommended standard). + npm run auth --if-present - name: Install dependencies if: steps.cache-node-modules.outputs.cache-hit != 'true' @@ -93,6 +105,43 @@ runs: shell: bash run: npm run test:cov + - name: Build vulnerability scan image + id: scan-image + shell: bash + run: | + IMAGE="${IMAGE_NAME:+${IMAGE_NAME}:${GITHUB_SHA}}" + + if [ -z "$IMAGE" ]; then + echo "Unable to resolve vulnerability scan image tag." + echo "Set IMAGE_NAME in caller workflow." + exit 1 + fi + + if [ ! -f "Dockerfile" ]; then + echo "No Dockerfile found in repository root." + exit 1 + fi + + export DOCKER_BUILDKIT=1 + + echo "Building local image for vulnerability scan: $IMAGE" + if ! docker build --secret id=npmrc,src=.npmrc --quiet -t "$IMAGE" .; then + echo "Initial quiet Docker build failed. Retrying with full logs for debugging..." + docker build --secret id=npmrc,src=.npmrc -t "$IMAGE" . + echo "Failed to build image $IMAGE." + exit 1 + fi + + echo "image=$IMAGE" >> "$GITHUB_OUTPUT" + + - name: Vulnerability scan + uses: extenda/actions/trivy-scan@v0 + with: + image: ${{ steps.scan-image.outputs.image }} + service-account-key: ${{ inputs.GCLOUD_AUTH }} + fail-on-vulnerabilities: true + notify-slack-on-vulnerabilities: false + - name: Analyze with SonarCloud uses: extenda/actions/sonar-scanner@v0 with: @@ -106,6 +155,6 @@ runs: with: text: | *Unit test failed for ${{ github.repository }}: ${{ github.workflow }}* :heavy_exclamation_mark: - Test failed on ${{ github.event_name }} event. Workflow: ${{ github.workflow }}. Job: ${{github.job}}. Run id: + Test failed on ${{ github.event_name }} event. Workflow: ${{ github.workflow }}. Job: ${{ github.job }}. Run id: channel: ${{ inputs.slack-channel }} - service-account-key: ${{ inputs.GCLOUD_AUTH || inputs.SECRET_AUTH }} + service-account-key: ${{ inputs.GCLOUD_AUTH || inputs.SECRET_AUTH }} \ No newline at end of file