Files
openobserve/.github/workflows/auto-assign-metadata.yml
T

271 lines
12 KiB
YAML

name: Auto Assign Metadata
on:
issues:
types: [opened]
# pull_request_target runs with base-repo secrets for fork PRs — safe as long
# as no actions/checkout step is added without pinning ref to the base branch.
pull_request_target:
types: [opened, ready_for_review]
permissions: {}
env:
PROJECT_NUMBER: "19"
jobs:
auto-assign:
runs-on: ubuntu-latest
steps:
# ── Classify creator: team | internal | stranger ──
- name: Classify creator
id: classify
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
ORG: ${{ github.repository_owner }}
CREATOR: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.user.login || github.event.issue.user.login }}
run: |
ALLOWLIST=" bjp232004 hengfeiyang prabhatsharma uddhavdave oasisk haohuaijin Subhra264 Loaki07 007harshmahajan chaitanya-sistla ktx-kirtan omkarK06 ktx-vaidehi ktx-abhay neha00290 ktx-akshay ktx-sadhna nikhilsaikethe YashodhanJoshi1 ktx-riya mmosarafO2 Shrinath-O2 ktx-mihir vamsikarthikr pr1sm8 "
CREATOR_LOWER=$(echo "$CREATOR" | tr '[:upper:]' '[:lower:]')
ALLOWLIST_LOWER=$(echo "$ALLOWLIST" | tr '[:upper:]' '[:lower:]')
if echo "$ALLOWLIST_LOWER" | grep -q " $CREATOR_LOWER "; then
echo "category=team" >> "$GITHUB_OUTPUT"
echo "Creator $CREATOR is on the engineering team"
elif gh api "orgs/$ORG/members/$CREATOR" --silent 2>/dev/null; then
echo "category=internal" >> "$GITHUB_OUTPUT"
echo "Creator $CREATOR is an internal member (not engineering team) — skipping"
else
echo "category=stranger" >> "$GITHUB_OUTPUT"
echo "Creator $CREATOR is an external contributor"
fi
# ── PR: assign creator ──
- name: Assign PR creator
if: github.event_name == 'pull_request_target' && steps.classify.outputs.category == 'team'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
CREATOR: ${{ github.event.pull_request.user.login }}
run: |
gh pr edit "$NUMBER" --add-assignee "$CREATOR" \
&& echo "Assigned $CREATOR to PR #$NUMBER" \
|| echo "::warning::Could not assign $CREATOR to PR #$NUMBER"
# ── PR: add lowest open milestone (skip drafts) ──
- name: Add milestone to PR
if: github.event_name == 'pull_request_target' && steps.classify.outputs.category == 'team' && github.event.pull_request.draft == false && github.event.pull_request.base.ref == 'main'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
run: |
CURRENT=$(gh api "repos/$GH_REPO/pulls/$NUMBER" --jq '.milestone.title // empty')
if [ -n "$CURRENT" ]; then
echo "Milestone already set to '$CURRENT' — skipping"
exit 0
fi
MILESTONE=$(gh api "repos/$GH_REPO/milestones?state=open&per_page=100" --jq '
[.[] | select(.title != "Backlog")] |
map({
title: .title,
due_ts: (if .due_on then (.due_on | fromdateiso8601) else null end),
sort_key: ([.title | scan("[0-9]+")] | map(tonumber))
}) |
map(select(.sort_key | length > 0)) |
sort_by(.sort_key) |
if length == 0 then empty
elif (.[0].due_ts != null and .[0].due_ts < now) then (.[1].title // .[0].title)
else .[0].title
end')
if [ -n "$MILESTONE" ]; then
gh pr edit "$NUMBER" -m "$MILESTONE" \
&& echo "Set milestone: $MILESTONE" \
|| echo "::warning::Could not set milestone $MILESTONE"
else
echo "::warning::No open milestones found"
fi
# ── PR: add to project ──
- name: Add PR to project
if: github.event_name == 'pull_request_target' && steps.classify.outputs.category == 'team'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
NODE_ID: ${{ github.event.pull_request.node_id }}
ORG: ${{ github.repository_owner }}
run: |
PROJECT_ID=$(gh api graphql \
-f query='query($org:String!,$num:Int!){organization(login:$org){projectV2(number:$num){id}}}' \
-F org="$ORG" -F num="$PROJECT_NUMBER" \
--jq '.data.organization.projectV2.id')
[ -n "$PROJECT_ID" ] || { echo "::warning::Project not found — check PROJECT_NUMBER and token scope"; exit 0; }
gh api graphql \
-f query='mutation($project:ID!,$content:ID!){addProjectV2ItemById(input:{projectId:$project,contentId:$content}){item{id}}}' \
-f project="$PROJECT_ID" \
-f content="$NODE_ID" \
&& echo "Added PR to project" \
|| echo "::warning::Could not add PR to project"
# ── Issue: assign creator if unassigned ──
- name: Assign issue creator
if: github.event_name == 'issues' && steps.classify.outputs.category == 'team'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.issue.number }}
CREATOR: ${{ github.event.issue.user.login }}
run: |
ASSIGNEE_COUNT=$(gh api "repos/$GH_REPO/issues/$NUMBER" --jq '.assignees | length')
if [ "$ASSIGNEE_COUNT" -eq 0 ]; then
gh issue edit "$NUMBER" --add-assignee "$CREATOR" \
&& echo "Assigned $CREATOR to issue #$NUMBER" \
|| echo "::warning::Could not assign $CREATOR to issue #$NUMBER"
else
echo "Issue already has assignees — skipping"
fi
# ── Issue: add lowest open milestone ──
- name: Add milestone to issue
if: github.event_name == 'issues' && steps.classify.outputs.category == 'team'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.issue.number }}
run: |
CURRENT=$(gh api "repos/$GH_REPO/issues/$NUMBER" --jq '.milestone.title // empty')
if [ -n "$CURRENT" ]; then
echo "Milestone already set to '$CURRENT' — skipping"
exit 0
fi
MILESTONE=$(gh api "repos/$GH_REPO/milestones?state=open&per_page=100" --jq '
[.[] | select(.title != "Backlog")] |
map({
title: .title,
due_ts: (if .due_on then (.due_on | fromdateiso8601) else null end),
sort_key: ([.title | scan("[0-9]+")] | map(tonumber))
}) |
map(select(.sort_key | length > 0)) |
sort_by(.sort_key) |
if length == 0 then empty
elif (.[0].due_ts != null and .[0].due_ts < now) then (.[1].title // .[0].title)
else .[0].title
end')
if [ -n "$MILESTONE" ]; then
gh issue edit "$NUMBER" -m "$MILESTONE" \
&& echo "Set milestone: $MILESTONE" \
|| echo "::warning::Could not set milestone $MILESTONE"
else
echo "::warning::No open milestones found"
fi
# ── Issue: add to project ──
- name: Add issue to project
id: add_issue_to_project
if: github.event_name == 'issues' && steps.classify.outputs.category == 'team'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
NODE_ID: ${{ github.event.issue.node_id }}
ORG: ${{ github.repository_owner }}
run: |
PROJECT_ID=$(gh api graphql \
-f query='query($org:String!,$num:Int!){organization(login:$org){projectV2(number:$num){id}}}' \
-F org="$ORG" -F num="$PROJECT_NUMBER" \
--jq '.data.organization.projectV2.id')
[ -n "$PROJECT_ID" ] || { echo "::warning::Project not found — check PROJECT_NUMBER and token scope"; exit 0; }
ITEM_ID=$(gh api graphql \
-f query='mutation($project:ID!,$content:ID!){addProjectV2ItemById(input:{projectId:$project,contentId:$content}){item{id}}}' \
-f project="$PROJECT_ID" \
-f content="$NODE_ID" \
--jq '.data.addProjectV2ItemById.item.id')
if [ -n "$ITEM_ID" ]; then
echo "Added issue to project (item: $ITEM_ID)"
echo "item_id=$ITEM_ID" >> "$GITHUB_OUTPUT"
echo "project_id=$PROJECT_ID" >> "$GITHUB_OUTPUT"
else
echo "::warning::Could not add issue to project"
fi
# ── Issue: set start date ──
- name: Set start date on issue
if: github.event_name == 'issues' && steps.classify.outputs.category == 'team' && steps.add_issue_to_project.outputs.item_id != ''
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
ORG: ${{ github.repository_owner }}
ITEM_ID: ${{ steps.add_issue_to_project.outputs.item_id }}
PROJECT_ID: ${{ steps.add_issue_to_project.outputs.project_id }}
run: |
TODAY=$(date -u +%Y-%m-%d)
FIELD_ID=$(gh api graphql \
-f query='query($project:ID!){node(id:$project){... on ProjectV2{fields(first:30){nodes{... on ProjectV2Field{id name}}}}}}' \
-f project="$PROJECT_ID" \
--jq '[.data.node.fields.nodes[] | select(.name | ascii_downcase == "start date")] | .[0].id // empty')
[ -n "$FIELD_ID" ] || { echo "::warning::Start date field not found in project"; exit 0; }
MUTATION_OUT=$(gh api graphql \
-f query='mutation($project:ID!,$item:ID!,$field:ID!,$date:Date!){updateProjectV2ItemFieldValue(input:{projectId:$project,itemId:$item,fieldId:$field,value:{date:$date}}){projectV2Item{id}}}' \
-f project="$PROJECT_ID" \
-f item="$ITEM_ID" \
-f field="$FIELD_ID" \
-f date="$TODAY" 2>&1) \
&& echo "Set start date to $TODAY" \
|| echo "::warning::Could not set start date: $MUTATION_OUT"
# ── Stranger: assign issue to Shrinath + Manas ──
- name: Assign stranger issue
if: github.event_name == 'issues' && steps.classify.outputs.category == 'stranger'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.issue.number }}
run: |
gh issue edit "$NUMBER" --add-assignee "simranquirky" \
&& echo "Assigned simranquirky to stranger issue #$NUMBER" \
|| echo "::warning::Could not assign to stranger issue #$NUMBER"
# ── Stranger: assign PR to Ashish + label as community (label skips bots) ──
- name: Assign and label stranger PR
if: github.event_name == 'pull_request_target' && steps.classify.outputs.category == 'stranger'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
USER_TYPE: ${{ github.event.pull_request.user.type }}
run: |
gh pr edit "$NUMBER" --add-assignee "oasisk" \
&& echo "Assigned oasisk to stranger PR #$NUMBER" \
|| echo "::warning::Could not assign to stranger PR #$NUMBER"
if [ "$USER_TYPE" != "Bot" ]; then
gh pr edit "$NUMBER" --add-label "community" \
&& echo "Labeled stranger PR #$NUMBER as community" \
|| echo "::warning::Could not label stranger PR #$NUMBER"
fi
# ── Dependabot: label ready-for-ci to unlock gated CI, approve any held runs ──
- name: Enable CI for dependabot PR
if: github.event_name == 'pull_request_target' && github.event.pull_request.user.login == 'dependabot[bot]'
env:
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
gh pr edit "$NUMBER" --add-label "ready-for-ci" \
&& echo "Labeled dependabot PR #$NUMBER with ready-for-ci" \
|| echo "::warning::Could not label dependabot PR #$NUMBER"
for id in $(gh api "repos/$GH_REPO/actions/runs?head_sha=$HEAD_SHA&status=action_required" --jq '.workflow_runs[].id'); do
gh api -X POST "repos/$GH_REPO/actions/runs/$id/approve" \
&& echo "Approved held run $id" \
|| echo "::warning::Could not approve run $id"
done