Skip to content

Conversation

@beNative
Copy link
Owner

Summary

  • add a CI tab to the repository form so Git projects can browse .github/workflows files, edit YAML, fork recommended templates, and push workflow commits without leaving the modal
  • enhance the project intelligence service to recommend workflow templates and expose new IPC helpers to list, read, write, create, validate, and commit workflow files
  • stream workflow validation logs through the existing task log panel by delegating to yamllint and act, and document the new capability in the changelog

Testing

  • npm test

Codex Task

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3434 to +3453
const loadWorkflowFile = useCallback(async (relativePath: string) => {
if (!repository?.localPath || !window.electronAPI?.readWorkflowFile) {
return;
}
setIsWorkflowLoading(true);
setWorkflowError(null);
try {
const result = await window.electronAPI.readWorkflowFile({ repoPath: repository.localPath, relativePath });
if (result?.success && typeof result.content === 'string') {
setWorkflowEditorContent(result.content);
setWorkflowOriginalContent(result.content);
} else {
setWorkflowError(result?.error || 'Unable to load workflow.');
}
} catch (error: any) {
logger.error('Failed to read workflow file', { repoId: repository?.id ?? null, relativePath, error: error?.message || error });
setWorkflowError(error?.message || 'Unable to read workflow.');
} finally {
setIsWorkflowLoading(false);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard workflow editor against stale loads

When two workflow files are selected back‑to‑back, both loadWorkflowFile calls run concurrently and each one blindly writes its result into the editor once the IPC read resolves (lines 3434‑3453). There is no check that the file whose contents just arrived is still the one shown in the UI. If the slower request finishes last, the editor will display the contents of the previously selected workflow while the header still shows the new file, so any edits/saves are applied to the wrong file. Please gate the state updates on the current selection (e.g. compare relativePath with selectedWorkflowPathRef.current or cancel the previous load) so that stale reads cannot clobber the active document.

Useful? React with 👍 / 👎.

Comment on lines +1696 to +1707
ipcMain.handle('commit-workflow-files', async (_event, { repo, filePaths, message }: { repo: Repository; filePaths: string[]; message: string }): Promise<{ success: boolean; error?: string }> => {
if (!repo || repo.vcs !== VcsTypeEnum.Git) {
return { success: false, error: 'Workflow commits are only supported for Git repositories.' };
}
try {
const settings = await readSettings();
const gitCmd = getExecutableCommand(VcsTypeEnum.Git, settings);
const sanitized = filePaths.map(fp => resolveWorkflowPath(repo.localPath, fp).relative);
const quotedFiles = sanitized.map(fp => `"${fp.replace(/"/g, '\\"')}"`).join(' ');
await execAsync(`${gitCmd} add ${quotedFiles}`, { cwd: repo.localPath });
await execAsync(`${gitCmd} commit -m "${message.replace(/"/g, '\\"')}"`, { cwd: repo.localPath });
await execAsync(`${gitCmd} push`, { cwd: repo.localPath });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Commit message allows shell injection

The workflow commit handler builds shell commands with interpolated user input: execAsync(${gitCmd} commit -m "${message.replace(/"/g, '\"')}", …) (electron/main.ts lines 1696‑1707). Because execAsync uses child_process.exec, the command runs through /bin/sh, so characters like ` or $() in the commit message will be evaluated by the shell before git sees them (git commit -m "$(touch /tmp/pwn)" will execute touch). This lets anyone who edits a workflow run arbitrary shell commands on the host just by typing a crafted commit message. Please switch to spawn/execFile with argument arrays or fully escape shell metacharacters so that the message is passed to git verbatim.

Useful? React with 👍 / 👎.

@beNative beNative merged commit 1de015c into main Nov 16, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants