From 7a0f479093f0ebfe706a9dada36a35f7feda3f2f Mon Sep 17 00:00:00 2001 From: Petr Klemsinsky Date: Fri, 26 Jun 2026 12:48:23 +0200 Subject: [PATCH] feat(fossa): switch OSS PR scan to native gdc-fossa-cli action Replace Jenkins trigger with native fossa/pr-scan composite action using the gdc-fossa-cli container. Adds the fossa/pr-scan action to this repo following the same pattern as gooddata/github-actions. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/fossa-oss-pr-scan.yaml | 29 ++----- fossa/pr-scan/action.yml | 41 +++++++++ fossa/pr-scan/scan.sh | 103 +++++++++++++++++++++++ 3 files changed, 151 insertions(+), 22 deletions(-) create mode 100644 fossa/pr-scan/action.yml create mode 100644 fossa/pr-scan/scan.sh diff --git a/.github/workflows/fossa-oss-pr-scan.yaml b/.github/workflows/fossa-oss-pr-scan.yaml index e351192..7b6e1fd 100644 --- a/.github/workflows/fossa-oss-pr-scan.yaml +++ b/.github/workflows/fossa-oss-pr-scan.yaml @@ -1,14 +1,14 @@ --- # yamllint disable rule:line-length -name: Fossa-oss PR scan (jenkins) +name: Fossa OSS PR scan on: pull_request: concurrency: - group: ${{ github.event.repository.name }}-fossa-scanning-oss-zuul-${{ github.event.pull_request.number }} + group: ${{ github.event.repository.name }}-fossa-scanning-oss-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: - fossa: + fossa-native: runs-on: group: infra1-runners-arc labels: runners-small @@ -17,23 +17,8 @@ jobs: id-token: write pull-requests: write steps: - - name: Call Jenkins trigger - id: call-jenkins - uses: gooddata/github-actions-public/jenkins/trigger@master + - uses: gooddata/github-actions-public/fossa/pr-scan@master with: - server: ${{ secrets.JENKINS_ADDRESS }} - folder: compliance - job-name: "${{ github.event.repository.name }}-fossa-scanning-oss-zuul" - vault-url: ${{ secrets.VAULT_ADDRESS }} - params: |- - { - "GH_BRANCH":"${{ github.base_ref }}", - "GH_REF":"${{ github.ref }}", - "GH_COMMIT":"${{ github.event.pull_request.head.sha }}", - "GH_URL":"git@github.com:", - "GH_CHANGE":"${{ github.event.pull_request.number }}", - "GH_PROJECT":"${{ github.repository }}", - "GH_PR_NUMBER":"${{ github.event.pull_request.number }}", - "BUILD_BY_GITHUB":"true", - "GH_PIPELINE":"gate" - } + fossa-api-key: ${{ secrets.FOSSA_API_KEY }} + npm-auth-token: ${{ secrets.NPM_TOKEN }} + github-token: ${{ secrets.TOKEN_GITHUB_YENKINS }} diff --git a/fossa/pr-scan/action.yml b/fossa/pr-scan/action.yml new file mode 100644 index 0000000..6237786 --- /dev/null +++ b/fossa/pr-scan/action.yml @@ -0,0 +1,41 @@ +--- +name: "FOSSA PR scan" +description: "Run a native FOSSA analyze+test scan for a PR, reusing the gdc-fossa-cli container (no Jenkins)." +inputs: + branch: + description: "Branch reported to FOSSA for the analyze upload" + required: false + default: ${{ github.head_ref }} + scan-image: + description: "Default FOSSA scan container image (per-repo gdc_fossa.yaml scan_image overrides this)" + required: false + default: "020413372491.dkr.ecr.us-east-1.amazonaws.com/tools/gdc-fossa-cli:latest" + fossa-api-key: + description: "FOSSA API key (org GitHub secret FOSSA_API_KEY)" + required: true + npm-auth-token: + description: "NPM read token for private dependency resolution (org GitHub secret NPM_TOKEN)" + required: false + default: "" + github-token: + description: "GitHub PAT for private-repo dependency resolution (org GitHub secret TOKEN_GITHUB_YENKINS)" + required: false + default: "" +runs: + using: "composite" + steps: + - name: Checkout the PR + uses: actions/checkout@v7 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - name: Run FOSSA scan + shell: bash + env: + FOSSA_API_KEY: ${{ inputs.fossa-api-key }} + NPM_AUTH_TOKEN: ${{ inputs.npm-auth-token }} + GITHUB_PULL_TOKEN: ${{ inputs.github-token }} + SCAN_IMAGE_DEFAULT: ${{ inputs.scan-image }} + FOSSA_BRANCH: ${{ inputs.branch }} + REPO_NAME: ${{ github.event.repository.name }} + run: bash ${{ github.action_path }}/scan.sh diff --git a/fossa/pr-scan/scan.sh b/fossa/pr-scan/scan.sh new file mode 100644 index 0000000..b9268eb --- /dev/null +++ b/fossa/pr-scan/scan.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# Native port of `cish fossa-scanning` scan loop. Reproduces the Jenkins +# docker-run invocation of fossa_scanning_tool inside the gdc-fossa-cli image. +# +# Auth uses org GitHub Actions secrets (no Vault): NPM_AUTH_TOKEN for npm, and a +# GitHub PAT (GITHUB_PULL_TOKEN) wired through a git insteadOf rewrite so the +# in-container dependency resolution can fetch private gooddata repos over HTTPS +# (replaces the Jenkins SSH-agent approach). +set -euo pipefail + +: "${FOSSA_API_KEY:?FOSSA_API_KEY is required}" +: "${REPO_NAME:?REPO_NAME is required}" +NPM_AUTH_TOKEN="${NPM_AUTH_TOKEN:-}" +GITHUB_PULL_TOKEN="${GITHUB_PULL_TOKEN:-}" +SCAN_IMAGE_DEFAULT="${SCAN_IMAGE_DEFAULT:?SCAN_IMAGE_DEFAULT is required}" +FOSSA_BRANCH="${FOSSA_BRANCH:-}" + +src_dir="${GITHUB_WORKSPACE:-$PWD}" +work_dir="${RUNNER_TEMP:-$PWD}/fossa-pr-scan" +mkdir -p "${PWD}/build-output" "${work_dir}" + +# --- npm auth (mounted into the container as ~/.npmrc) --- +# Jenkins used the public registry with an auth token; npm interpolates the +# NPM_AUTH_TOKEN env var (also passed into the container) at runtime. +npmrc="${work_dir}/npmrc" +if [ -n "${NPM_AUTH_TOKEN}" ]; then + printf '//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}\n' > "${npmrc}" +else + : > "${npmrc}" +fi + +# --- git auth for private gooddata deps (mounted into the container) --- +# Rewrite ssh/https gooddata URLs to token-authenticated HTTPS so go/npm/maven +# can resolve private dependencies in-container. The token is embedded in a +# throwaway gitconfig on the ephemeral runner. +gitconfig="${work_dir}/gitconfig" +: > "${gitconfig}" +if [ -n "${GITHUB_PULL_TOKEN}" ]; then + cat > "${gitconfig}" </dev/null; } + +run_scan() { + local scan_img="$1" gdc_conf="$2" + local java_version="" conf_arg=() + local mount_args=() + + if [ -n "${gdc_conf}" ] && [ -f "${gdc_conf}" ]; then + local img_override + img_override="$(yq -r '.scan_image | select(. != null)' "${gdc_conf}")" + [ -n "${img_override}" ] && scan_img="${img_override}" + java_version="$(yq -r '.java_version | select(. != null)' "${gdc_conf}")" + conf_arg=(--gdc-conf "$(basename "${gdc_conf}")") + fi + + docker_pull "${scan_img}" + + mount_args=( + -v "${npmrc}:/home/fossa/.npmrc" + -v "${gitconfig}:/home/fossa/.gitconfig" + -v "${src_dir}:/home/fossa/sources/${REPO_NAME}" + -v "${PWD}/build-output:/home/fossa/build-output" + ) + if [ -f "${m2_settings}" ]; then + mount_args+=(-v "${m2_settings}:/home/fossa/.m2/settings.xml") + fi + + docker run --rm \ + "${mount_args[@]}" \ + -e USER_UID="$(id -u)" \ + -e FOSSA_API_KEY -e NPM_AUTH_TOKEN \ + -e JAVA_VERSION="${java_version}" \ + "${scan_img}" \ + fossa_scanning_tool -r "${REPO_NAME}" -o "not_found" -v -c analyze test \ + ${FOSSA_BRANCH:+-b "${FOSSA_BRANCH}"} \ + "${conf_arg[@]}" +} + +# --- find gdc_fossa*.yaml configs; loop, or single scan if none --- +mapfile -t confs < <(find "${src_dir}" -type f -name "gdc_fossa*.yaml" | sort) +if [ "${#confs[@]}" -eq 0 ]; then + run_scan "${SCAN_IMAGE_DEFAULT}" "" +else + for conf in "${confs[@]}"; do + run_scan "${SCAN_IMAGE_DEFAULT}" "${conf}" + done +fi + +# fossa_scanning_tool writes build-output/analyze_failed.txt on analyze failure +if [ -f "./build-output/analyze_failed.txt" ]; then + echo "ERROR: FOSSA analyze failed for some module(s); see logs above." + exit 1 +fi +echo "FOSSA scan completed."