diff --git a/.github/agents/ci-fixer.agent.md b/.github/agents/cicd-repair.agent.md similarity index 98% rename from .github/agents/ci-fixer.agent.md rename to .github/agents/cicd-repair.agent.md index 433e06b..647fe87 100644 --- a/.github/agents/ci-fixer.agent.md +++ b/.github/agents/cicd-repair.agent.md @@ -12,6 +12,7 @@ If the fix is ambiguous, propose the most likely solution in the PR description. - NEVER ask for clarification or additional information. You are operating autonomously and must make decisions based on the available data. - You MUST open a Pull Request with the proposed fix. If you fail to do so, keep trying with different approaches until successful. +- Use GitHub MCP tools over CLI commands when possible. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f005ec1..80b6416 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,16 +2,14 @@ name: Fake CI on: workflow_dispatch: - # push: - # branches: - # - main + pull_request: + branches: + - main jobs: build: runs-on: ubuntu-latest steps: - # - uses: actions/checkout@v5 - - run: echo "Hello, world!" - run: echo "Hello, world!" - run: exit 1 diff --git a/.github/workflows/copilot-ci-fix.yml b/.github/workflows/copilot-ci-fix.yml index 3ea293c..42bc16a 100644 --- a/.github/workflows/copilot-ci-fix.yml +++ b/.github/workflows/copilot-ci-fix.yml @@ -3,6 +3,8 @@ on: workflows: ['*'] # All workflow failures types: [completed] +permissions: write-all # We need workflow: write + jobs: ci-failure: runs-on: ubuntu-latest @@ -12,7 +14,6 @@ jobs: - uses: austenstone/copilot-cli@main with: copilot-token: ${{ secrets.PAT }} - # enable-all-github-mcp-tools: true mcp-config: | { "mcpServers": { @@ -27,7 +28,7 @@ jobs: } } } - agent: ci-fixer + agent: cicd-repair prompt: | The GitHub Actions workflow run failed. Please analyze the failure and suggest a fix. diff --git a/.github/workflows/copilot-dependabot-update.yml b/.github/workflows/copilot-dependabot-update.yml index 5b67c5c..cc3a802 100644 --- a/.github/workflows/copilot-dependabot-update.yml +++ b/.github/workflows/copilot-dependabot-update.yml @@ -9,13 +9,9 @@ jobs: if: github.event.pull_request.user.login == 'dependabot[bot]' steps: - uses: actions/checkout@v6 - - name: Fetch Dependabot metadata id: metadata uses: dependabot/fetch-metadata@v2 - with: - copilot-token: ${{ secrets.GITHUB_TOKEN }} - - name: Generate dependency analysis with Copilot uses: austenstone/copilot-cli@main env: @@ -47,10 +43,16 @@ jobs: ### 2. Provided Context + #### Dependabot Metadata ```json ${{ toJson(steps.metadata.outputs) }} ``` + #### Event Data + ```event + ${{ toJson(github.event) }} + ``` + ### 3. Your Tasks Based on the context provided above: diff --git a/.github/workflows/copilot-triage.yml b/.github/workflows/copilot-labeler.yml similarity index 57% rename from .github/workflows/copilot-triage.yml rename to .github/workflows/copilot-labeler.yml index 991b5f2..c6c97aa 100644 --- a/.github/workflows/copilot-triage.yml +++ b/.github/workflows/copilot-labeler.yml @@ -1,52 +1,25 @@ on: - workflow_call: - schedule: - - cron: '0 * * * *' # Runs every hour issues: - types: [opened, edited, reopened] + types: [opened] pull_request: + types: [opened] branches: - 'main' - workflow_dispatch: jobs: triage: runs-on: ubuntu-latest timeout-minutes: 7 - outputs: - available_labels: '${{ steps.get_labels.outputs.available_labels }}' - selected_labels: '${{ env.SELECTED_LABELS }}' permissions: contents: 'read' id-token: 'write' issues: 'read' pull-requests: 'read' steps: - - name: 'Get repository labels' - id: get_labels - uses: 'actions/github-script@main' - with: - script: |- - const { data: labels } = await github.rest.issues.listLabelsForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - }); - - if (!labels || labels.length === 0) { - core.setFailed('There are no issue labels in this repository.') - } - - const labelNames = labels.map(label => label.name).sort(); - core.setOutput('available_labels', labelNames.join(',')); - core.info(`Found ${labelNames.length} labels: ${labelNames.join(', ')}`); - return labelNames; - uses: austenstone/copilot-cli@main - if: steps.get_labels.outputs.available_labels != '' env: - GITHUB_TOKEN: '' # Do NOT pass any auth tokens here since this runs on untrusted inputs ISSUE_TITLE: '${{ github.event.issue.title }}' ISSUE_BODY: '${{ github.event.issue.body }}' - AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}' with: copilot-token: ${{ secrets.PAT }} prompt: | @@ -61,11 +34,6 @@ jobs: ## Input Data - **Available Labels** (comma-separated): - ``` - ${{ env.AVAILABLE_LABELS }} - ``` - **Issue Title**: ``` ${{ env.ISSUE_TITLE }} @@ -83,6 +51,8 @@ jobs: ## Steps + 0. Fetch possible labels from the repository. + 1. Review the issue title, issue body, and available labels provided above. 2. Based on the issue title and issue body, classify the issue and choose all appropriate labels from the list of available labels. diff --git a/.github/workflows/copilot-research.yml b/.github/workflows/copilot-research.yml index 67aed3e..3b895a7 100644 --- a/.github/workflows/copilot-research.yml +++ b/.github/workflows/copilot-research.yml @@ -1,6 +1,6 @@ on: issues: - types: [opened, edited, reopened] + types: [opened] jobs: research: diff --git a/.github/workflows/copilot-security-triage.yml b/.github/workflows/copilot-security-triage.yml index 4782b29..6a50537 100644 --- a/.github/workflows/copilot-security-triage.yml +++ b/.github/workflows/copilot-security-triage.yml @@ -9,6 +9,7 @@ jobs: - uses: austenstone/copilot-cli@main with: copilot-token: ${{ secrets.PAT }} + enable-all-github-mcp-tools: true prompt: | ## Role diff --git a/.github/workflows/copilot-usage-report.yml b/.github/workflows/copilot-usage-report.yml index 789511a..654a3fd 100644 --- a/.github/workflows/copilot-usage-report.yml +++ b/.github/workflows/copilot-usage-report.yml @@ -8,6 +8,7 @@ jobs: - uses: austenstone/copilot-cli@main with: copilot-token: ${{ secrets.PAT }} + repo-token: ${{ secrets.PAT }} prompt: | ## Role diff --git a/.github/workflows/test-copilot.yml b/.github/workflows/test-copilot.yml index 2041f4d..5967edc 100644 --- a/.github/workflows/test-copilot.yml +++ b/.github/workflows/test-copilot.yml @@ -6,14 +6,15 @@ jobs: copilot: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: austenstone/copilot-cli@main with: copilot-token: ${{ secrets.PAT }} - enable-all-github-mcp-tools: true prompt: | Who are you? What is your plan? What tools do you have? Will you use them? + + Can you test out some github mcp tools? diff --git a/README.md b/README.md index 079b47e..3d4e5b3 100644 Binary files a/README.md and b/README.md differ diff --git a/action.yml b/action.yml index 2c50e6a..f2b2cbf 100644 --- a/action.yml +++ b/action.yml @@ -17,10 +17,6 @@ inputs: mcp-config: description: 'MCP configuration for GitHub Copilot [Link](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/extend-coding-agent-with-mcp#writing-a-json-configuration-for-mcp-servers)' required: false - default: | - { - "mcpServers": { } - } copilot-config: description: 'Configuration for GitHub Copilot' required: false @@ -34,7 +30,7 @@ inputs: allow-all-tools: description: 'Allow all tools without approval' required: false - default: 'true' + default: true allowed-tools: description: 'Comma-separated list of tools to allow (e.g., "shell(rm),shell(git push)")' required: false @@ -57,7 +53,7 @@ inputs: enable-all-github-mcp-tools: description: 'Enable all GitHub MCP tools' required: false - default: 'false' + default: false resume-session: description: 'Resume from a previous session ID (use "latest" for most recent)' required: false @@ -68,6 +64,13 @@ inputs: agent: description: 'Specify a custom agent to use' required: false + log-level: + description: 'Set the log level (choices: "none", "error", "warning", "info", "debug", "all", "default")' + required: false + default: 'all' + options: + description: 'Additional options to pass to the Copilot CLI (e.g., "--no-custom-instructions --screen-reader --no-color --model gpt-5")' + required: false outputs: logs-path: description: 'Path to the copilot logs directory' @@ -81,146 +84,113 @@ runs: - uses: actions/setup-node@v6 with: node-version: '22' - # - name: Configure Git credentials - # run: | - # git config --global user.email "github-actions[bot]@users.noreply.github.com" - # git config --global user.name "${{ github.workflow }}" - # shell: bash - # - name: Cache Copilot CLI - # uses: actions/cache@v4 - # if: ${{ inputs.cache-cli == 'true' }} - # with: - # path: ~/.npm - # key: ${{ runner.os }}-copilot-cli-${{ inputs.copilot-version }} - # restore-keys: | - # ${{ runner.os }}-copilot-cli- - - name: Install GitHub Copilot CLI + - name: Run GitHub Copilot CLI + id: copilot + shell: bash run: | - echo "::group::Installing GitHub Copilot CLI" + # Script + + echo "::group::Install GitHub Copilot CLI" if [ "$COPILOT_VERSION" = "latest" ]; then npm install -g @github/copilot else npm install -g @github/copilot@$COPILOT_VERSION fi - copilot --version || echo "Warning: Could not get copilot version" + echo "CLI Version: $(copilot --version)" echo "::endgroup::" - shell: bash - env: - COPILOT_VERSION: ${{ inputs.copilot-version }} - - name: Configure Copilot - shell: bash - run: | - echo "::group::Configuring Copilot" - mkdir -p $XDG_CONFIG_HOME/.copilot - # Create base MCP config with GitHub MCP server (comes pre-configured by default) - BASE_MCP_CONFIG='{ - "mcpServers": { } - }' - - # Merge user-provided MCP config with base config - MERGED_MCP_CONFIG=$(echo "$BASE_MCP_CONFIG" | jq --argjson user "$MCP_CONFIG" '.mcpServers += $user.mcpServers') - echo "$MERGED_MCP_CONFIG" > $XDG_CONFIG_HOME/.copilot/mcp-config.json - cat $XDG_CONFIG_HOME/.copilot/mcp-config.json - env: - CONFIG: ${{ inputs.copilot-config }} - MCP_CONFIG: ${{ inputs.mcp-config }} - - name: Run Copilot CLI - id: copilot - shell: bash - run: | - echo "::group::Verifying GitHub CLI authentication" - gh auth status - echo "::endgroup::" + if [ -n "$MCP_CONFIG" ]; then + echo "::group::Configure Copilot MCP" + cat $XDG_CONFIG_HOME/.copilot/mcp-config.json || echo "No existing MCP config found" + mkdir -p $XDG_CONFIG_HOME/.copilot + + BASE_MCP_CONFIG='{ + "mcpServers": { } + }' - set +e # Don't exit on error + MERGED_MCP_CONFIG=$(echo "$BASE_MCP_CONFIG" | jq --argjson user "$MCP_CONFIG" '.mcpServers += $user.mcpServers') + echo "$MERGED_MCP_CONFIG" > $XDG_CONFIG_HOME/.copilot/mcp-config.json + cat $XDG_CONFIG_HOME/.copilot/mcp-config.json + echo "::endgroup::" + fi - # Build args array for safer execution with multi-line prompts - COPILOT_ARGS=(-p "$PROMPT") + echo "::group::Copilot Options" + COPILOT_ARGS="" - # Pre-trust common paths that Copilot might need in CI environment - COPILOT_ARGS+=(--add-dir "/") - - # Add additional trusted directories + COPILOT_ARGS+="--add-dir / " if [ -n "$ADDITIONAL_DIRS" ]; then IFS=',' read -ra DIRS <<< "$ADDITIONAL_DIRS" for dir in "${DIRS[@]}"; do - COPILOT_ARGS+=(--add-dir "$dir") + COPILOT_ARGS+="--add-dir $dir " done fi - - # Add disabled MCP servers if [ -n "$DISABLE_MCP_SERVERS" ]; then IFS=',' read -ra SERVERS <<< "$DISABLE_MCP_SERVERS" for server in "${SERVERS[@]}"; do - COPILOT_ARGS+=(--disable-mcp-server "$server") + COPILOT_ARGS+="--disable-mcp-server $server " done fi - - # Enable all GitHub MCP tools if [ "$ENABLE_ALL_GITHUB_MCP_TOOLS" = "true" ]; then - COPILOT_ARGS+=(--enable-all-github-mcp-tools) + COPILOT_ARGS+="--enable-all-github-mcp-tools " fi - - # Add tool permissions if [ "$ALLOW_ALL_TOOLS" = "true" ]; then - COPILOT_ARGS+=(--allow-all-tools) + COPILOT_ARGS+="--allow-all-tools " fi - - # Add allowed tools if [ -n "$ALLOWED_TOOLS" ]; then IFS=',' read -ra TOOLS <<< "$ALLOWED_TOOLS" for tool in "${TOOLS[@]}"; do - COPILOT_ARGS+=(--allow-tool "$tool") + COPILOT_ARGS+="--allow-tool $tool " done fi - - # Add denied tools if [ -n "$DENIED_TOOLS" ]; then IFS=',' read -ra TOOLS <<< "$DENIED_TOOLS" for tool in "${TOOLS[@]}"; do - COPILOT_ARGS+=(--deny-tool "$tool") + COPILOT_ARGS+="--deny-tool $tool " done fi - - # Add model selection if [ -n "$MODEL" ]; then - COPILOT_ARGS+=(--model "$MODEL") + COPILOT_ARGS+="--model $MODEL " fi - - # Add agent selection if [ -n "$AGENT" ]; then - COPILOT_ARGS+=(--agent "$AGENT") + COPILOT_ARGS+="--agent $AGENT " fi - - # Add resume session if [ -n "$RESUME_SESSION" ]; then if [ "$RESUME_SESSION" = "latest" ]; then - COPILOT_ARGS+=(--continue) + COPILOT_ARGS+="--continue " else - COPILOT_ARGS+=(--resume "$RESUME_SESSION") + COPILOT_ARGS+="--resume $RESUME_SESSION " fi fi - - # Add other options - COPILOT_ARGS+=(--log-dir "$HOME/.copilot/logs") - - # Debug: Show the full command being executed - echo "::group::GitHub Copilot CLI command" - printf '%s\n' "${COPILOT_ARGS[@]}" + if [ -n "$LOG_LEVEL" ]; then + COPILOT_ARGS+="--log-level $LOG_LEVEL " + fi + if [ -n "$EXTRA_ARGS" ]; then + COPILOT_ARGS+="$EXTRA_ARGS " + fi + COPILOT_ARGS+="--log-dir $HOME/.copilot/logs" + + echo "$COPILOT_ARGS" echo "::endgroup::" - - # Execute the command with array expansion for proper quoting - copilot "${COPILOT_ARGS[@]}" + + echo "::group::Prompt" + echo "$PROMPT" + echo "::endgroup::" + + echo "::group::Run Copilot CLI" + set +e + copilot -p "$PROMPT" $COPILOT_ARGS EXIT_CODE=$? - - # Set outputs + echo "::endgroup::" + echo "logs_path=$HOME/.copilot/logs" >> $GITHUB_OUTPUT echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT env: GH_TOKEN: ${{ inputs.repo-token || inputs.copilot-token }} COPILOT_GITHUB_TOKEN: ${{ inputs.copilot-token }} PROMPT: ${{ inputs.prompt }} + COPILOT_VERSION: ${{ inputs.copilot-version }} + CONFIG: ${{ inputs.copilot-config }} + MCP_CONFIG: ${{ inputs.mcp-config }} ALLOW_ALL_TOOLS: ${{ inputs.allow-all-tools }} ALLOWED_TOOLS: ${{ inputs.allowed-tools }} DENIED_TOOLS: ${{ inputs.denied-tools }} @@ -230,8 +200,8 @@ runs: DISABLE_MCP_SERVERS: ${{ inputs.disable-mcp-servers }} ENABLE_ALL_GITHUB_MCP_TOOLS: ${{ inputs.enable-all-github-mcp-tools }} RESUME_SESSION: ${{ inputs.resume-session }} - TEMP: ${{ runner.temp }} - GITHUB_WORKSPACE: ${{ github.workspace }} + LOG_LEVEL: ${{ inputs.log-level }} + EXTRA_ARGS: ${{ inputs.options }} - name: Upload Copilot Artifacts uses: actions/upload-artifact@v4 if: ${{ always() && inputs.upload-artifact == 'true' }}