Skip to content
Open
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
238 changes: 133 additions & 105 deletions .github/workflows/handle_metadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,126 +76,154 @@ jobs:
run: |
# split the comma-separated plugin-dir input into an array.
IFS=',' read -ra PLUGIN_DIRS <<< "${{ inputs.plugin-dir }}"
pr_numbers=""
metadata_paths=""
db_flag=""
if [ "${{ inputs.db-connection }}" = "true" ]; then
db_flag="--db-connection"
fi

for dir in "${PLUGIN_DIRS[@]}"; do
echo "Processing metadata in directory: $dir" 1>&2
pr_num=$(python -m brainscore_core.plugin_management.handle_metadata --plugin-dir "$dir" --plugin-type "${{ inputs.plugin-type }}" --db-connection)
echo "PR number for $dir: $pr_num" 1>&2
# Append to the list (if multiple directories are provided)
if [ -z "$pr_numbers" ]; then
pr_numbers="$pr_num"
else
pr_numbers="$pr_numbers,$pr_num"
# Use --skip-pr to prevent individual PR creation; collect metadata paths instead
meta_path=$(python -m brainscore_core.plugin_management.handle_metadata --plugin-dir "$dir" --plugin-type "${{ inputs.plugin-type }}" $db_flag --skip-pr)
echo "Metadata path for $dir: $meta_path" 1>&2
if [ -n "$meta_path" ]; then
if [ -z "$metadata_paths" ]; then
metadata_paths="$meta_path"
else
metadata_paths="$metadata_paths,$meta_path"
fi
fi
done
echo "pr_numbers=${pr_numbers}" >> $GITHUB_OUTPUT

- name: Auto-approve PRs
if: steps.run_metadata.outputs.pr_numbers != ''
echo "metadata_paths=${metadata_paths}" >> $GITHUB_OUTPUT

- name: Create Combined PR
id: create_pr
if: steps.run_metadata.outputs.metadata_paths != ''
env:
GITHUB_TOKEN: ${{ secrets.APPROVAL_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
IFS=',' read -ra PR_ARRAY <<< "${{ steps.run_metadata.outputs.pr_numbers }}"
for pr in "${PR_ARRAY[@]}"; do
echo "Auto-approving PR #$pr" 1>&2
gh pr review $pr --approve --repo ${{ github.repository }}
# Create a single branch and PR for all metadata files
branch_name="auto/metadata-update_$(date +%s)"
git checkout -b "$branch_name"

IFS=',' read -ra PATHS <<< "${{ steps.run_metadata.outputs.metadata_paths }}"
for path in "${PATHS[@]}"; do
echo "Adding metadata file: $path"
git add "$path"
done

git commit -m "Auto-add/update metadata.yml for ${#PATHS[@]} plugin(s)"
git push origin "$branch_name"

pr_title="Auto-add/update metadata.yml for ${#PATHS[@]} plugin(s)"
pr_body="This PR was automatically generated to add or update metadata.yml files for the following plugins:\n\n$(printf '- %s\n' "${PATHS[@]}")"
gh pr create --title "$pr_title" --body "$pr_body" --label "automerge-metadata"

sleep 5
pr_number=$(gh pr view --json number --jq '.number')
echo "pr_number=${pr_number}" >> $GITHUB_OUTPUT

- name: Auto-approve PR
if: steps.create_pr.outputs.pr_number != ''
env:
GITHUB_TOKEN: ${{ secrets.APPROVAL_TOKEN }}
run: |
pr=${{ steps.create_pr.outputs.pr_number }}
echo "Auto-approving PR #$pr"
gh pr review $pr --approve --repo ${{ github.repository }}

- name: Wait for Status Checks
if: steps.run_metadata.outputs.pr_numbers != ''
if: steps.create_pr.outputs.pr_number != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
IFS=',' read -ra PR_ARRAY <<< "${{ steps.run_metadata.outputs.pr_numbers }}"
pr=${{ steps.create_pr.outputs.pr_number }}
TOKEN="${{ secrets.GITHUB_TOKEN }}"
MAX_WAIT=600 # 10 minutes maximum wait time per PR
MAX_WAIT=600 # 10 minutes maximum wait time
SLEEP_INTERVAL=10

for pr in "${PR_ARRAY[@]}"; do
echo "Waiting for status checks on PR #$pr"
commit_sha=$(gh pr view $pr --json headRefOid --jq '.headRefOid')
echo "Commit SHA for PR #$pr is $commit_sha"

# initial delay to allow statuses to start being reported
echo "Sleeping for initial delay (30s) to allow statuses to be reported..."
sleep 30
ELAPSED=30

while true; do
echo "Polling statuses for PR #$pr (commit $commit_sha)"
statuses=$(curl -s -H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/commits/$commit_sha/statuses")

# get required status checks for the branch
branch=$(gh pr view $pr --json headRefName --jq '.headRefName')
required_checks=$(curl -s -H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/branches/$branch/protection" | \
jq -r '.required_status_checks.contexts[]' 2>/dev/null || echo "")

# process the latest status for each context
latest_statuses=$(echo "$statuses" | jq '[group_by(.context)[] | max_by(.created_at)]')

# count by state
pending=$(echo "$latest_statuses" | jq 'map(select(.state=="pending")) | length')
failures=$(echo "$latest_statuses" | jq 'map(select(.state=="failure" or .state=="error")) | length')
successes=$(echo "$latest_statuses" | jq 'map(select(.state=="success")) | length')
total=$(echo "$latest_statuses" | jq 'length')

# list the current statuses for visibility
echo "$latest_statuses" | jq -r '.[] | " - \(.context): \(.state)"' | sort
echo "Status summary: $pending pending, $failures failures, $successes successes (total: $total)"

# check for required status checks
missing_required=0
if [ ! -z "$required_checks" ]; then
echo "Required status checks for branch $branch:"
echo "$required_checks" | while read -r check; do
exists=$(echo "$latest_statuses" | jq --arg check "$check" 'map(select(.context == $check)) | length')
if [ "$exists" -eq 0 ]; then
echo " - $check: MISSING"
missing_required=1
else
state=$(echo "$latest_statuses" | jq -r --arg check "$check" '.[] | select(.context == $check) | .state')
echo " - $check: $state"
fi
done
else
echo "No required status checks found for branch $branch"
fi

if [ "$failures" -gt 0 ]; then
echo "❌ One or more status checks failed for PR #$pr - aborting"
exit 1
fi

if [ "$pending" -eq 0 ] && [ "$missing_required" -eq 0 ]; then
echo "✅ All status checks passed for PR #$pr"
break
fi

# sleep and check again
sleep $SLEEP_INTERVAL
ELAPSED=$((ELAPSED + SLEEP_INTERVAL))
if [ "$ELAPSED" -ge "$MAX_WAIT" ]; then
echo "⏱️ Timeout of $MAX_WAIT seconds reached for PR #$pr - aborting"
exit 1
fi

echo "Waiting for status checks to complete (elapsed time: ${ELAPSED}s)..."
done

echo "Waiting for status checks on PR #$pr"
commit_sha=$(gh pr view $pr --json headRefOid --jq '.headRefOid')
echo "Commit SHA for PR #$pr is $commit_sha"

# initial delay to allow statuses to start being reported
echo "Sleeping for initial delay (30s) to allow statuses to be reported..."
sleep 30
ELAPSED=30

while true; do
echo "Polling statuses for PR #$pr (commit $commit_sha)"
statuses=$(curl -s -H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/commits/$commit_sha/statuses")

# get required status checks for the branch
branch=$(gh pr view $pr --json headRefName --jq '.headRefName')
required_checks=$(curl -s -H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/branches/$branch/protection" | \
jq -r '.required_status_checks.contexts[]' 2>/dev/null || echo "")

# process the latest status for each context
latest_statuses=$(echo "$statuses" | jq '[group_by(.context)[] | max_by(.created_at)]')

# count by state
pending=$(echo "$latest_statuses" | jq 'map(select(.state=="pending")) | length')
failures=$(echo "$latest_statuses" | jq 'map(select(.state=="failure" or .state=="error")) | length')
successes=$(echo "$latest_statuses" | jq 'map(select(.state=="success")) | length')
total=$(echo "$latest_statuses" | jq 'length')

# list the current statuses for visibility
echo "$latest_statuses" | jq -r '.[] | " - \(.context): \(.state)"' | sort
echo "Status summary: $pending pending, $failures failures, $successes successes (total: $total)"

# check for required status checks
missing_required=0
if [ ! -z "$required_checks" ]; then
echo "Required status checks for branch $branch:"
echo "$required_checks" | while read -r check; do
exists=$(echo "$latest_statuses" | jq --arg check "$check" 'map(select(.context == $check)) | length')
if [ "$exists" -eq 0 ]; then
echo " - $check: MISSING"
missing_required=1
else
state=$(echo "$latest_statuses" | jq -r --arg check "$check" '.[] | select(.context == $check) | .state')
echo " - $check: $state"
fi
done
else
echo "No required status checks found for branch $branch"
fi

if [ "$failures" -gt 0 ]; then
echo "One or more status checks failed for PR #$pr - aborting"
exit 1
fi

if [ "$pending" -eq 0 ] && [ "$missing_required" -eq 0 ]; then
echo "All status checks passed for PR #$pr"
break
fi

# sleep and check again
sleep $SLEEP_INTERVAL
ELAPSED=$((ELAPSED + SLEEP_INTERVAL))
if [ "$ELAPSED" -ge "$MAX_WAIT" ]; then
echo "Timeout of $MAX_WAIT seconds reached for PR #$pr - aborting"
exit 1
fi

echo "Waiting for status checks to complete (elapsed time: ${ELAPSED}s)..."
done
echo "All PRs have passed their status checks!"
- name: Merge PRs
if: steps.run_metadata.outputs.pr_numbers != ''

echo "PR has passed all status checks!"

- name: Merge PR
if: steps.create_pr.outputs.pr_number != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
IFS=',' read -ra PR_ARRAY <<< "${{ steps.run_metadata.outputs.pr_numbers }}"
for pr in "${PR_ARRAY[@]}"; do
echo "Merging PR #$pr" 1>&2
gh pr merge $pr --squash --delete-branch --repo ${{ github.repository }}
done
pr=${{ steps.create_pr.outputs.pr_number }}
echo "Merging PR #$pr"
gh pr merge $pr --squash --delete-branch --repo ${{ github.repository }}