Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": ["$ts-webpack-watch"]
"problemMatcher": "$tsc-watch"
},
{
"label": "delay",
Expand Down
55 changes: 49 additions & 6 deletions src/commands/triggerWorkflowRun.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as vscode from "vscode";

import {getGitHead, getGitHubContextForWorkspaceUri, GitHubRepoContext} from "../git/repository";
import {getGitHead, getGitHubContextForWorkspaceUri, GitHubRepoContext, getGitExtension} from "../git/repository";
import {getRepositoryRootForDocumentUri} from "../git/submoduleHelper";
import {getWorkflowUri, parseWorkflowFile} from "../workflow/workflow";
import {Protocol} from "../external/protocol";

import {Workflow} from "../model";

Expand All @@ -10,6 +12,40 @@ interface TriggerRunCommandOptions {
gitHubRepoContext: GitHubRepoContext;
}

async function getGitHubContextForRepository(repositoryUri: vscode.Uri): Promise<GitHubRepoContext | undefined> {
let context = await getGitHubContextForWorkspaceUri(repositoryUri);
if (context) {
return context;
}

const git = await getGitExtension();
if (!git) {
return undefined;
}

for (const repository of git.repositories) {
if (repository.rootUri.fsPath === repositoryUri.fsPath) {
await repository.status();
const remote = repository.state.remotes.find(r => r.name === "origin") || repository.state.remotes[0];

if (remote?.pushUrl) {
try {
const protocol = new Protocol(remote.pushUrl);
return {
owner: protocol.owner,
name: protocol.repositoryName,
client: undefined as any
} as GitHubRepoContext;
} catch {
return undefined;
}
}
}
}

return undefined;
}

export function registerTriggerWorkflowRun(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand(
Expand All @@ -28,12 +64,17 @@ export function registerTriggerWorkflowRun(context: vscode.ExtensionContext) {
}

// Parse
const workspaceFolder = vscode.workspace.getWorkspaceFolder(workflowUri);
if (!workspaceFolder) {
return;
let repositoryUri = await getRepositoryRootForDocumentUri(workflowUri);

if (!repositoryUri) {
const workspaceFolder = vscode.workspace.getWorkspaceFolder(workflowUri);
if (!workspaceFolder) {
return;
}
repositoryUri = workspaceFolder.uri;
}

const gitHubRepoContext = await getGitHubContextForWorkspaceUri(workspaceFolder.uri);
const gitHubRepoContext = await getGitHubContextForRepository(repositoryUri);
if (!gitHubRepoContext) {
return;
}
Expand Down Expand Up @@ -85,7 +126,9 @@ export function registerTriggerWorkflowRun(context: vscode.ExtensionContext) {
}

try {
const relativeWorkflowPath = vscode.workspace.asRelativePath(workflowUri, false);
const workflowPath = workflowUri.fsPath;
const repositoryPath = repositoryUri.fsPath;
const relativeWorkflowPath = require("path").relative(repositoryPath, workflowPath).replace(/\\/g, "/");

await gitHubRepoContext.client.actions.createWorkflowDispatch({
owner: gitHubRepoContext.owner,
Expand Down
2 changes: 1 addition & 1 deletion src/git/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface GitHubUrls {
protocol: Protocol;
}

async function getGitExtension(): Promise<API | undefined> {
export async function getGitExtension(): Promise<API | undefined> {
const gitExtension = vscode.extensions.getExtension<GitExtension>("vscode.git");
if (gitExtension) {
if (!gitExtension.isActive) {
Expand Down
62 changes: 62 additions & 0 deletions src/git/submoduleHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as vscode from "vscode";
import * as path from "path";

import {getGitExtension} from "./repository";
import {logDebug} from "../log";

async function getGitRemoteForPath(directoryPath: string): Promise<string | undefined> {
try {
const fs = await import("fs/promises");
const stats = await fs.stat(directoryPath);
const cwd = stats.isDirectory() ? directoryPath : path.dirname(directoryPath);

const child_process = await import("child_process");
const util = await import("util");
const execFile = util.promisify(child_process.execFile);
const {stdout} = await execFile("git", ["config", "--get", "remote.origin.url"], {cwd});
return stdout.trim();
} catch {
return undefined;
}
}

function isPathWithin(childPath: string, parentPath: string): boolean {
const relative = path.relative(parentPath, childPath);
return !relative.startsWith("..") && !path.isAbsolute(relative);
}

export async function getRepositoryRootForDocumentUri(documentUri: vscode.Uri): Promise<vscode.Uri | undefined> {
const git = await getGitExtension();
if (!git || git.repositories.length === 0) {
return undefined;
}

const documentPath = documentUri.fsPath;

for (const repository of git.repositories) {
const repoPath = repository.rootUri.fsPath;

if (isPathWithin(documentPath, repoPath)) {
const state = repository.state;

if (state && state.submodules && state.submodules.length > 0) {
for (const submodule of state.submodules) {
const submodulePath = path.join(repoPath, submodule.path);
if (isPathWithin(documentPath, submodulePath)) {
logDebug("Found document in submodule:", submodule.path);
const remoteUrl = await getGitRemoteForPath(submodulePath);
if (remoteUrl) {
logDebug("Submodule remote URL:", remoteUrl);
}
return vscode.Uri.file(submodulePath);
}
}
}

logDebug("Found document in repository:", repoPath);
return repository.rootUri;
}
}

return undefined;
}