Skip to content

deps: clear all 13 Dependabot alerts, fix 3 failing workflows, bump stale actions #23109

deps: clear all 13 Dependabot alerts, fix 3 failing workflows, bump stale actions

deps: clear all 13 Dependabot alerts, fix 3 failing workflows, bump stale actions #23109

name: Projects • Add & Sync meta from labels
on:
push:
branches: [develop]
issues:
types: [opened, edited, labeled, unlabeled, reopened, closed]
pull_request:
branches: [develop]
types:
[
opened,
edited,
labeled,
unlabeled,
reopened,
ready_for_review,
synchronize,
closed,
]
permissions:
contents: read
issues: read
pull-requests: read
concurrency:
group: project-meta-sync-${{ github.event.number || github.event.issue.number || github.run_id }}
env:
PROJECT_URL: ${{ vars.LS_PROJECT_URL }}
jobs:
add-and-sync:
runs-on: ubuntu-latest
steps:
- name: Preflight project sync configuration
id: preflight
env:
APP_ID: ${{ vars.LS_APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.LS_APP_PRIVATE_KEY }}
run: |
set -euo pipefail
enabled="true"
reason=""
if [ -z "${PROJECT_URL:-}" ]; then
enabled="false"
reason="LS_PROJECT_URL is not configured"
elif [ -z "${APP_ID:-}" ] || [ -z "${APP_PRIVATE_KEY:-}" ]; then
enabled="false"
reason="LS_APP_ID and/or LS_APP_PRIVATE_KEY is missing"
fi
echo "enabled=$enabled" >> "$GITHUB_OUTPUT"
if [ "$enabled" != "true" ]; then
echo "::notice::$reason; skipping project meta sync."
fi
- name: Create GitHub App installation token
id: app-token
if: steps.preflight.outputs.enabled == 'true'
uses: actions/create-github-app-token@v3
with:
app-id: ${{ vars.LS_APP_ID }}
private-key: ${{ secrets.LS_APP_PRIVATE_KEY }}
- name: Add item to project (new issues/PRs)
id: addp
if: steps.preflight.outputs.enabled == 'true'
uses: actions/add-to-project@v2.0.0
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ steps.app-token.outputs.token }}
- name: Derive Status/Priority/Type from labels & branch
id: derive
if: steps.preflight.outputs.enabled == 'true'
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "issues" ]; then
NUMBER=${{ github.event.issue.number }}
LABELS=$(gh issue view $NUMBER --json labels --jq '.labels[].name')
else
NUMBER=${{ github.event.pull_request.number }}
LABELS=$(gh pr view $NUMBER --json labels --jq '.labels[].name')
fi
STATUS=""
echo "$LABELS" | grep -q '^status:in-progress' && STATUS='In progress'
echo "$LABELS" | grep -q '^status:needs-review' && STATUS='In review'
echo "$LABELS" | grep -q '^status:needs-qa' && STATUS='In QA'
echo "$LABELS" | grep -q '^status:blocked' && STATUS='Blocked'
echo "$LABELS" | grep -q '^status:ready' && STATUS='Ready'
if [ "${{ github.event_name }}" = "issues" ] && [ "${{ github.event.action }}" = "closed" ]; then STATUS='Done'; fi
if [ "${{ github.event_name }}" = "pull_request" ] && [ "${{ github.event.action }}" = "closed" ] && [ "${{ github.event.pull_request.merged }}" = "true" ]; then STATUS='Done'; fi
[ -z "$STATUS" ] && STATUS='Triage'
PRIORITY=""
echo "$LABELS" | grep -q '^priority:critical' && PRIORITY='Critical'
echo "$LABELS" | grep -q '^priority:important' && PRIORITY='Important'
echo "$LABELS" | grep -q '^priority:normal' && PRIORITY='Normal'
echo "$LABELS" | grep -q '^priority:minor' && PRIORITY='Minor'
TYPE=""
HEAD="$HEAD_REF"
if [ -n "$HEAD" ]; then
case "$HEAD" in
feat/*) TYPE='Feature' ;;
fix/*) TYPE='Bug' ;;
doc/*|docs/*) TYPE='Documentation' ;;
chore/*|build/*) TYPE='Task' ;;
esac
fi
echo "status=$STATUS" >> $GITHUB_OUTPUT
echo "priority=$PRIORITY" >> $GITHUB_OUTPUT
echo "type=$TYPE" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# This step runs before any actions/checkout, so gh has no git remote
# to infer the repository from and fails with "failed to run git:
# fatal: not a git repository". GH_REPO supplies the context directly,
# which is all these two API reads need - no clone required.
GH_REPO: ${{ github.repository }}
HEAD_REF: ${{ github.head_ref }}
- name: Checkout code for retry wrapper
if: steps.preflight.outputs.enabled == 'true' && steps.addp.outputs.itemId != ''
uses: actions/checkout@v7
- name: Setup Node for retry wrapper
if: steps.preflight.outputs.enabled == 'true' && steps.addp.outputs.itemId != ''
uses: actions/setup-node@v7
with:
node-version-file: ".nvmrc"
- name: Update project fields with retry and backoff
if: steps.preflight.outputs.enabled == 'true' && steps.addp.outputs.itemId != ''
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
PROJECT_URL: ${{ env.PROJECT_URL }}
ITEM_ID: ${{ steps.addp.outputs.itemId }}
FIELD_KEYS: Status,Priority,Type
FIELD_VALUES: ${{ steps.derive.outputs.status }},${{ steps.derive.outputs.priority }},${{ steps.derive.outputs.type }}
run: |
set -euo pipefail
PROJECT_URL="${{ env.PROJECT_URL }}"
ITEM_ID="${{ steps.addp.outputs.itemId }}"
FIELD_KEYS="${{ steps.derive.outputs.status }},Priority,Type"
FIELD_VALUES="${{ steps.derive.outputs.status }},${{ steps.derive.outputs.priority }},${{ steps.derive.outputs.type }}"
# Extract project number from URL
PROJECT_NUMBER=$(echo "$PROJECT_URL" | grep -oP 'projects/\K[0-9]+')
# Function to update fields with exponential backoff
update_with_backoff() {
local max_attempts=5
local initial_delay=1
local attempt=1
while [ $attempt -le $max_attempts ]; do
echo "::notice::Attempt $attempt/$max_attempts: Updating project fields..."
# Attempt update
if gh project field-list $PROJECT_NUMBER --format json | jq . > /dev/null 2>&1; then
echo "::notice::Project fields update successful"
return 0
fi
if [ $attempt -lt $max_attempts ]; then
local delay=$((2 ** (attempt - 1) * initial_delay))
echo "::warning::Attempt $attempt failed, retrying in ${delay}s..."
sleep $delay
fi
((attempt++))
done
echo "::error::Failed to update project fields after $max_attempts attempts"
return 1
}
# Execute update with backoff
update_with_backoff || exit 1