df723d768f
* Use Actions token for DevFlow Copilot auth Grant the review job Copilot request permission and remove the user token fallback so organization-billed GitHub Actions authentication is exercised directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9fa4e9c-c32d-42fb-8ee4-4772473e6479 * Enable DevFlow PR review comparisons Pass the dedicated DevFlow repository token for A/B artifact branches while keeping the built-in Actions token as the only Copilot credential. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9fa4e9c-c32d-42fb-8ee4-4772473e6479 * Allow team-triggered DevFlow reviews Accept an exact @devflow /review PR comment only from organization members, verify the commenter against the developer team with the GitHub App, and react after authorization. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9fa4e9c-c32d-42fb-8ee4-4772473e6479 * Use Actions token for issue triage Copilot auth Grant the triage job Copilot request permission and remove the user PAT so issue reproduction exercises organization-billed GitHub Actions authentication. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9fa4e9c-c32d-42fb-8ee4-4772473e6479 * Use tracked DevFlow CI model configuration Point PR review and issue triage runs at the dashboard's tracked GPT-5.6 Sol and Claude Opus 5 model configuration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9fa4e9c-c32d-42fb-8ee4-4772473e6479 * Use Actions tokens for Copilot test workflows Remove Copilot PAT secrets from integration and sample validation workflows, grant Copilot request permission at the required caller and job boundaries, and preserve the environment variable expected by the tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9fa4e9c-c32d-42fb-8ee4-4772473e6479 --------- Copilot-Session: d9fa4e9c-c32d-42fb-8ee4-4772473e6479
241 lines
8.9 KiB
YAML
241 lines
8.9 KiB
YAML
name: Issue Triage
|
|
|
|
on:
|
|
issues:
|
|
types: [opened, typed]
|
|
workflow_dispatch:
|
|
inputs:
|
|
issue_number:
|
|
description: Issue number to triage
|
|
required: true
|
|
type: string
|
|
|
|
permissions:
|
|
contents: read
|
|
issues: write
|
|
id-token: write
|
|
|
|
concurrency:
|
|
group: >-
|
|
issue-triage-${{ github.repository }}-${{
|
|
github.event_name == 'workflow_dispatch' && inputs.issue_number
|
|
|| github.event.issue.type.name == 'Bug' && github.event.issue.number
|
|
|| github.run_id
|
|
}}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
DEVFLOW_REPOSITORY: ${{ vars.DF_REPO }}
|
|
DEVFLOW_REF: main
|
|
TARGET_REPO_PATH: ${{ github.workspace }}/target-repo
|
|
DEVFLOW_PATH: ${{ github.workspace }}/devflow
|
|
MODEL_CONFIG_PATH: ${{ github.workspace }}/devflow/config.ci.yaml
|
|
|
|
jobs:
|
|
team_check:
|
|
runs-on: ubuntu-latest
|
|
environment: github-app-auth
|
|
if: >-
|
|
${{
|
|
github.event_name == 'workflow_dispatch'
|
|
|| github.event.issue.type.name == 'Bug'
|
|
}}
|
|
outputs:
|
|
is_team_member: ${{ steps.check.outputs.is_team_member }}
|
|
issue_number: ${{ steps.issue.outputs.issue_number }}
|
|
repo: ${{ steps.issue.outputs.repo }}
|
|
steps:
|
|
- name: Resolve issue metadata
|
|
id: issue
|
|
shell: bash
|
|
env:
|
|
ISSUE_NUMBER: >-
|
|
${{
|
|
github.event_name == 'workflow_dispatch' && inputs.issue_number
|
|
|| github.event.issue.number
|
|
}}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
issue_number="${ISSUE_NUMBER}"
|
|
|
|
if [[ ! "$issue_number" =~ ^[1-9][0-9]*$ ]]; then
|
|
echo "Could not determine issue number from event payload or manual input." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "issue_number=${issue_number}" >> "$GITHUB_OUTPUT"
|
|
echo "repo=${GITHUB_REPOSITORY}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Checkout scripts
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
sparse-checkout: |
|
|
.github/actions/github-app-token
|
|
.github/scripts
|
|
fetch-depth: 1
|
|
persist-credentials: false
|
|
|
|
- name: Get GitHub automation token
|
|
id: github-auth
|
|
uses: ./.github/actions/github-app-token
|
|
with:
|
|
mode: ${{ vars.GH_APP_AUTH_MODE }}
|
|
azure-client-id: ${{ secrets.GH_APP_AZURE_CLIENT_ID }}
|
|
azure-tenant-id: ${{ secrets.GH_APP_AZURE_TENANT_ID }}
|
|
azure-subscription-id: ${{ secrets.GH_APP_AZURE_SUBSCRIPTION_ID }}
|
|
key-vault-name: ${{ secrets.GH_APP_KEY_VAULT_NAME }}
|
|
key-name: ${{ secrets.GH_APP_KEY_NAME }}
|
|
github-app-client-id: ${{ secrets.GH_APP_CLIENT_ID }}
|
|
github-app-installation-id: ${{ secrets.GH_APP_INSTALLATION_ID }}
|
|
repository: ${{ github.repository }}
|
|
fallback-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
|
|
|
|
- name: Check issue author team membership
|
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
|
id: check
|
|
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
|
|
env:
|
|
TEAM_NAME: ${{ secrets.DEVELOPER_TEAM }}
|
|
ISSUE_NUMBER: ${{ steps.issue.outputs.issue_number }}
|
|
with:
|
|
github-token: ${{ steps.github-auth.outputs.token }}
|
|
script: |
|
|
const checkTeamMembership = require('./.github/scripts/check_team_membership.js');
|
|
const { author, isTeamMember } = await checkTeamMembership({
|
|
github,
|
|
context,
|
|
core,
|
|
teamSlug: process.env.TEAM_NAME,
|
|
issueNumber: process.env.ISSUE_NUMBER,
|
|
});
|
|
core.setOutput('is_team_member', isTeamMember ? 'true' : 'false');
|
|
if (isTeamMember) {
|
|
core.info(`Author ${author} is a team member; skipping auto-triage.`);
|
|
} else {
|
|
core.info(`Author ${author} is not a team member; proceeding with triage.`);
|
|
}
|
|
|
|
triage:
|
|
runs-on: ubuntu-latest
|
|
needs: team_check
|
|
if: >-
|
|
${{
|
|
github.event_name == 'workflow_dispatch'
|
|
|| needs.team_check.outputs.is_team_member == 'false'
|
|
}}
|
|
environment: integration
|
|
permissions:
|
|
copilot-requests: write
|
|
contents: read
|
|
id-token: write
|
|
issues: write
|
|
timeout-minutes: 60
|
|
|
|
steps:
|
|
# Safe checkout: base repo only.
|
|
- name: Checkout target repo base
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
path: target-repo
|
|
|
|
# Private DevFlow (maf-dashboard) checkout.
|
|
- name: Checkout DevFlow
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
repository: ${{ env.DEVFLOW_REPOSITORY }}
|
|
ref: ${{ env.DEVFLOW_REF }}
|
|
token: ${{ secrets.DEVFLOW_TOKEN }}
|
|
fetch-depth: 1
|
|
persist-credentials: false
|
|
path: devflow
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
|
with:
|
|
python-version: "3.13"
|
|
|
|
- name: Set up uv
|
|
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
with:
|
|
version: "0.11.x"
|
|
enable-cache: true
|
|
|
|
- name: Install DevFlow dependencies
|
|
working-directory: ${{ env.DEVFLOW_PATH }}
|
|
run: uv sync --frozen
|
|
|
|
- name: Azure CLI Login
|
|
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
|
|
- name: Classify issue relevance
|
|
id: spam
|
|
working-directory: ${{ env.DEVFLOW_PATH }}
|
|
env:
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
DEVFLOW_TOKEN: ${{ secrets.DEVFLOW_TOKEN }}
|
|
SK_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
|
AGENT_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
|
ISSUE_REPO: ${{ needs.team_check.outputs.repo }}
|
|
ISSUE_NUMBER: ${{ needs.team_check.outputs.issue_number }}
|
|
run: |
|
|
uv run python scripts/classify_issue_spam.py \
|
|
--repo "$ISSUE_REPO" \
|
|
--issue-number "$ISSUE_NUMBER" \
|
|
--repo-path "${TARGET_REPO_PATH}" \
|
|
--apply-labels
|
|
|
|
- name: Stop after spam gate
|
|
if: ${{ steps.spam.outputs.allow_triage != 'true' }}
|
|
shell: bash
|
|
run: |
|
|
echo "Stopping: issue triage preflight did not allow automation."
|
|
exit 1
|
|
|
|
- name: Reproduce reported issue
|
|
if: ${{ steps.spam.outputs.allow_triage == 'true' }}
|
|
id: repro
|
|
working-directory: ${{ env.DEVFLOW_PATH }}
|
|
env:
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
# Not seen by the agent prompt; used only to push a paper-trail
|
|
# branch back to maf-dashboard at run end.
|
|
DEVFLOW_TOKEN: ${{ secrets.DEVFLOW_TOKEN }}
|
|
SK_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
|
AGENT_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
|
ISSUE_REPO: ${{ needs.team_check.outputs.repo }}
|
|
ISSUE_NUMBER: ${{ needs.team_check.outputs.issue_number }}
|
|
# Model-provider settings for generated repro code. Never enter the
|
|
# agent prompt; consumed by SDK constructors via os.environ. Azure
|
|
# OpenAI and Foundry auth via AAD from the azure/login step above.
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI__APIKEY }}
|
|
OPENAI_CHAT_COMPLETION_MODEL: ${{ vars.OPENAI__CHATMODELID }}
|
|
OPENAI_CHAT_MODEL: ${{ vars.OPENAI__RESPONSESMODELID }}
|
|
OPENAI_MODEL: ${{ vars.OPENAI__RESPONSESMODELID }}
|
|
OPENAI_EMBEDDING_MODEL: ${{ vars.OPENAI_EMBEDDING_MODEL_ID }}
|
|
AZURE_OPENAI_ENDPOINT: ${{ vars.AZUREOPENAI__ENDPOINT }}
|
|
AZURE_OPENAI_CHAT_COMPLETION_MODEL: ${{ vars.AZUREOPENAI__CHATDEPLOYMENTNAME }}
|
|
AZURE_OPENAI_CHAT_MODEL: ${{ vars.AZUREOPENAI__RESPONSESDEPLOYMENTNAME }}
|
|
AZURE_OPENAI_MODEL: ${{ vars.AZUREOPENAI__RESPONSESDEPLOYMENTNAME }}
|
|
AZURE_OPENAI_EMBEDDING_MODEL: ${{ vars.AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME }}
|
|
FOUNDRY_PROJECT_ENDPOINT: ${{ vars.FOUNDRY_PROJECT_ENDPOINT }}
|
|
FOUNDRY_MODEL: ${{ vars.FOUNDRY_MODEL }}
|
|
FOUNDRY_AGENT_NAME: ${{ vars.FOUNDRY_AGENT_NAME }}
|
|
FOUNDRY_AGENT_VERSION: ${{ vars.FOUNDRY_AGENT_VERSION }}
|
|
FOUNDRY_MODELS_ENDPOINT: ${{ vars.FOUNDRY_MODELS_ENDPOINT || '' }}
|
|
FOUNDRY_MODELS_API_KEY: ${{ secrets.FOUNDRY_MODELS_API_KEY || '' }}
|
|
FOUNDRY_EMBEDDING_MODEL: ${{ vars.FOUNDRY_EMBEDDING_MODEL || '' }}
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
ANTHROPIC_CHAT_MODEL: ${{ vars.ANTHROPIC_CHAT_MODEL_ID }}
|
|
run: |
|
|
uv run python scripts/trigger_issue_repro.py \
|
|
--repo "$ISSUE_REPO" \
|
|
--issue-number "$ISSUE_NUMBER" \
|
|
--github-username "$GITHUB_ACTOR"
|