diff --git a/.github/workflows/maven-mend-ci.yml b/.github/workflows/mend-ci.yml similarity index 77% rename from .github/workflows/maven-mend-ci.yml rename to .github/workflows/mend-ci.yml index dbf48ae..02c576e 100644 --- a/.github/workflows/maven-mend-ci.yml +++ b/.github/workflows/mend-ci.yml @@ -1,18 +1,8 @@ -name: Mend CLI scan for Maven +name: Mend CLI scan on: workflow_call: inputs: - java_version: - description: "The Java version to use to compile. Default: 21" - required: false - type: string - default: "21" - maven_version: - description: "The Maven version to use. Defaults to version of the runner image" - required: false - type: string - default: "3.9.14" SCA: required: true type: boolean @@ -23,18 +13,13 @@ on: SAST: required: true type: boolean - mode: - description: "'fresh' (checkout + build + scan) or 'deferred' (consume artifact + scan)" - required: false - type: string - default: "fresh" triggering_run_id: - description: "workflow_run id to pull artifacts from (required for mode='deferred')" + description: "workflow_run id to pull artifacts from" required: false type: string default: "" pr_feedback: - description: "PR check and comment feedback (deferred mode only)" + description: "Whether to add PR check and comment feedback" required: false type: boolean default: false @@ -70,51 +55,32 @@ jobs: security-events: write steps: - # Fresh mode: checkout + build - - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - if: inputs.mode == 'fresh' - with: - persist-credentials: false - - - uses: project-ncl/shared-github-actions/.github/actions/maven-build@94481b379fd7ddda5fe363d1c1d5fc311930c607 # main - if: inputs.mode == 'fresh' - with: - java_version: ${{ inputs.java_version }} - build_command: "mvn -B -V clean install -DskipTests" - maven_version: ${{ inputs.maven_version }} - - # Deferred mode: fetch PR metadata and build artifact - - name: Download PR metadata - if: inputs.mode == 'deferred' + if: inputs.pr_feedback uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: pr-metadata path: pr-metadata - run-id: ${{ inputs.triggering_run_id }} + run-id: ${{ inputs.triggering_run_id || github.run_id }} github-token: ${{ secrets.GITHUB_TOKEN }} - name: Read PR metadata - if: inputs.mode == 'deferred' + if: inputs.pr_feedback id: metadata run: | echo "pr_number=$(cat pr-metadata/pr-number)" >> "$GITHUB_OUTPUT" echo "pr_sha=$(cat pr-metadata/pr-sha)" >> "$GITHUB_OUTPUT" - - name: Download PR build artifact - if: inputs.mode == 'deferred' + - name: Download build artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: pr-build path: . - run-id: ${{ inputs.triggering_run_id }} + run-id: ${{ inputs.triggering_run_id || github.run_id }} github-token: ${{ secrets.GITHUB_TOKEN }} - # Deferred mode: create in-progress check-run - - name: Create in-progress check-run - if: inputs.mode == 'deferred' && inputs.pr_feedback + if: inputs.pr_feedback id: check uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 env: @@ -131,27 +97,23 @@ jobs: }); return check.id; - # Common: run Mend scan - - name: Run Mend CLI scan uses: project-ncl/shared-github-actions/.github/actions/mend@94481b379fd7ddda5fe363d1c1d5fc311930c607 # main with: PROJECT_NAME: ${{ github.event.repository.name }} TAGS: >- - ${{ inputs.mode == 'deferred' + ${{ inputs.pr_feedback && format('trigger:pr, pr:{0}, run:{1}', steps.metadata.outputs.pr_number, github.run_id) || format('trigger:{0}, run:{1}', github.event_name, github.run_id) }} SCA: ${{ inputs.SCA }} SCA_REACHABILITY: ${{ inputs.SCA_REACHABILITY }} SAST: ${{ inputs.SAST }} - source_ref: ${{ inputs.mode == 'deferred' && format('refs/pull/{0}/head', steps.metadata.outputs.pr_number) || '' }} - source_sha: ${{ inputs.mode == 'deferred' && steps.metadata.outputs.pr_sha || '' }} - - # Deferred mode: update check-run + PR comment with results + source_ref: ${{ steps.metadata.outputs.pr_number && format('refs/pull/{0}/head', steps.metadata.outputs.pr_number) || '' }} + source_sha: ${{ steps.metadata.outputs.pr_sha || '' }} - name: Build result summary id: summary - if: ${{ !cancelled() && inputs.mode == 'deferred' && inputs.pr_feedback }} + if: ${{ !cancelled() && inputs.pr_feedback }} run: | SCA_LOG="$HOME/.mend/logs/sca-results.txt" SAST_LOG="$HOME/.mend/logs/sast-results.sarif" @@ -229,7 +191,7 @@ jobs: echo "overall=success" >> "$GITHUB_OUTPUT" - name: Update check-run - if: ${{ !cancelled() && inputs.mode == 'deferred' && inputs.pr_feedback }} + if: ${{ !cancelled() && inputs.pr_feedback }} uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 env: CHECK_ID: ${{ steps.check.outputs.result }} @@ -251,7 +213,7 @@ jobs: }); - name: Post or update PR comment - if: ${{ !cancelled() && inputs.mode == 'deferred' && inputs.pr_feedback }} + if: ${{ !cancelled() && inputs.pr_feedback }} uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # 9.0.0 env: PR_NUMBER: ${{ steps.metadata.outputs.pr_number }} diff --git a/.github/workflows/npm-ci.yml b/.github/workflows/npm-ci.yml new file mode 100644 index 0000000..5732597 --- /dev/null +++ b/.github/workflows/npm-ci.yml @@ -0,0 +1,92 @@ +name: NPM CI + +on: + workflow_call: + inputs: + fetch_all_commits: + description: "Whether to fetch all commits. Default: false" + required: false + type: boolean + default: false + node_version: + description: "The Node.js version to use. Default: 22.x" + required: false + type: string + default: "22.x" + build_command: + description: "The build command to use. Default: npm ci and npm run build" + required: false + type: string + default: "npm ci && npm run build" + test_command: + description: "The command to use for tests. Default: null" + required: false + type: string + formatter_command: + description: "The command to use for formatting. Default: null" + required: false + type: string + upload_artifacts: + description: "Whether to upload artifacts and their metadata. Default: false" + required: false + type: boolean + default: false + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.node_version }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: ${{ inputs.fetch_all_commits == true && '0' || '1' }} + persist-credentials: false + + - uses: project-ncl/shared-github-actions/.github/actions/npm-build@8ba48d272f8e53b55e5a266a4c3feeab6e7f0526 # main + with: + node_version: ${{ inputs.node_version }} + build_command: ${{ inputs.build_command }} + + - if: inputs.test_command + env: + INPUTS_TEST_COMMAND: ${{ inputs.test_command }} + run: bash -c "${INPUTS_TEST_COMMAND}" + + - if: inputs.formatter_command + env: + INPUTS_FORMATTER_COMMAND: ${{ inputs.formatter_command }} + run: bash -c "${INPUTS_FORMATTER_COMMAND}" + + - name: Save PR metadata + if: inputs.upload_artifacts + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_SHA: ${{ github.event.pull_request.head.sha }} + run: | + mkdir -p pr-metadata + echo "$PR_NUMBER" > pr-metadata/pr-number + echo "$PR_SHA" > pr-metadata/pr-sha + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: inputs.upload_artifacts + with: + name: pr-build + path: | + . + !.git + !pr-metadata + retention-days: 1 + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: inputs.upload_artifacts + with: + name: pr-metadata + path: pr-metadata + retention-days: 1 diff --git a/README.md b/README.md index 2ec1e51..3978966 100644 --- a/README.md +++ b/README.md @@ -43,15 +43,22 @@ the Java version etc. It is possible to use this within a matrix job. ``` -## Maven Mend -Workflow to run Mend analysis, both SCA (Software Composition Analysis) and SAST (Static Application Security Testing), on Maven projects. Because it has to have access to secrets in the organization or repository, it has two modes: `fresh` and `deferred`. +## NPM CI (`npm-ci.yml`) +Standard CI workflow for NPM projects. -Fresh mode checkouts the code, builds the Maven project, and runs the Mend analysis. It is designed for cronjob schedule, and push to main workflow runs - because for those, the secrets are accessible. +- **Tasks**: Checkout code, set up Node.js, set up NPM, run build command, optionally run tests, optionally check for code formatting errors, and optionally push build artifact (which is used by Mend workflow). -Workflows run in the context of the PR from a fork do not have access to the secrets. For that use-case, deferred mode exists. It is meant to be executed `on: workflow_run` depending on Maven CI workflow with `upload_artifact` set to `true` - this way, the Maven Mend workflow is run in the context of the base repository. It downloads saved PR metadata and build artifact, sets check-run on the PR, runs the Mend analysis, and posts PR comment. +## Mend CI (`mend-ci.yml`) +Workflow to run Mend analysis, both SCA (Software Composition Analysiss) and SAST (Static Application Security Testing), on Maven projects. Because it has to have access to secrets in the organization or repository, on Pull Requests, it is meant to run `on: workflow_run`. + +It depends on some build workflow with `upload_artifact` set to `true`, and before analysis, downloads an build artifact. + +If `pr_feedback` is `false`, it downloads the build artifact, and runs the Mend analysis. This is meant for cronjob schedule, and push to main workflow runs. + +Workflows run in the context of the PR from a fork do not have access to the secrets. It is meant to be executed `on: workflow_run` - this way, the Mend workflow is run in the context of the base repository. `pr_feedback` should be set to `true` and `triggering_run_id` set to ID of a triggering workflow. It downloads saved PR metadata and build artifact, sets check-run on the PR, runs the Mend analysis, and posts PR comment.
-Example of 'fresh' mode usage +Example of push to main and cronjob usage ```yaml name: Mend CLI scan for Maven @@ -71,8 +78,19 @@ permissions: security-events: write jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@ + - uses: project-ncl/shared-github-actions/.github/actions/maven-build@ + - uses: actions/upload-artifact@ + with: + name: pr-build + path: . + call-maven-mend-ci: - uses: project-ncl/shared-github-actions/.github/workflows/maven-mend-ci.yml@ + needs: build + uses: project-ncl/shared-github-actions/.github/workflows/mend-ci.yml@ with: SCA: true SAST: true @@ -86,7 +104,7 @@ jobs:
-Example of 'deferred' mode usage +Example of PR usage ```yaml name: Java CI with Maven @@ -126,11 +144,10 @@ concurrency: jobs: scan: if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' - uses: project-ncl/shared-github-actions/.github/workflows/maven-mend-ci.yml@ + uses: project-ncl/shared-github-actions/.github/workflows/mend-ci.yml@ with: SCA: true SAST: true - mode: deferred triggering_run_id: ${{ github.event.workflow_run.id }} pr_feedback: true secrets: