From 32aca4ad2f0e44a975e576b440b16c041588a6ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 07:41:38 +0000 Subject: [PATCH 1/2] Initial plan From 30786064d691867717250094b21f8a29e1af7d41 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 07:50:37 +0000 Subject: [PATCH 2/2] Fix path resolution for GitHub API file reader in frontmatter hash Use path.join instead of path.resolve to preserve repository-relative paths when computing frontmatter hashes with the GitHub API file reader. This fixes the issue where absolute filesystem paths were being passed to the GitHub API, causing import files to fail loading and producing incorrect hash values. Add integration tests to verify that: - All paths passed to GitHub API are repository-relative (not absolute) - Hash computation produces identical results with filesystem and GitHub API readers Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../js/frontmatter_hash_github_api.test.cjs | 87 +++++++++++++++++++ actions/setup/js/frontmatter_hash_pure.cjs | 4 +- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/frontmatter_hash_github_api.test.cjs b/actions/setup/js/frontmatter_hash_github_api.test.cjs index 2cab88cccb..b07af7a1e5 100644 --- a/actions/setup/js/frontmatter_hash_github_api.test.cjs +++ b/actions/setup/js/frontmatter_hash_github_api.test.cjs @@ -245,6 +245,93 @@ describe("frontmatter_hash with GitHub API", () => { }); }); + describe("path resolution with GitHub API", () => { + it("should use repository-relative paths for imports (not absolute filesystem paths)", async () => { + // This test validates the fix for issue where path.resolve() created absolute paths + // that broke GitHub API calls + const owner = "githubnext"; + const repo = "gh-aw"; + const ref = "main"; + + // Track all paths requested from GitHub API + const requestedPaths = []; + const trackingMockGitHub = { + rest: { + repos: { + getContent: async ({ path: filePath }) => { + requestedPaths.push(filePath); + + // Verify path is repository-relative (not absolute) + if (path.isAbsolute(filePath)) { + throw new Error(`GitHub API should not receive absolute paths: ${filePath}`); + } + + // Read from local filesystem for testing + const fsPath = require("path"); + const repoRoot = fsPath.resolve(__dirname, "../../.."); + const fullPath = fsPath.join(repoRoot, filePath); + + if (!fs.existsSync(fullPath)) { + const error = new Error(`Not Found: ${filePath}`); + error.status = 404; + throw error; + } + + const content = fs.readFileSync(fullPath, "utf8"); + const base64Content = Buffer.from(content).toString("base64"); + + return { + data: { + content: base64Content, + encoding: "base64", + }, + }; + }, + }, + }, + }; + + const fileReader = createGitHubFileReader(trackingMockGitHub, owner, repo, ref); + + // Test with smoke-codex.md which has imports + const workflowPath = ".github/workflows/smoke-codex.md"; + const hash = await computeFrontmatterHash(workflowPath, { fileReader }); + + // Verify hash was computed successfully + expect(hash).toMatch(/^[a-f0-9]{64}$/); + + // Verify all requested paths are repository-relative + expect(requestedPaths.length).toBeGreaterThan(1); // Should include main file + imports + for (const requestedPath of requestedPaths) { + expect(path.isAbsolute(requestedPath)).toBe(false); + expect(requestedPath).toMatch(/^\.github\/workflows\//); + } + + // Log the paths for debugging + console.log("Requested paths from GitHub API:", requestedPaths); + }); + + it("should compute same hash with GitHub API reader as with filesystem reader", async () => { + const owner = "githubnext"; + const repo = "gh-aw"; + const ref = "main"; + + // Compute hash with filesystem reader (absolute path) + const repoRoot = path.resolve(__dirname, "../../.."); + const absolutePath = path.join(repoRoot, ".github/workflows/smoke-codex.md"); + const fsHash = await computeFrontmatterHash(absolutePath); + + // Compute hash with GitHub API reader (relative path) + const fileReader = createGitHubFileReader(mockGitHub, owner, repo, ref); + const apiHash = await computeFrontmatterHash(".github/workflows/smoke-codex.md", { + fileReader, + }); + + // Hashes should match (this was broken before the fix) + expect(apiHash).toBe(fsHash); + }); + }); + describe("live GitHub API integration", () => { it("should compute hash using real GitHub API (no mocks)", async () => { // Skip this test if no GitHub token is available diff --git a/actions/setup/js/frontmatter_hash_pure.cjs b/actions/setup/js/frontmatter_hash_pure.cjs index d094fc3796..06a008bdd0 100644 --- a/actions/setup/js/frontmatter_hash_pure.cjs +++ b/actions/setup/js/frontmatter_hash_pure.cjs @@ -129,8 +129,8 @@ async function processImportsTextBased(frontmatterText, baseDir, visited = new S const sortedImports = [...imports].sort(); for (const importPath of sortedImports) { - // Resolve import path relative to base directory - const fullPath = path.resolve(baseDir, importPath); + // Join import path with base directory (preserves relative paths for GitHub API compatibility) + const fullPath = path.join(baseDir, importPath); // Skip if already visited (cycle detection) if (visited.has(fullPath)) continue;