Refactor Codacy workflow for asset retrieval #121
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Codacy Security Scan (revised: replaced docker action with codacy-cli-v2 install+analyze) | |
| # - Uses codacy-cli-v2 installer to run analyze when the docker image pre-pull succeeds | |
| # Codacy security scan action usage and parameters, see | |
| # https://github.com/codacy/codacy-analysis-cli-action. | |
| # For more information on Codacy Analysis CLI in general, see | |
| # https://github.com/codacy/codacy-analysis-cli. | |
| name: Codacy Security Scan | |
| on: | |
| push: | |
| branches: [ "main" ] | |
| pull_request: | |
| branches: [ "main" ] | |
| schedule: | |
| - cron: '44 7 * * 0' | |
| permissions: | |
| contents: read | |
| jobs: | |
| codacy-security-scan: | |
| name: Codacy Security Scan | |
| runs-on: ubuntu-latest | |
| env: | |
| CLI_VERSION: "4.0.0" | |
| CODACY_CLI_V2_VERSION: "" | |
| CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} | |
| MAX_PULL_RETRIES: "6" | |
| PULL_RETRY_BASE: "5" | |
| permissions: | |
| contents: read | |
| security-events: write | |
| actions: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Check for non-UTF-8 files | |
| run: | | |
| find . -type f -exec file --mime {} + | grep -v 'charset=utf-8' || true | |
| - name: Pre-pull Codacy CLI Docker image (with exponential backoff + jitter) | |
| run: | | |
| set -euo pipefail | |
| IMAGE="codacy/codacy-analysis-cli:${CLI_VERSION}" | |
| MAX_RETRIES=${MAX_PULL_RETRIES} | |
| RETRY_BASE=${PULL_RETRY_BASE} | |
| echo "CODACY_DOCKER_OK=false" >> $GITHUB_ENV | |
| for i in $(seq 1 $MAX_RETRIES); do | |
| echo "Attempt $i to pull $IMAGE" | |
| if docker pull "$IMAGE"; then | |
| echo "Successfully pulled $IMAGE" | |
| echo "CODACY_DOCKER_OK=true" >> $GITHUB_ENV | |
| break | |
| fi | |
| if [ "$i" -lt "$MAX_RETRIES" ]; then | |
| # exponential backoff with jitter | |
| sleep_time=$(( RETRY_BASE * 2 ** (i - 1) )) | |
| jitter=$(( (RANDOM % 5) + 1 )) | |
| total_sleep=$(( sleep_time + jitter )) | |
| if [ "$total_sleep" -gt 300 ]; then | |
| total_sleep=300 | |
| fi | |
| echo "Failed to pull $IMAGE (attempt $i). Retrying in ${total_sleep}s..." | |
| sleep "$total_sleep" | |
| else | |
| echo "Failed to pull $IMAGE after $i attempts." | |
| fi | |
| done | |
| if [ "${CODACY_DOCKER_OK:-}" != "true" ]; then | |
| echo "::warning::Could not pull $IMAGE after $MAX_RETRIES attempts. Fallback will run." | |
| fi | |
| - name: Run Codacy CLI v2 (install & analyze) | |
| if: env.CODACY_DOCKER_OK == 'true' | |
| env: | |
| CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} | |
| CODACY_CLI_V2_VERSION: ${{ env.CODACY_CLI_V2_VERSION }} | |
| run: | | |
| set -euo pipefail | |
| echo "Installing codacy-cli-v2 via the official installer script" | |
| if [ -n "${CODACY_CLI_V2_VERSION:-}" ]; then | |
| export CODACY_CLI_V2_VERSION | |
| fi | |
| bash <(curl -Ls https://raw.githubusercontent.com/codacy/codacy-cli-v2/main/codacy-cli.sh) | |
| echo "Running codacy-cli analyze to produce SARIF (results.sarif)" | |
| if [ -n "${CODACY_PROJECT_TOKEN:-}" ]; then | |
| TOKEN_ARG="--project-token ${CODACY_PROJECT_TOKEN}" | |
| else | |
| TOKEN_ARG="" | |
| fi | |
| codacy-cli analyze --format sarif --output results.sarif ${TOKEN_ARG} --gh-code-scanning-compat --verbose || true | |
| - name: Run Codacy Analysis CLI (robust fallback via GitHub Releases API) | |
| if: env.CODACY_DOCKER_OK != 'true' | |
| env: | |
| CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} | |
| CLI_VERSION: ${{ env.CLI_VERSION }} | |
| run: | | |
| set -euo pipefail | |
| echo "Fallback: attempt to obtain a Codacy Analysis CLI release asset (tag: ${CLI_VERSION})" | |
| REPO="codacy/codacy-analysis-cli" | |
| PREFERRED_TAG="${CLI_VERSION}" | |
| get_release_json() { | |
| tag="$1" | |
| if [ -n "$tag" ]; then | |
| url="https://api.github.com/repos/${REPO}/releases/tags/${tag}" | |
| echo "Querying $url" | |
| curl -sS "$url" || return 1 | |
| else | |
| url="https://api.github.com/repos/${REPO}/releases/latest" | |
| echo "Querying $url" | |
| curl -sS "$url" || return 1 | |
| fi | |
| } | |
| release_json="$(get_release_json "${PREFERRED_TAG}" || true)" | |
| if [ -z "$release_json" ] || echo "$release_json" | grep -q '"message": "Not Found"'; then | |
| echo "Preferred release '${PREFERRED_TAG}' not found. Falling back to latest release." | |
| release_json="$(get_release_json "" )" || { echo "::error::Could not fetch latest release info"; exit 1; } | |
| fi | |
| # Use jq (installed on ubuntu-latest) to pick the best asset: | |
| # Preference order: | |
| # 1) asset name contains 'codacy-analysis-cli' and ends with .zip | |
| # 2) any .zip asset | |
| # 3) any .jar asset | |
| # 4) first asset | |
| asset_url="$(echo "$release_json" | jq -r ' | |
| (.assets[] | select(.name | test("codacy-analysis-cli.*\\.zip"; "i")) | .browser_download_url) // | |
| (.assets[] | select(.name | test("\\.zip$"; "i")) | .browser_download_url) // | |
| (.assets[] | select(.name | test("\\.jar$"; "i")) | .browser_download_url) // | |
| (.assets[] | .browser_download_url) | |
| ' | grep -v null | head -n1 || true)" | |
| if [ -z "$asset_url" ]; then | |
| echo "::error::No suitable release asset found in the release. Release JSON:" | |
| echo "$release_json" | |
| exit 1 | |
| fi | |
| echo "Selected release asset: ${asset_url}" | |
| ARCHIVE_NAME="$(basename "$asset_url")" | |
| echo "Downloading asset to ${ARCHIVE_NAME}" | |
| curl -fSL "$asset_url" -o "$ARCHIVE_NAME" || { echo "::error::Failed to download ${asset_url}"; exit 1; } | |
| echo "Extracting ${ARCHIVE_NAME}" | |
| if file "$ARCHIVE_NAME" | grep -qi zip; then | |
| unzip -q "$ARCHIVE_NAME" | |
| else | |
| echo "Downloaded asset does not appear to be a zip. Proceeding to check for jar or executable." | |
| fi | |
| # Determine runnable CLI (executable or jar) | |
| if [ -x "./codacy-analysis-cli" ]; then | |
| CMD="./codacy-analysis-cli" | |
| elif ls codacy-analysis-cli-* 2>/dev/null | grep -q '\.jar$'; then | |
| JAR="$(ls codacy-analysis-cli-*.jar | head -n1)" | |
| CMD="java -jar ${JAR}" | |
| elif ls *.jar 2>/dev/null | head -n1 >/dev/null 2>&1; then | |
| JAR="$(ls *.jar | head -n1)" | |
| CMD="java -jar ${JAR}" | |
| else | |
| if [ -f "$ARCHIVE_NAME" ] && [ -x "$ARCHIVE_NAME" ]; then | |
| CMD="./${ARCHIVE_NAME}" | |
| else | |
| candidate="$(ls | grep -i codacy | head -n1 || true)" | |
| if [ -n "$candidate" ]; then | |
| if [ -f "$candidate" ]; then | |
| chmod +x "$candidate" || true | |
| CMD="./${candidate}" | |
| fi | |
| fi | |
| fi | |
| fi | |
| if [ -z "${CMD:-}" ]; then | |
| echo "::error::Could not determine a runnable CLI (executable or jar) after downloading and extracting ${ARCHIVE_NAME}." | |
| ls -la | |
| exit 1 | |
| fi | |
| echo "Running Codacy CLI fallback via: $CMD" | |
| if [ -n "${CODACY_PROJECT_TOKEN:-}" ]; then | |
| TOKEN_ARG="--project-token ${CODACY_PROJECT_TOKEN}" | |
| else | |
| TOKEN_ARG="" | |
| fi | |
| $CMD analyze --format sarif --output results.sarif ${TOKEN_ARG} --gh-code-scanning-compat --verbose || true | |
| - name: Upload SARIF results file | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: results.sarif |