CodeMender יכול לסרוק כל בקשת משיכה בפייפליין של אינטגרציה רציפה (CI) ופיתוח רציף (CD). הבדיקה נכשלת כש-CodeMender מוצא פגיעות ברמת חומרה CRITICAL או HIGH בקוד שמשתנה בבקשת משיכת הקוד. ממצאים בקוד שלא השתנה בבקשת משיכה מופיעים בדוח, אבל הם לא גורמים לסימון הבדיקה כנכשלת.
במאמר הזה מוסבר איך:
- סריקת בקשות למשיכת קוד באמצעות GitHub Actions, ופתיחת בקשה למשיכת קוד עם תיקונים על ידי CodeMender.
- סריקת בקשות משיכה באמצעות Cloud Build.
- סורקים את השינויים לפני כל ביצוע commit באמצעות Git pre-commit hook.
איך פועלות סריקות של בקשות משיכה
כדי לסרוק בקשת משיכה, מריצים את הפקודה cm find עם הדגל --diff וענף הבסיס של בקשת המשיכה:
cm find . --diff=origin/main
בתגובה לפקודה הזו, CodeMender מבצע את הפעולות הבאות:
- הכלי משווה בין הענף של בקשת משיכת השינויים לבין ענף הבסיס, וסורק את קובצי המקור שעברו שינוי ואת הקבצים שתלויים בהם באופן ישיר, כמו קבצים שקוראים לפונקציות וקבצים שמייבאים פונקציות.
- מבחין בין פגיעויות חדשות שהבקשה לשליפת נתונים מציגה או חושפת לבין ממצאים קיימים, שמסומנים בתווית
[LEGACY / UNTOUCHED]. בדיקת ה-CI חוסמת רק פגיעויות שנגרמות כתוצאה מבקשת המשיכה. - הכלי יוצא עם סטטוס 1 אם ממצא שנגרם על ידי בקשת המשיכה תואם לחומרת הבעיה ב-
--fail-on. ערך ברירת המחדל הואCRITICAL,HIGH.
מידע נוסף על ההשוואה בין --diff לבין מצבי סריקה אחרים זמין במאמר מצבי חיפוש ב-CodeMender.
לפני שמתחילים
CodeMender זמין לקבוצה מוגבלת של לקוחות ב-Public Preview. כדי לקבל גישה, צריך לפנות לצוות המכירות.
- נכנסים לחשבון Google Cloud . אנחנו ממליצים למשתמשים חדשים ב- Google Cloud ליצור חשבון כדי שיוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
If you're using an existing project for this guide, verify that you have the permissions required to complete this guide. If you created a new project, then you already have the required permissions.
-
Verify that billing is enabled for your Google Cloud project.
Enable the Agent Platform API and Cloud Resource Manager API APIs, if any are not already enabled.
Roles required to enable APIs
To enable APIs, you need the
serviceusage.services.enablepermission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.-
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init -
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
If you're using an existing project for this guide, verify that you have the permissions required to complete this guide. If you created a new project, then you already have the required permissions.
-
Verify that billing is enabled for your Google Cloud project.
Enable the Agent Platform API and Cloud Resource Manager API APIs, if any are not already enabled.
Roles required to enable APIs
To enable APIs, you need the
serviceusage.services.enablepermission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.-
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init
מוודאים שגרסת CodeMender CLI שלכם תומכת בסריקות של בקשות משיכה. הצינורות (pipelines) במסמך הזה מורידים את הגרסה היציבה האחרונה בכל פעם שהם פועלים. כדי לבדוק התקנה מקומית, מריצים את הפקודה cm find --help ומחפשים את הדגל --diff. כדי לעדכן את ה-CLI, מריצים את הפקודה cm update. למידע נוסף, ראו התקנה והגדרה של ה-CLI.
התפקידים הנדרשים
כדי לקבל את ההרשאות שדרושות להגדרת שילובים של CI/CD ב-CodeMender, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים בפרויקט:
- אדמין בחשבון שירות (
roles/iam.serviceAccountAdmin) - אדמין IAM בפרויקט (
roles/resourcemanager.projectIamAdmin) -
הגדרת איחוד זהויות של עומסי עבודה עבור GitHub Actions:
אדמין במאגר זהויות של עומסי עבודה (
roles/iam.workloadIdentityPoolAdmin) -
יוצרים טריגרים של Cloud Build:
- עריכה ב-Cloud Build (
roles/cloudbuild.builds.editor) - משתמש בחשבון שירות (
roles/iam.serviceAccountUser)
- עריכה ב-Cloud Build (
-
מריצים את ה-hook לפני ביצוע commit ב-Git באופן מקומי:
Agent Platform User (
roles/aiplatform.user)
להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.
יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.
כדי לוודא שלחשבון השירות של CI/CD יש את ההרשאות הנדרשות להפעלת CodeMender בצינור CI/CD, צריך לבקש מהאדמין להקצות לחשבון השירות של CI/CD את תפקידי ה-IAM הבאים:
- משתמש ב-Agent Platform (
roles/aiplatform.user) בפרויקט שלך -
כתיבת יומני build של Cloud Build:
Logs Writer (
roles/logging.logWriter) בפרויקט -
שמירת דוחות SARIF בקטגוריה של Cloud Storage:
Storage Object User (
roles/storage.objectUser) on the bucket
להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.
יכול להיות שהאדמין גם יוכל לתת לחשבון השירות של CI/CD את ההרשאות שנדרשות באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש אחרים.
שיקולי אבטחה
כשמריצים את CodeMender בתהליך עבודה של GitHub Actions, בטריגר לפיתוח גרסת Build של Cloud Build או בוו של Git לפני ביצוע קומיט, CodeMender פועל בלי לבקש אישור. לפני שמגדירים את השילובים האלה, כדאי לקחת בחשבון את הנקודות הבאות:
- הודעות לאישור: הדגל
--yesמשבית את ההודעות שמוצגות למשתמש ומבקשות ממנו לאשר את הפקודות של הסוכן ואת הכתיבה לקובץ. הדגל--bypass-warningמדלג על האזהרה שהסוכן יכול לשנות קבצים ולהריץ פקודות במערכת שלכם. לפני שמשתמשים בדגלים האלה, חשוב לקרוא את תנאי התצוגה המקדימה בתחילת המסמך הזה, כולל התנאים בנוגע להשבתת אישור אנושי. - ארגז חול: צינורות האספקה משביתים את ארגז החול של CodeMender באמצעות
--sandbox=false. לפקודות שהסוכן מריץ, כמו בנייה ובדיקות כשהוא מתקן ממצא, יש את אותה גישה כמו למשימה, כוללGoogle Cloud האישורים והגישה לרשת. ארגז החול של Linux משתמש במרחבי שמות של משתמשים, שחלק מסביבות CI, כמו קונטיינרים ללא הרשאות, לא תומכות בהם. כדאי להשבית את ארגז החול רק בסביבות מבודדות וחד-פעמיות. אם סביבת ה-CI תומכת בארגז החול, מסירים את--sandbox=false. - Runners: הפעלת תהליך העבודה של GitHub Actions ב-Runners באירוח GitHub, כמו
ubuntu-24.04, שמפעילים כל משימה במכונה וירטואלית חדשה. אל תשתמשו ב-runners באירוח עצמי שנעשה בהם שימוש חוזר בין משימות. - קוד לא מהימן: קוד בבקשת משיכה יכול להכיל טקסט שמנסה להכווין את הסוכן. תהליך העבודה של פעולות GitHub סורק רק בקשות משיכה מענפים באותו מאגר, ורק משתמשים עם הרשאת כתיבה יכולים ליצור אותן. ב-Cloud Build, משתמשים בבקרה על תגובות כדי שבעלים או משתפי פעולה יצטרכו לאשר בנייה של בקשות משיכה ממשתתפים אחרים.
- גישה: מקצים לכל חשבון שירות רק את תפקידי ניהול הזהויות והרשאות הגישה (IAM) הנדרשים עבור צינור הנתונים שלו.
סריקת בקשות משיכה באמצעות GitHub Actions
תהליך העבודה שמתואר בקטע הזה סורק כל בקשת משיכה במאגר ב-GitHub.com. כש-CodeMender מוצא פגיעות ברמת חומרה CRITICAL או HIGH בשינויים של בקשת המשיכה, תהליך העבודה מבצע את הפעולות הבאות:
- הבדיקה CodeMender scan נכשלת.
- מריץ את
cm fixלכל ממצא ופותח בקשת משיכה עם התיקונים בענף של בקשת המשיכה.
בנוסף, תהליך העבודה מעלה את הממצאים לסריקת קוד ב-GitHub.
הגדרת איחוד שירותי אימות הזהות של עומסי עבודה
תהליך העבודה מאומת ב- Google Cloud באמצעות איחוד שירותי אימות הזהות של עומסי עבודה, כך שלא צריך לאחסן מפתח של חשבון שירות ב-GitHub. מריצים את הפקודות הבאות באמצעות Google Cloud CLI:
מגדירים משתני Shell לפרויקט ולמאגר:
PROJECT_ID="PROJECT_ID" GITHUB_ORG="GITHUB_ORG" REPO="GITHUB_ORG/REPOSITORY"מחליפים את מה שכתוב בשדות הבאים:
-
PROJECT_ID: מזהה הפרויקט ב- Google Cloud . -
GITHUB_ORG: שם הארגון שלכם ב-GitHub, או שם המשתמש שלכם ב-GitHub למאגר בחשבון אישי. -
REPOSITORY: השם של מאגר GitHub.
-
מפעילים את ממשקי ה-API שבהם נעשה שימוש ב-Workload Identity Federation:
gcloud services enable iam.googleapis.com \ cloudresourcemanager.googleapis.com iamcredentials.googleapis.com \ sts.googleapis.com --project="${PROJECT_ID}"יוצרים חשבון שירות לזרימת העבודה ומקצים לו את תפקיד המשתמש ב-Agent Platform ב-IAM (
roles/aiplatform.user):gcloud iam service-accounts create codemender-ci \ --project="${PROJECT_ID}" \ --display-name="CodeMender CI" gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:codemender-ci@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/aiplatform.user"יוצרים מאגר זהויות של עומסי עבודה. אם כבר יש לכם מאגר ל-GitHub Actions, דלגו על השלב הזה והשתמשו במזהה המאגר במקום
githubבשלבים הבאים.gcloud iam workload-identity-pools create github \ --project="${PROJECT_ID}" \ --location="global" \ --display-name="GitHub Actions"יוצרים ספק עבור GitHub במאגר. תנאי המאפיין מקבל טוקנים רק ממאגרים שבבעלות
GITHUB_ORG.gcloud iam workload-identity-pools providers create-oidc codemender \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github" \ --display-name="CodeMender" \ --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \ --attribute-condition="assertion.repository_owner == '${GITHUB_ORG}'" \ --issuer-uri="https://token.actions.githubusercontent.com"מאפשרים לתהליכי עבודה במאגר להשתמש בחשבון השירות:
POOL_ID=$(gcloud iam workload-identity-pools describe github \ --project="${PROJECT_ID}" \ --location="global" \ --format="value(name)") gcloud iam service-accounts add-iam-policy-binding \ "codemender-ci@${PROJECT_ID}.iam.gserviceaccount.com" \ --project="${PROJECT_ID}" \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/${POOL_ID}/attribute.repository/${REPO}"אחזור השם המלא של הספק. תצטרכו אותו בקטע הבא.
gcloud iam workload-identity-pools providers describe codemender \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github" \ --format="value(name)"הפלט אמור להיראות כך:
projects/123456789/locations/global/workloadIdentityPools/github/providers/codemender
השינויים באיחוד שירותי אימות הזהות של עומסי העבודה וב-IAM ייכנסו לתוקף תוך 5 דקות לכל היותר. מידע נוסף זמין במאמר הגדרה של איחוד שירותי אימות הזהות של עומסי עבודה עם צינורות עיבוד נתונים לפריסה.
הוספת סודות למאגר
במאגר, עוברים אל הגדרות > Secrets and variables (סודות ומשתנים)> Actions (פעולות), ומוסיפים את הסודות הבאים במאגר:
| סוד | ערך |
|---|---|
GCP_PROJECT_ID |
מזהה הפרויקט. |
GCP_WIF_PROVIDER |
השם המלא של הספק מהקטע הקודם. |
GCP_WIF_SERVICE_ACCOUNT |
codemender-ci@PROJECT_ID.iam.gserviceaccount.com,
כאשר PROJECT_ID הוא מזהה הפרויקט.
|
מידע נוסף זמין במאמר בנושא שימוש בסודות ב-GitHub Actions.
קביעת הגדרות המאגר
- כדי לאפשר לעבודת התיקון האוטומטי לפתוח בקשות למשיכת שינויים, עוברים אל הגדרות > פעולות > כללי. בקטע Workflow permissions (הרשאות של תהליך העבודה), בוחרים באפשרות Allow GitHub Actions to create and approve pull requests (מתן הרשאה ל-GitHub Actions ליצור ולאשר בקשות משיכה), ואז לוחצים על Save (שמירה). מאגר בארגון יורש את ההגדרה הזו מהארגון. אם אתם לא יכולים לשנות את השם, אתם צריכים לבקש מבעלי הארגון. אם אתם לא משתמשים בתיקון אוטומטי, אפשר לדלג על השלב הזה. מידע נוסף מופיע במאמר בנושא ניהול ההגדרות של GitHub Actions במאגר.
- מוודאים שסריקת הקוד ב-GitHub זמינה למאגר. כדי לסרוק קוד במאגרים פרטיים ופנימיים, צריך להשתמש ב-GitHub Code Security. אם סריקת הקוד לא זמינה, מוחקים את השלב Upload results to
code scanning ואת ההרשאות
security-eventsו-actionsמעבודת הסריקה. אחרת, ההעלאה נכשלת, וכך גם עבודת הסריקה. מידע נוסף זמין במאמר בנושא העלאת קובץ SARIF ל-GitHub.
הוספת תהליך העבודה
שומרים את תהליך העבודה הבא במאגר בתור .github/workflows/codemender.yml:
name: CodeMender
on:
pull_request:
permissions: {}
defaults:
run:
shell: bash
env:
CM_DOWNLOAD_URL: https://artifactregistry.googleapis.com/download/v1/projects/cmoc-prod/locations/us/repositories/codemender-cli-production/files/cm%3Astable%3Acm-linux-amd64.zip:download?alt=media
jobs:
scan:
name: CodeMender scan
# Workflows for fork and Dependabot pull requests can't read this
# repository's secrets, so they can't authenticate to Google Cloud.
if: >-
github.event.pull_request.head.repo.full_name == github.repository &&
github.actor != 'dependabot[bot]'
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: read
id-token: write # Workload Identity Federation
security-events: write # Upload SARIF to code scanning
actions: read # Upload SARIF from a private repository
outputs:
findings: ${{ steps.scan.outputs.findings }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # cm needs the base branch history
persist-credentials: false
- uses: google-github-actions/auth@v3
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
service_account: ${{ secrets.GCP_WIF_SERVICE_ACCOUNT }}
- name: Install the CodeMender CLI
run: |
curl -fsSL -o "$RUNNER_TEMP/cm.zip" "$CM_DOWNLOAD_URL"
unzip -q -o "$RUNNER_TEMP/cm.zip" -d "$RUNNER_TEMP/cm"
echo "$RUNNER_TEMP/cm" >> "$GITHUB_PATH"
- name: Scan the pull request
id: scan
env:
BASE_REF: ${{ github.base_ref }}
FAIL_ON: CRITICAL,HIGH
run: |
cm init
status=0
cm find . \
--diff="origin/$BASE_REF" \
--diff-workers=16 \
--fail-on="$FAIL_ON" \
--format=sarif \
--output=codemender.sarif \
--sandbox=false \
--yes \
--bypass-warning || status=$?
# Save the findings that failed the scan for the autofix job. Like the
# CI gate, skip findings labeled [LEGACY / UNTOUCHED]: they're in code
# that the pull request didn't change.
echo '[]' > "$RUNNER_TEMP/codemender-findings.json"
if [ "$status" -ne 0 ]; then
cm report --format=json --status=OPEN \
| jq --arg fail_on "$FAIL_ON" '
($fail_on | ascii_upcase | split(",")) as $severities
| [.[]
| select(.title | startswith("[LEGACY / UNTOUCHED]") | not)
| select(.severity | ascii_upcase | IN($severities[]))]' \
> "$RUNNER_TEMP/codemender-findings.json"
fi
echo "findings=$(jq length "$RUNNER_TEMP/codemender-findings.json")" >> "$GITHUB_OUTPUT"
exit "$status"
- name: Upload results to code scanning
if: ${{ !cancelled() && hashFiles('codemender.sarif') != '' }}
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: codemender.sarif
category: codemender
- name: Save findings for autofix
if: ${{ !cancelled() && steps.scan.outputs.findings > 0 }}
uses: actions/upload-artifact@v7
with:
name: codemender-findings
path: ${{ runner.temp }}/codemender-findings.json
retention-days: 1
autofix:
name: CodeMender autofix
needs: scan
if: ${{ !cancelled() && needs.scan.outputs.findings > 0 }}
runs-on: ubuntu-24.04
timeout-minutes: 60
permissions:
contents: write # Push the fix branch
pull-requests: write # Open the fix pull request
id-token: write # Workload Identity Federation
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.head_ref }}
persist-credentials: false
- uses: google-github-actions/auth@v3
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
service_account: ${{ secrets.GCP_WIF_SERVICE_ACCOUNT }}
- name: Install the CodeMender CLI
run: |
curl -fsSL -o "$RUNNER_TEMP/cm.zip" "$CM_DOWNLOAD_URL"
unzip -q -o "$RUNNER_TEMP/cm.zip" -d "$RUNNER_TEMP/cm"
echo "$RUNNER_TEMP/cm" >> "$GITHUB_PATH"
- uses: actions/download-artifact@v8
with:
name: codemender-findings
path: ${{ runner.temp }}/codemender
- name: Fix findings
run: |
# Keep CodeMender state and the auth action's credentials file out of
# the commits, and out of the `git clean` that cm fix runs.
printf '%s\n' .cm_project 'gha-creds-*.json' >> .git/info/exclude
cm init
# Fix in the repository root instead of each file's directory.
printf 'project_paths:\n - "%s"\n' "$GITHUB_WORKSPACE" \
>> ~/.codemender/config.yaml
cm report import -f "$RUNNER_TEMP/codemender/codemender-findings.json"
git config user.name "github-actions[bot]"
git config user.email \
"41898282+github-actions[bot]@users.noreply.github.com"
cm report --format=json --status=OPEN \
| jq -r '.[] | [.finding_id, .title] | @tsv' \
> "$RUNNER_TEMP/findings.tsv"
while IFS=$'\t' read -r id title; do
# cm fix exits 0 when it makes no edits, so also check for changes.
if cm fix "$id" \
--sandbox=false --yes --bypass-warning < /dev/null &&
! git diff --quiet; then
git commit -q -a -m "Fix $title" -m "CodeMender finding $id"
else
echo "::warning::CodeMender didn't fix \"$title\" ($id)."
fi
# Discard files the fix agent created, such as test output.
git reset -q --hard
git clean -q -fd
done < "$RUNNER_TEMP/findings.tsv"
- uses: peter-evans/create-pull-request@v8
with:
branch: codemender/fix-pr-${{ github.event.pull_request.number }}
base: ${{ github.head_ref }}
title: "CodeMender fixes for #${{ github.event.pull_request.number }}"
body: |
CodeMender generated these fixes for findings in #${{ github.event.pull_request.number }}.
Review each commit before you merge this pull request into `${{ github.head_ref }}`.
פרטי תהליך העבודה
התרשים הבא מציג את האינטראקציה בין הסריקה של בקשת המיזוג לבין עבודות התיקון האוטומטי:
הפעולה CodeMender scan מבצעת את הפעולות הבאות:
- הפונקציה מאחזרת את בקשת המיזוג עם ההיסטוריה המלאה שלה. במקרה של בקשות משיכה, GitHub מבצע checkout של קומיט מיזוג של הסתעפות בקשת המשיכה אל הסתעפות הבסיס.
- מתבצעת אימות ל- Google Cloud והורדה של הגרסה היציבה האחרונה של CodeMender CLI.
- מריצים את הפקודה
cm find --diffמול ענף הבסיס. העבודה נכשלת אם CodeMender מוצא נקודת חולשה ברמת חומרה שמפורטת ב-FAIL_ONבשינויים של בקשת משיכה (pull request). - הדוח מועלה לסריקת הקוד ב-GitHub, גם אם הסריקה נכשלת. הדוח כולל ממצאים עם התווית
[LEGACY / UNTOUCHED]. בנוסף, סריקת קוד מציגה ממצא בבדיקות של בקשת משיכה אם כל השורות של הממצא נמצאות בהבדלים של בקשת המשיכה. - שומר את הממצאים שנכשלו בעבודה לצורך תיקון אוטומטי.
עבודת הסריקה לא מופעלת לבקשות מיזוג ממזלגות או מ-Dependabot,
כי תהליכי העבודה של בקשות המיזוג האלה לא יכולים לקרוא את הסודות של המאגר.
מערכת GitHub מדווחת על משימה שדילגה עליה כעל משימה שהושלמה בהצלחה, ולכן הבדיקה לא חוסמת את בקשות המשיכה האלה, גם אם מגדירים אותה כבדיקה נדרשת. כדאי לבדוק את בקשות המיזוג האלה בעצמך, או לסרוק אותן באופן מקומי באמצעות cm find --diff.
המשימה CodeMender autofix פועלת כשמשימת הסריקה שומרת את הממצאים. הוא מבצע את הפעולות הבאות:
- הפונקציה מאחזרת את הענף של בקשת המיזוג.
- הכלי מריץ
cm fixלכל ממצא ומבצע כל תיקון בנפרד. אם CodeMender לא מתקן ממצא, המערכת רושמת אזהרה ביומני העבודה. העבודה מבצעת קומיט רק של שינויים בקבצים שכבר נמצאים במאגר, ומוחקת קבצים שסוכן התיקון יוצר, כמו פלט של בדיקות. - פותח בקשת משיכה מהענף
codemender/fix-pr-NUMBERלענף בקשת המשיכה, כאשרNUMBERהוא מספר בקשת המשיכה. אם בקשת המיזוג לתיקון כבר קיימת, העדכון מתבצע במשימה. אם CodeMender לא מתקן אף ממצא, או אם המשימה מגיעה לזמן הקצוב לתפוגה של 60 דקות, המשימה לא פותחת בקשת משיכה (pull request).
בדיקה ומיזוג של תיקונים
GitHub לא מפעיל באופן אוטומטי תהליכי עבודה לבקשות משיכה שתהליך עבודה יוצר באמצעות GITHUB_TOKEN. כדי לסרוק את בקשת המיזוג של התיקון, משתמש עם גישת כתיבה למאגר לוחץ על Approve workflows to run (אישור הפעלת תהליכי עבודה) בבקשת המיזוג של התיקון.
כשממזגים את בקשת המשיכה לתיקון, הענף של בקשת המשיכה משתנה, ותהליך העבודה סורק שוב את בקשת המשיכה המקורית.
התאמה אישית של תהליך העבודה
אפשר להתאים אישית את תהליך העבודה בדרכים הבאות:
- כדי לשנות את רמות החומרה שגורמות לכשל בבדיקה, בשלב Scan the pull
request (סריקת בקשת המשיכה), מגדירים את
FAIL_ONלרשימה של רמות חומרה שמופרדות בפסיקים ללא רווחים, כמוCRITICAL,HIGH,MEDIUM. הערכים התקפים הםCRITICAL,HIGH,MEDIUMו-LOW. - כדי לדווח על ממצאים בלי שהבדיקה תיכשל, צריך להגדיר את
FAIL_ON: "". תהליך העבודה עדיין מעלה ממצאים לסריקת קוד, אבל הוא לא מפעיל את משימת התיקון האוטומטי. כדי לסרוק בקשות למשיכת קוד רק בענפים מסוימים, מוסיפים
branchesפילטר לטריגרpull_request. לאחר מכן, תהליך העבודה לא סורק בקשות משיכה לתיקון, כי הבסיס שלהן הוא ענף של בקשת משיכה:on: pull_request: branches: [main]כדי להשבית את התיקון האוטומטי, מוחקים את המשימה
autofixואת השלב Save findings for autofix.
סריקת בקשות משיכה באמצעות Cloud Build
ה-build בחלק הזה סורק כל בקשת משיכה במאגר GitHub שמחובר ל-Cloud Build. ה-build והבדיקה שלו ב-GitHub נכשלים כש-CodeMender מוצא פגיעות ברמת חומרה של CRITICAL או HIGH בשינויים של בקשת המשיכה. ה-build לא מתקן את הממצאים.
לפני שמתחילים, צריך לבצע את הפעולות הבאות:
- מחברים את המאגר ל-Cloud Build כמאגר מהדור השני. מידע נוסף זמין במאמר בנושא חיבור למאגר GitHub.
מפעילים את Cloud Build API ואת IAM API בפרויקט שיש לו גישה ל-CodeMender. הגרסה משתמשת ב-CodeMender בפרויקט שמריץ את הגרסה.
PROJECT_ID="PROJECT_ID" gcloud services enable cloudbuild.googleapis.com iam.googleapis.com \ --project="${PROJECT_ID}"מחליפים את
PROJECT_IDבמזהה הפרויקט ב- Google Cloud.
יצירה של חשבון שירות
יוצרים חשבון שירות בשביל הבנייה. מקצים לו את תפקיד ה-IAM של משתמש בפלטפורמת הסוכנים (roles/aiplatform.user) כדי להשתמש ב-CodeMender, ואת התפקיד של כתיבת יומנים (roles/logging.logWriter) כדי לכתוב יומני בנייה:
SA="codemender-build@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud iam service-accounts create codemender-build \
--project="${PROJECT_ID}" \
--display-name="CodeMender Cloud Build"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${SA}" \
--role="roles/aiplatform.user"
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${SA}" \
--role="roles/logging.logWriter"
כדי לשמור דוחות SARIF בקטגוריה של Cloud Storage, צריך גם להעניק לחשבון השירות גישה לקטגוריה:
BUCKET="BUCKET"
gcloud storage buckets add-iam-policy-binding "gs://${BUCKET}" \
--member="serviceAccount:${SA}" \
--role="roles/storage.objectUser"
מחליפים את BUCKET בשם של הקטגוריה שלכם ב-Cloud Storage.
הוספת הגדרות הבנייה
מבצעים קומיט של הגדרת ה-build הבאה אל שורש המאגר בתור cloudbuild.yaml:
# Scans a pull request with CodeMender. The build fails when CodeMender finds
# a CRITICAL or HIGH vulnerability in the pull request's changes.
steps:
- id: install-codemender
name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
script: |
#!/usr/bin/env bash
set -euo pipefail
curl -fsSL -o /tmp/cm.zip "$_CM_DOWNLOAD_URL"
python3 -m zipfile -e /tmp/cm.zip /workspace/.codemender-cli
chmod +x /workspace/.codemender-cli/cm
- id: fetch-history
name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
script: |
#!/usr/bin/env bash
set -euo pipefail
: "${_BASE_BRANCH:?Run this build from a pull request trigger.}"
# Triggers check out only the pull request's commit. CodeMender needs the
# history back to where the pull request branched from the base branch.
# Fetch from origin, or from GitHub if origin isn't configured.
refspec="+refs/heads/$_BASE_BRANCH:refs/remotes/origin/$_BASE_BRANCH"
git fetch --quiet --unshallow origin "$refspec" ||
git fetch --quiet --unshallow \
"https://github.com/$REPO_FULL_NAME.git" "$refspec"
merge_base=$(git merge-base HEAD "origin/$_BASE_BRANCH")
echo "Merge base with $_BASE_BRANCH: $merge_base"
- id: scan
name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
script: |
#!/usr/bin/env bash
set -uo pipefail
export PATH="/workspace/.codemender-cli:$PATH"
# The project that has access to CodeMender.
export GOOGLE_CLOUD_PROJECT="$PROJECT_ID"
cm init || exit 1
status=0
cm find . \
--diff="origin/$_BASE_BRANCH" \
--diff-workers=16 \
--fail-on=CRITICAL,HIGH \
--format=sarif \
--output=codemender.sarif \
--sandbox=false \
--yes \
--bypass-warning || status=$?
# cm find writes the SARIF report when the scan completes.
if [ -f codemender.sarif ]; then
# cm find doesn't print finding details, so print them here.
cm report --status=OPEN --format=md
if [ -n "${_REPORT_BUCKET:-}" ]; then
gcloud storage cp codemender.sarif \
"gs://$_REPORT_BUCKET/codemender/$BUILD_ID.sarif" || status=1
fi
fi
exit "$status"
substitutions:
_CM_DOWNLOAD_URL: https://artifactregistry.googleapis.com/download/v1/projects/cmoc-prod/locations/us/repositories/codemender-cli-production/files/cm%3Astable%3Acm-linux-amd64.zip:download?alt=media
_REPORT_BUCKET: '' # Optional: a bucket to save the SARIF report in.
timeout: 1200s
options:
automapSubstitutions: true
logging: CLOUD_LOGGING_ONLY
יצירת הטריגר
יוצרים טריגר שמריץ את ה-build לכל בקשת משיכה אל main:
REGION="REGION"
CONNECTION="CONNECTION"
REPOSITORY="REPOSITORY"
gcloud builds triggers create github \
--project="${PROJECT_ID}" \
--region="${REGION}" \
--name="codemender-scan" \
--repository="projects/${PROJECT_ID}/locations/${REGION}/connections/${CONNECTION}/repositories/${REPOSITORY}" \
--pull-request-pattern='^main$' \
--comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY \
--build-config=cloudbuild.yaml \
--service-account="projects/${PROJECT_ID}/serviceAccounts/${SA}"
מחליפים את מה שכתוב בשדות הבאים:
-
REGION: האזור של חיבור המאגר של Cloud Build. -
CONNECTION: השם של חיבור המאגר של Cloud Build. -
REPOSITORY: השם של המאגר המחובר ב-Cloud Build.
אלה האפשרויות:
-
--pull-request-patternהוא ביטוי רגולרי לענף הבסיס של בקשת משיכת השינויים. משתמשים בתווים^ו-$כדי להתאים את כל שם הענף. - עם
--comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY, ה-build מופעל באופן אוטומטי לבקשות משיכה מבעלי המאגר וממשתפי פעולה. לגבי בקשות מיזוג מעורכים אחרים, הבנייה מופעלת אחרי שהבעלים או העורכים משאירים תגובה/gcbrunבבקשת המיזוג. - כדי לשמור דוחות SARIF בדלי, מוסיפים את
--substitutions=_REPORT_BUCKET="${BUCKET}".
אפשר ליצור את הטריגר גם במסוף Google Cloud . מידע נוסף זמין במאמר בנושא יצירת מאגרים מ-GitHub.
כדי להציג את יומני הבנייה ב-GitHub, מוסיפים את --include-logs-with-status כשיוצרים את הטריגר, ומעניקים לחשבון השירות את התפקיד Logs Viewer (צפייה ביומנים) (roles/logging.viewer). כל מי שיכול לצפות בבדיקה ב-GitHub יכול לקרוא את יומני הבנייה, כולל הממצאים.
איך הבנייה מתבצעת
תהליך הבנייה כולל שלושה שלבים:
-
install-codemenderמוריד את הגרסה היציבה האחרונה של CodeMender CLI. -
fetch-historyמאחזר את הסתעפות הבסיס ואת ההיסטוריה שנדרשות ל-CodeMender. Cloud Build בודק רק את הקומיט שהתחיל את הבנייה. השלב מאחזר מהמאגר המרוחקorigin. אם לא מוגדרorigin, השלב מאחזר מ-GitHub ללא פרטי כניסה, וזה עובד רק במאגרי מידע ציבוריים. במקרה כזה, כדי לגשת למאגר פרטי צריך פרטי כניסה, כמו מפתח SSH. מידע נוסף זמין במאמר גישה ל-GitHub מ-build באמצעות מפתחות SSH. -
scanמריץ אתcm find --diffמול ענף הבסיס. בסיום הסריקה, כל הממצאים מודפסים ביומן הבנייה. אם מגדירים את_REPORT_BUCKET, השלב גם מעתיק את דוח SARIF אלgs://BUCKET/codemender/BUILD_ID.sarif.
כדי לשנות את רמות החומרה שגורמות לכך שה-build ייכשל, עורכים את --fail-on בשלב scan. אם מריצים את ה-build בלי טריגר של בקשת משיכה, הוא נכשל עם ההודעה Run this build from a pull request trigger.
סריקה לפני כל קומיט
אפשר להשתמש ב-Git pre-commit hook כדי לסרוק את השינויים שהועברו להכנה לשליחה ולחסום את השליחה אם CodeMender מוצא פגיעות ברמת חומרה CRITICAL או HIGH. מפתחים יכולים לדלג על ה-hook, ולכן כדאי להשתמש בו בנוסף לסריקה ב-CI, ולא במקום הסריקה.
כל מפתח שמשתמש ב-hook צריך:
- ה-CLI של CodeMender, שמותקן ומוגדר כמו שמתואר במאמר התקנה והגדרה של ה-CLI, כולל
gcloud auth application-default loginו-cm init. הפזמון הקליט צריך להיות ב-cmב-PATH. - התפקיד Agent Platform User (משתמש ב-Agent Platform) (
roles/aiplatform.user) בפרויקט עם גישה ל-CodeMender. CodeMender משתמש בפרויקט במשתנה הסביבהGOOGLE_CLOUD_PROJECT. אם המשתנה הזה לא מוגדר, CodeMender משתמש בפרויקט מ-Application Default Credentials או בפרויקט שמוגדר כברירת מחדל ב-CLI של gcloud.
כדי להוסיף את ה-hook, שומרים את הסקריפט הבא בשם .git/hooks/pre-commit במאגר:
#!/bin/sh
# Scans staged changes with CodeMender before each commit.
if ! cm find . --diff --staged --fail-on=CRITICAL,HIGH \
--yes --bypass-warning; then
echo "CodeMender blocked this commit. To see the findings, run:" >&2
echo " cm report --status=OPEN" >&2
echo "To commit anyway, run git commit --no-verify." >&2
exit 1
fi
הופכים את הסקריפט לניתן להרצה, ואז מוסיפים .cm_project לקובץ .gitignore
כדי לא לבצע קומיט לקובץ שנוצר על ידי CodeMender למעקב אחרי המאגר:
chmod +x .git/hooks/pre-commit
echo .cm_project >> .gitignore
כשמריצים את הפקודה git commit, ה-hook סורק את הקבצים עם השינויים שהועברו לאזור ההכנה. הסריקה יכולה להימשך כמה דקות. ה-hook לא משבית את ארגז החול של CodeMender.
כדי לבצע קומיט בלי הסריקה, מריצים את הפקודה git commit --no-verify.
סריקת דגלים
הדגלים הבאים cm find שולטים בסריקות של בקשות משיכה. כדי לראות את כל הדגלים, מריצים את הפקודה cm
find --help:
| דגל | ברירת מחדל | תיאור |
|---|---|---|
--diff[=REF] |
מושבת |
סורק את השינויים בהשוואה ל-REF, כמו origin/main. בלי REF, הסריקות
לא כוללות שינויים שלא נשמרו בקבצים שעוקבים אחריהם (בהשוואה ל-HEAD). אי אפשר להשתמש באפשרות הזו עם --deep.
|
--staged |
מושבת | ב---diff, הסריקות מתבצעות רק על שינויים שהועברו לשלב ההכנה. |
--diff-depth DEPTH |
1 |
עומק המעבר לניתוח ההשפעה (1 עד 3, ברירת מחדל: 1-hop). |
--diff-workers COUNT |
4 |
מספר הקבצים לסריקה בו-זמנית, מ-1 עד 16. |
--diff-max-neighbors COUNT |
10 |
המספר המקסימלי של קבצים תלויים לסריקה. |
--fail-on SEVERITIES |
CRITICAL,HIGH |
במקרה של --diff, רמות החומרה שגורמות ל-cm find
לצאת עם סטטוס 1. אם הערך ריק, הממצאים לא משפיעים על סטטוס היציאה.
|
--fail-on-truncation |
מושבת |
עם --diff, מתבצעת יציאה עם סטטוס 1 אם CodeMender מוצא יותר קבצים תלויים ממה ש---diff-max-neighbors מאפשר.
|
--format FORMAT |
table |
פורמט הדוח: table, json או sarif.
|
--output FILE |
פלט רגיל | הקובץ שאליו ייכתב הדוח. |
פתרון בעיות
בקטע הזה מוסבר איך לפתור בעיות נפוצות בהרצת CodeMender בצינורות CI/CD.
ההרשאה נדחתה
בקטע היומן מוצגת שורה כמו זו:
[1/1] ❌ src/app.py: start session failed: StartSession failed with HTTP 403 Forbidden.
ההודעה יכולה לכלול גם את Permission 'aiplatform.interactions.create'
denied. כדאי לבדוק את הדברים הבאים:
- לפרויקט יש גישה ל-CodeMender.
- לחשבון השירות או למשתמש יש את התפקיד Agent Platform User (משתמש בפלטפורמת סוכנים) (
roles/aiplatform.user) בפרויקט. - ממשק Agent Platform API מופעל בפרויקט.
- הכלי CodeMender משתמש בפרויקט הנכון. ב-GitHub Actions, בודקים את הסוד
GCP_PROJECT_ID. Cloud Build משתמש בפרויקט שבו מופעלת הבנייה. באופן מקומי, בודקים את משתנה הסביבהGOOGLE_CLOUD_PROJECT, או את פרויקט ברירת המחדל אם המשתנה לא מוגדר.
הגדרת המשאב מתבצעת
אם ביומן מופיע Resource setup has just started. Please try again shortly. או Resource setup is in progress. Please try again shortly., סימן ש-CodeMender מגדיר משאבים לפרויקט, תהליך שבדרך כלל נמשך כמה דקות. מריצים את העבודה שוב מאוחר יותר.
סימון לא ידוע: --diff
אם הפקודה cm find נכשלת עם Error: unknown flag: --diff, הגרסה של ה-CLI לא תומכת בסריקות של בקשות משיכה. מריצים את cm update או מורידים את הגרסה האחרונה.
לא נמצא ענף בסיס
אם הפקודה cm find נכשלת עם שגיאה כמו השגיאה הבאה, הענף הבסיסי לא נמצא ב-checkout:
Error: retrieving VCS diff: git diff failed: exit status 128: fatal: ambiguous argument 'origin/main': unknown revision or path not in the working tree.
לפני שמריצים את הפקודה cm find, צריך לאחזר את ענף הבסיס ואת ההיסטוריה שלו. ב-GitHub
Actions, מגדירים את fetch-depth: 0 ב-actions/checkout.
קבצים שלא נסרקו
שורה עם ❌, כמו [1/1] ❌ src/app.py: start session failed, מציינת ש-CodeMender לא הצליח לסרוק את הקובץ הזה. צריך לבדוק את השגיאה בשורה ואז להריץ את העבודה שוב.
אין בקשת משיכה לתיקון
אם תהליך העבודה לא פותח בקשת מיזוג לתיקון, כדאי לבדוק את הדברים הבאים:
- אם משימת התיקון האוטומטי נכשלת כשיוצרים את בקשת משיכת השינויים, מפעילים את האפשרות Allow GitHub Actions to create and approve pull requests (מתן הרשאה ל-GitHub Actions ליצור ולאשר בקשות משיכת שינויים). מידע נוסף מופיע במאמר הגדרת מאגר.
- אם עבודת התיקון האוטומטי מצליחה בלי לפתוח בקשת משיכה, CodeMender לא תיקן אף ממצא. ב-job log מוצגת אזהרה לכל ממצא שלא תוקן על ידי CodeMender.
העלאה של סריקת קוד נכשלת
אם שלב ההעלאה נכשל עם GitHub Code Security or GitHub Advanced Security
must be enabled for this repository to use code scanning, צריך להפעיל את GitHub Code Security במאגר או למחוק את שלב ההעלאה. מידע נוסף מופיע במאמר הגדרת מאגר.
האזהרה לא אושרה
אם cm נכשל עם warning not acknowledged. Please run interactively once to
acknowledge or pass --bypass-warning, CodeMender צריך אישור שהוא לא יכול לבקש בסביבה לא אינטראקטיבית. מוסיפים את --bypass-warning לפקודה. לפני שתעשו זאת, קראו את תנאי התצוגה המקדימה בחלק העליון של הדף הזה.
לקבלת עזרה נוספת, אפשר לפנות לצוות המכירות.