diff --git a/.github/workflows/bump-dependency.yaml b/.github/workflows/bump-dependency.yaml index b77cd627ae..716c6ce048 100644 --- a/.github/workflows/bump-dependency.yaml +++ b/.github/workflows/bump-dependency.yaml @@ -5,28 +5,31 @@ on: types: [ bump-dependency ] jobs: - get-label: - name: Get Label - outputs: - label: ${{ steps.get-label.outputs.label }} + sanitize-payload: + name: Sanitize Payload runs-on: ubuntu-22.04 + outputs: + label: ${{ steps.sanitize.outputs.label }} + safe_module: ${{ steps.sanitize.outputs.safe_module }} + safe_head: ${{ steps.sanitize.outputs.safe_head }} + safe_assignee: ${{ steps.sanitize.outputs.safe_assignee }} + safe_email: ${{ steps.sanitize.outputs.safe_email }} + safe_branch: ${{ steps.sanitize.outputs.safe_branch }} + safe_short: ${{ steps.sanitize.outputs.safe_short }} steps: - - name: Get Label - id: get-label + - uses: actions/checkout@v4 + - name: Validate & Sanitize Payload (script) + id: sanitize env: - REPO: ${{ github.event.client_payload.dependency }} - run: | - if [ "$REPO" == "vitess" ] - then - echo "label=vitess-bump" >> $GITHUB_OUTPUT - else - echo "$REPO is unsupported" - exit 1 - fi + RAW_DEP: ${{ github.event.client_payload.dependency }} + RAW_SHA: ${{ github.event.client_payload.head_commit_sha }} + RAW_USER: ${{ github.event.client_payload.assignee }} + RAW_MAIL: ${{ github.event.client_payload.assignee_email }} + run: bash .github/workflows/scripts/sanitize_payload.sh stale-bump-prs: name: Retrieving Stale Bump PRs - needs: get-label + needs: sanitize-payload outputs: stale-pulls: ${{ steps.get-stale-prs.outputs.open-pulls }} runs-on: ubuntu-22.04 @@ -35,7 +38,7 @@ jobs: id: get-stale-prs uses: actions/github-script@v7 env: - LABEL: ${{ needs.get-label.outputs.label }} + LABEL: ${{ needs.sanitize-payload.outputs.label }} with: debug: true github-token: ${{ secrets.REPO_ACCESS_TOKEN }} @@ -85,7 +88,7 @@ jobs: } open-bump-pr: - needs: [get-label, stale-bump-prs] + needs: [sanitize-payload, stale-bump-prs] name: Open Bump PR runs-on: ubuntu-22.04 outputs: @@ -94,48 +97,66 @@ jobs: - uses: actions/checkout@v4 with: token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }} + - name: Set up Go 1.x uses: actions/setup-go@v5 with: go-version-file: go.mod - - name: Bump dependency - run: GOOS=linux go get github.com/dolthub/${{ github.event.client_payload.dependency }}@${{ github.event.client_payload.head_commit_sha }} - - name: Get Assignee and Reviewer + + - name: Bump dependency (safe) + env: + SAFE_MODULE: ${{ needs.sanitize-payload.outputs.safe_module }} + SAFE_HEAD: ${{ needs.sanitize-payload.outputs.safe_head }} + run: | + set -euo pipefail + IFS=$'\n\t' + echo "Installing ${SAFE_MODULE}@${SAFE_HEAD}" + GOOS=linux go get "${SAFE_MODULE}@${SAFE_HEAD}" + + - name: Get Assignee and Reviewer (safe) id: get_reviewer + env: + ASSIGNEE: ${{ needs.sanitize-payload.outputs.safe_assignee }} run: | - if [ "${{ github.event.client_payload.assignee }}" == "zachmu" ] - then - echo "reviewer=Hydrocharged" >> $GITHUB_OUTPUT + set -euo pipefail + if [ "${ASSIGNEE}" = "zachmu" ]; then + echo "reviewer=Hydrocharged" >> "$GITHUB_OUTPUT" else - echo "reviewer=zachmu" >> $GITHUB_OUTPUT + echo "reviewer=zachmu" >> "$GITHUB_OUTPUT" fi - - name: Get short hash - id: short-sha - run: | - commit=${{ github.event.client_payload.head_commit_sha }} - short=${commit:0:8} - echo "short=$short" >> $GITHUB_OUTPUT - - name: Create and Push new branch + + - name: Create and Push new branch (safe) + env: + GIT_USER: ${{ needs.sanitize-payload.outputs.safe_assignee }} + GIT_MAIL: ${{ needs.sanitize-payload.outputs.safe_email }} + BRANCH: ${{ needs.sanitize-payload.outputs.safe_branch }} + COMMIT_BY: ${{ needs.sanitize-payload.outputs.safe_assignee }} run: | - git config --global --add user.name "${{ github.event.client_payload.assignee }}" - git config --global --add user.email "${{ github.event.client_payload.assignee_email }}" - branchname=${{ format('{0}-{1}', github.event.client_payload.assignee, steps.short-sha.outputs.short) }} - git checkout -b "$branchname" + set -euo pipefail + IFS=$'\n\t' + + git config --global user.name "${GIT_USER}" + git config --global user.email "${GIT_MAIL}" + + git checkout -b -- "${BRANCH}" git add . - git commit -m "${{ format('[ga-bump-dep] Bump dependency in GMS by {0}', github.event.client_payload.assignee) }}" - git push origin "$branchname" + + # Commit message uses sanitized assignee only + git commit -m "[ga-bump-dep] Bump dependency in GMS by ${COMMIT_BY}" + git push origin "${BRANCH}" + - name: pull-request uses: repo-sync/pull-request@v2 id: latest-pr with: - source_branch: ${{ format('{0}-{1}', github.event.client_payload.assignee, steps.short-sha.outputs.short ) }} + source_branch: ${{ needs.sanitize-payload.outputs.safe_branch }} destination_branch: "main" github_token: ${{ secrets.REPO_ACCESS_TOKEN }} - pr_title: "[auto-bump] [no-release-notes] dependency by ${{ github.event.client_payload.assignee }}" + pr_title: "[auto-bump] [no-release-notes] dependency by ${{ needs.sanitize-payload.outputs.safe_assignee }}" pr_template: ".github/markdown-templates/dep-bump.md" pr_reviewer: ${{ steps.get_reviewer.outputs.reviewer }} - pr_assignee: ${{ github.event.client_payload.assignee }} - pr_label: ${{ needs.get-label.outputs.label }} + pr_assignee: ${{ needs.sanitize-payload.outputs.safe_assignee }} + pr_label: ${{ needs.sanitize-payload.outputs.label }} comment-on-stale-prs: needs: [open-bump-pr, stale-bump-prs] diff --git a/.github/workflows/scripts/sanitize_payload.sh b/.github/workflows/scripts/sanitize_payload.sh new file mode 100755 index 0000000000..fb1d1b6b15 --- /dev/null +++ b/.github/workflows/scripts/sanitize_payload.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +set -euo pipefail +IFS=$'\n\t' + +# Inputs via environment variables +RAW_DEP=${RAW_DEP:-} +RAW_SHA=${RAW_SHA:-} +RAW_USER=${RAW_USER:-} +RAW_MAIL=${RAW_MAIL:-} + +# --- Validate dependency via allow-list and map to module path + label +case "${RAW_DEP:-}" in + vitess) + MODULE='github.com/dolthub/vitess' + LABEL='vitess-bump' + ;; + *) + echo "Unsupported dependency '${RAW_DEP:-}'" >&2 + exit 1 + ;; +esac + +# --- Validate head SHA/tag (conservative) +# allow only hex SHAs or safe tag-ish: letters, digits, dot, dash, underscore, plus +if [ -z "${RAW_SHA:-}" ] || ! printf '%s' "$RAW_SHA" | grep -qE '^[A-Za-z0-9._+-]+$'; then + echo "Invalid head_commit_sha" >&2 + exit 1 +fi + +# Keep a short 8-char form if it's a hex SHA; otherwise derive short safe token +if printf '%s' "$RAW_SHA" | grep -qiE '^[0-9a-f]{40}$'; then + SHORT_SHA="${RAW_SHA:0:8}" +else + SHORT_SHA="$(printf '%s' "$RAW_SHA" | tr -cd 'A-Za-z0-9._+-' | cut -c1-12)" +fi + +# --- Validate assignee username (GitHub-compatible subset) +if [ -z "${RAW_USER:-}" ] || ! printf '%s' "$RAW_USER" | grep -qE '^[A-Za-z0-9-]{1,39}$'; then + echo "Invalid assignee username" >&2 + exit 1 +fi + +# --- Validate email; if invalid, fall back to GitHub noreply +if [ -n "${RAW_MAIL:-}" ] && printf '%s' "$RAW_MAIL" | grep -qE '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'; then + SAFE_EMAIL="$RAW_MAIL" +else + SAFE_EMAIL="${RAW_USER}+noreply@users.noreply.github.com" +fi + +# --- Build a safe branch name: - +BRANCH_NAME="$(printf '%s-%s' "$RAW_USER" "$SHORT_SHA" | tr -cd 'A-Za-z0-9._-')" + +# Expose sanitized values as step outputs +{ + echo "label=$LABEL" + echo "safe_module=$MODULE" + echo "safe_head=$RAW_SHA" + echo "safe_assignee=$RAW_USER" + echo "safe_email=$SAFE_EMAIL" + echo "safe_branch=$BRANCH_NAME" + echo "safe_short=$SHORT_SHA" +} >> "${GITHUB_OUTPUT}"