@@ -563,9 +563,36 @@ jobs:
563563 exit 1
564564 fi
565565
566+ # Resolve (or create) a team label named after the repository, so each created
567+ # issue is tagged with its source repo (e.g. "sourcebot-dev/sourcebot").
568+ REPO_LABEL_QUERY='query($teamId: String!, $name: String!) { team(id: $teamId) { labels(filter: { name: { eq: $name } }) { nodes { id } } } }'
569+ REPO_LABEL_PAYLOAD=$(jq -n --arg query "$REPO_LABEL_QUERY" --arg teamId "$TEAM_UUID" --arg name "$REPOSITORY" \
570+ '{query: $query, variables: {teamId: $teamId, name: $name}}')
571+ REPO_LABEL_RESPONSE=$(curl -s -X POST https://api.linear.app/graphql \
572+ -H "Content-Type: application/json" \
573+ -H "Authorization: $LINEAR_API_KEY" \
574+ -d "$REPO_LABEL_PAYLOAD")
575+ REPO_LABEL_ID=$(echo "$REPO_LABEL_RESPONSE" | jq -r '.data.team.labels.nodes[0].id // empty')
576+
577+ if [ -z "$REPO_LABEL_ID" ]; then
578+ echo "No '$REPOSITORY' label in Linear team — creating it."
579+ CREATE_LABEL_MUTATION='mutation($teamId: String!, $name: String!) { issueLabelCreate(input: { teamId: $teamId, name: $name }) { success issueLabel { id } } }'
580+ CREATE_LABEL_PAYLOAD=$(jq -n --arg query "$CREATE_LABEL_MUTATION" --arg teamId "$TEAM_UUID" --arg name "$REPOSITORY" \
581+ '{query: $query, variables: {teamId: $teamId, name: $name}}')
582+ CREATE_LABEL_RESPONSE=$(curl -s -X POST https://api.linear.app/graphql \
583+ -H "Content-Type: application/json" \
584+ -H "Authorization: $LINEAR_API_KEY" \
585+ -d "$CREATE_LABEL_PAYLOAD")
586+ REPO_LABEL_ID=$(echo "$CREATE_LABEL_RESPONSE" | jq -r '.data.issueLabelCreate.issueLabel.id // empty')
587+ if [ -z "$REPO_LABEL_ID" ]; then
588+ echo "::warning::Could not create '$REPOSITORY' label: $(echo "$CREATE_LABEL_RESPONSE" | jq -c '.errors // .')"
589+ fi
590+ fi
591+
566592 {
567593 echo "team_uuid=$TEAM_UUID"
568594 echo "label_id=$LABEL_ID"
595+ echo "repo_label_id=$REPO_LABEL_ID"
569596 echo "state_id=$STATE_ID"
570597 echo "viewer_id=$VIEWER_ID"
571598 } >> "$GITHUB_OUTPUT"
@@ -644,17 +671,22 @@ jobs:
644671 REPOSITORY : ${{ github.repository }}
645672 TEAM_UUID : ${{ steps.match.outputs.team_uuid }}
646673 LABEL_ID : ${{ steps.match.outputs.label_id }}
674+ REPO_LABEL_ID : ${{ steps.match.outputs.repo_label_id }}
647675 STATE_ID : ${{ steps.match.outputs.state_id }}
648676 VIEWER_ID : ${{ steps.match.outputs.viewer_id }}
649677 run : |
650678 set -uo pipefail
651- # Team UUID, "CVE" label, "Triage" state, and the API key owner's user ID were
652- # already resolved by the "Match existing Linear issues" step and passed in as env.
679+ # Team UUID, the "CVE" + repository labels, "Triage" state, and the API key
680+ # owner's user ID were already resolved by the "Match existing Linear issues"
681+ # step and passed in as env.
653682 STRUCTURED_OUTPUT=$(cat findings.json)
654683
655684 if [ -z "$LABEL_ID" ]; then
656685 echo "::warning::Could not find 'CVE' label in Linear team. Creating issues without label."
657686 fi
687+ if [ -z "$REPO_LABEL_ID" ]; then
688+ echo "::warning::Could not resolve '$REPOSITORY' repository label. Creating issues without it."
689+ fi
658690 if [ -z "$STATE_ID" ]; then
659691 echo "::warning::Could not find 'Triage' state in Linear team. Using default state."
660692 fi
@@ -756,8 +788,10 @@ jobs:
756788 --argjson priority "$PRIORITY" \
757789 '{teamId: $teamId, title: $title, description: $desc, priority: $priority}')
758790
759- if [ -n "$LABEL_ID" ]; then
760- VARIABLES=$(echo "$VARIABLES" | jq --arg lid "$LABEL_ID" '. + {labelIds: [$lid]}')
791+ # Attach the "CVE" label and the repository label (dropping any that failed to resolve).
792+ LABEL_IDS=$(jq -n --arg cve "$LABEL_ID" --arg repo "$REPO_LABEL_ID" '[$cve, $repo] | map(select(. != ""))')
793+ if [ "$(echo "$LABEL_IDS" | jq 'length')" -gt 0 ]; then
794+ VARIABLES=$(echo "$VARIABLES" | jq --argjson lids "$LABEL_IDS" '. + {labelIds: $lids}')
761795 fi
762796 if [ -n "$STATE_ID" ]; then
763797 VARIABLES=$(echo "$VARIABLES" | jq --arg sid "$STATE_ID" '. + {stateId: $sid}')
0 commit comments