Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 7 additions & 22 deletions .github/workflows/fossa-oss-pr-scan.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 }}
Comment thread
petr-klemsinsky marked this conversation as resolved.
122 changes: 122 additions & 0 deletions fossa/pr-scan/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
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: Get CodeArtifact token
uses: gooddata/github-actions-public/codeartifact/get-token@master
- name: Set up Maven settings
uses: s4u/maven-settings-action@v4.0.0
with:
servers: |
[{
"id": "infra1-gooddata",
"username": "aws",
"password": "${env.CODEARTIFACT_AUTH_TOKEN}"
},
{
"id": "infra1-gooddata-snapshots",
"username": "aws",
"password": "${env.CODEARTIFACT_AUTH_TOKEN}"
},
{
"id": "infra1-thirdparty",
"username": "aws",
"password": "${env.CODEARTIFACT_AUTH_TOKEN}"
},
{
"id": "gdc-codeartifact",
"username": "aws",
"password": "${env.CODEARTIFACT_AUTH_TOKEN}"
},
{
"id": "gdc-codeartifact-removed",
"username": "aws",
"password": "${env.CODEARTIFACT_AUTH_TOKEN}"
},
{
"id": "gdc-gooddata-and-upstream",
"username": "aws",
"password": "${env.CODEARTIFACT_AUTH_TOKEN}"
}]
repositories: |
[{
"id": "gdc-codeartifact",
"name": "gdc-codeartifact",
"url": "https://infra1-020413372491.d.codeartifact.us-east-1.amazonaws.com/maven/gooddata-and-upstream-repositories/",
"snapshots": {"enabled": "true"},
"releases": {"enabled": "true"}
},
{
"id": "gdc-codeartifact-removed",
"name": "gdc-codeartifact-removed",
"url": "https://infra1-020413372491.d.codeartifact.us-east-1.amazonaws.com/maven/upstream-removed/",
"snapshots": {"enabled": "true"},
"releases": {"enabled": "true"}
},
{
"id": "gdc-gooddata-and-upstream",
"name": "gdc-gooddata-and-upstream",
"url": "https://infra1-020413372491.d.codeartifact.us-east-1.amazonaws.com/maven/gooddata-and-upstream-repositories/",
"snapshots": {"enabled": "true"},
"releases": {"enabled": "true"}
},
{
"id": "central",
"name": "central",
"url": "https://repo.maven.apache.org/maven2/",
"snapshots": {"enabled": "true"},
"releases": {"enabled": "true"}
}]
pluginRepositories: |
[{
"id": "gdc-codeartifact",
"name": "gdc-codeartifact",
"url": "https://infra1-020413372491.d.codeartifact.us-east-1.amazonaws.com/maven/gooddata-and-upstream-repositories/",
"snapshots": {"enabled": "true"},
"releases": {"enabled": "true"}
},
{
"id": "central",
"name": "central",
"url": "https://repo.maven.apache.org/maven2/",
"snapshots": {"enabled": "true"},
"releases": {"enabled": "true"}
}]
githubServer: false
- 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
106 changes: 106 additions & 0 deletions fossa/pr-scan/scan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/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:-}"
CODEARTIFACT_AUTH_TOKEN="${CODEARTIFACT_AUTH_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}" <<EOF
[url "https://oauth2:${GITHUB_PULL_TOKEN}@github.com/gooddata/"]
insteadOf = ssh://git@github.com/gooddata/
insteadOf = git@github.com:gooddata/
insteadOf = https://github.com/gooddata/
EOF
fi

# --- m2 settings (optional; only mounted if present) ---
m2_settings="${HOME}/.m2/settings.xml"

docker_pull() { docker pull "$1" >/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 rel_conf="${gdc_conf#${src_dir}/}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟑 Minor | ⚑ Quick win

Quote ${src_dir} inside the prefix expansion.

In ${gdc_conf#${src_dir}/}, the unquoted ${src_dir} is interpreted as a glob pattern during prefix removal. If src_dir ever contains pattern metacharacters (*, ?, [), the prefix strip will misbehave and yield an incorrect rel_conf. Quote it separately.

πŸ”§ Proposed fix (SC2295)
-    local rel_conf="${gdc_conf#${src_dir}/}"
+    local rel_conf="${gdc_conf#"${src_dir}"/}"
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
local rel_conf="${gdc_conf#${src_dir}/}"
local rel_conf="${gdc_conf#"${src_dir}"/}"
🧰 Tools
πŸͺ› Shellcheck (0.11.0)

[info] 59-59: Expansions inside ${..} need to be quoted separately, otherwise they match as patterns.

(SC2295)

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fossa/pr-scan/scan.sh` at line 59, The rel_conf prefix removal in scan.sh is
using an unquoted src_dir inside the parameter expansion, which can be treated
as a glob pattern. Update the rel_conf assignment in the scan.sh logic to quote
src_dir separately within the ${gdc_conf#...} expansion so prefix stripping is
literal and robust when src_dir contains glob metacharacters.

Source: Linters/SAST tools

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 "${rel_conf}")
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.

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 CODEARTIFACT_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."
Loading