Skip to content

Security workflow fix#1285

Merged
ChrisTitusTech merged 2 commits into
mainfrom
security-workflow-fix
May 16, 2026
Merged

Security workflow fix#1285
ChrisTitusTech merged 2 commits into
mainfrom
security-workflow-fix

Conversation

@ChrisTitusTech
Copy link
Copy Markdown
Owner

This pull request simplifies and modernizes the project's automation and configuration for development workflows. The most significant changes are the refactoring of the GitHub Actions workflow for issue slash commands, and the removal of OpenCode agent and MCP configuration files, as well as related VSCode settings. These changes streamline the repository by eliminating custom development environment integrations and centralizing issue command logic into a single, maintainable script.

GitHub Actions Workflow Improvements:

  • Refactored .github/workflows/issue-slash-commands.yaml to consolidate multiple shell-based steps into a single github-script action, improving maintainability and security:
    • All slash command handling (/label, /unlabel, /close, /open, /reopen) is now managed in JavaScript, reducing complexity and removing shell interpolation risks.
    • Authorization is now checked at the top of the script, preventing unauthorized users from triggering any actions.
    • The allowlist of permitted users is now maintained in one place within the script.
    • The previous approach using environment variables and multiple steps has been replaced by direct API calls, making the workflow more robust and easier to update.

Removal of OpenCode and MCP Configuration:

  • Deleted .opencode/AGENTS.md, removing agent guidelines and development instructions specific to OpenCode and MCP integration.
  • Deleted .opencode/mcp-config.json, removing all custom MCP server, task, and language integration settings for Rust and Bash, as well as workspace configuration.

Editor Settings Cleanup:

  • Removed .vscode/settings.json, cleaning up editor-specific automation settings that are no longer needed after the removal of OpenCode/MCP integration.

Type of Change

  • New feature
  • Bug fix
  • Documentation update
  • Refactoring
  • Security patch
  • UI/UX improvement

Description

Issues / other PRs related

  • Resolves #

Screenshots (if applicable)

@ChrisTitusTech ChrisTitusTech merged commit 3548a65 into main May 16, 2026
6 checks passed
@ChrisTitusTech ChrisTitusTech deleted the security-workflow-fix branch May 16, 2026 17:58
@Abs313a
Copy link
Copy Markdown
Contributor

Abs313a commented May 16, 2026

  • It now trims the comment into individual lines and only executes commands when a line starts with an explicit command like /label, /unlabel, /close, /open, or /reopen. That prevents normal text such as do not /close this from accidentally triggering actions.

  • It also fixes label parsing. /label bug, /label good first issue, /label 'good first issue', and /label "good first issue" are all handled correctly, with matching quotes stripped safely.

  • Finally, label and unlabel operations are wrapped so failures do not stop later commands. For example, if /unlabel missing-label returns 404, the workflow ignores that and still processes /close. Other label/unlabel errors are recorded and reported after close/open actions finish.

Applies from line 37 through the end of the script in issue-slash-commands.yaml.

            const lines = body
              .split(/\r?\n/)
              .map(line => line.trim())
              .filter(Boolean);

            function parseCommandArg(line, command) {
              const raw = line.slice(command.length).trim();
              const quoted = raw.match(/^(['"])(.+)\1$/);
              return quoted ? quoted[2].trim() : raw;
            }

            const errors = [];

            async function runMutation(name, fn, options = {}) {
              try {
                await fn();
              } catch (error) {
                if (options.ignore404 && error.status === 404) {
                  console.log(`${name}: ignored 404`);
                  return;
                }

                errors.push(`${name}: ${error.status || 'unknown'} ${error.message}`);
                console.log(`${name} failed: ${error.message}`);
              }
            }

            for (const line of lines.filter(line => line.startsWith('/label '))) {
              const labelName = parseCommandArg(line, '/label');

              await runMutation(`add label "${labelName}"`, () =>
                github.rest.issues.addLabels({
                  owner, repo, issue_number: issueNumber,
                  labels: [labelName],
                })
              );
            }

            for (const line of lines.filter(line => line.startsWith('/unlabel '))) {
              const labelName = parseCommandArg(line, '/unlabel');

              await runMutation(
                `remove label "${labelName}"`,
                () =>
                  github.rest.issues.removeLabel({
                    owner, repo, issue_number: issueNumber,
                    name: labelName,
                  }),
                { ignore404: true }
              );
            }

            // /close  (optionally with 'not planned')
            const wantsClose = lines.some(line => line === '/close' || line.startsWith('/close '));
            if (wantsClose) {
              const closeLine = lines.find(line => line === '/close' || line.startsWith('/close '));
              const stateReason = closeLine.includes('not planned') ? 'not_planned' : 'completed';
              console.log(`Closing issue (reason: ${stateReason})`);
              await github.rest.issues.update({
                owner, repo, issue_number: issueNumber,
                state: 'closed',
                state_reason: stateReason,
              });
            }

            // /open  or  /reopen
            const wantsOpen = lines.some(line => line === '/open' || line === '/reopen');
            if (wantsOpen) {
              console.log('Reopening issue');
              await github.rest.issues.update({
                owner, repo, issue_number: issueNumber,
                state: 'open',
              });
            }

            if (errors.length > 0) {
              throw new Error(`One or more label operations failed:\n${errors.join('\n')}`);
            }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants