Skip to content

Commit a000216

Browse files
committed
wip: github links in stacks
1 parent a50cbe7 commit a000216

File tree

7 files changed

+44
-135
lines changed

7 files changed

+44
-135
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ jobs:
2626
yarn-${{ runner.os }}-
2727
yarn-
2828
- run: yarn install --frozen-lockfile
29-
- run: yarn setup
30-
- run: yarn try
3129
- run: yarn lint
30+
- run: yarn setup
3231
- run: yarn test
3332
- uses: codecov/codecov-action@v3
3433
with:

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@
5252
"test": "node --require ./src/node/experimental.cjs --experimental-loader ./build/loader-src.js --experimental-import-meta-resolve --enable-source-maps ./util/test.ts",
5353
"typecheck": "tsc && tsc -p test/tsconfig.json",
5454
"lint": "eslint .",
55-
"ui": "node --require ./src/node/experimental.cjs --experimental-loader ./build/loader-src.js --experimental-import-meta-resolve --enable-source-maps --watch ./util/ui.ts",
56-
"try": "node --require ./src/node/experimental.cjs --experimental-loader ./build/loader-src.js --experimental-import-meta-resolve --enable-source-maps ./util/link.tsx"
55+
"ui": "node --require ./src/node/experimental.cjs --experimental-loader ./build/loader-src.js --experimental-import-meta-resolve --enable-source-maps --watch ./util/ui.ts"
5756
},
5857
"files": [
5958
"dist"

src/error/GitHubResolver.ts

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,44 +15,65 @@ export class GitHubResolver implements SourceLocationResolver {
1515
this.workspaceUrl += '/'
1616
}
1717
}
18-
if (GITHUB_SHA && GITHUB_REPOSITORY && GITHUB_SERVER_URL) {
19-
this.resolvedWorkspaceUrl = `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA}/`
20-
}
2118
}
2219

2320
protected workspaceUrl?: string
24-
protected resolvedWorkspaceUrl?: string
21+
protected resolvedWorkspaceUrl?: Promise<string>
2522
protected treeObjects?: Promise<string[]>
2623

2724
async resolve(loc: SourceLocation): Promise<SourceLocation | undefined> {
28-
if (!this.workspaceUrl || !this.resolvedWorkspaceUrl || !loc.file?.startsWith(this.workspaceUrl)) {
25+
if (!this.workspaceUrl || !loc.file?.startsWith(this.workspaceUrl)) {
2926
return undefined
3027
}
3128
const path = loc.file.substring(this.workspaceUrl.length)
3229

30+
if (!this.resolvedWorkspaceUrl) {
31+
this.resolvedWorkspaceUrl = this.getGitAbbrevSha()
32+
.then(abbrev => [
33+
this.GITHUB_SERVER_URL,
34+
this.GITHUB_REPOSITORY,
35+
'blob',
36+
abbrev,
37+
].join('/'))
38+
}
3339
if (!this.treeObjects) {
3440
this.treeObjects = this.getGitTreeObjects()
3541
}
42+
const resolvedUrl = await this.resolvedWorkspaceUrl
3643
const tree = await this.treeObjects
44+
3745
if (tree.includes(path)) {
3846
return {...loc,
39-
url: this.resolvedWorkspaceUrl + path + (loc.position ? `#L${loc.position.line}` : ''),
47+
url: resolvedUrl + '/' + path + (loc.position ? `#L${loc.position.line}` : ''),
4048
}
4149
}
4250
}
4351

44-
protected getGitTreeObjects(): Promise<string[]> {
52+
protected getGitAbbrevSha(): Promise<string> {
53+
return this.runGitCmd([
54+
'rev-parse',
55+
'--short',
56+
'HEAD',
57+
])
58+
}
59+
60+
protected async getGitTreeObjects(): Promise<string[]> {
61+
const out = await this.runGitCmd([
62+
'ls-tree',
63+
'--name-only',
64+
'-r',
65+
'HEAD',
66+
])
67+
return out.split('\n')
68+
}
69+
70+
protected runGitCmd(args: string[]): Promise<string> {
4571
if (!this.GITHUB_WORKSPACE) {
4672
return Promise.reject(`GITHUB_WORKSPACE is not set.`)
4773
}
4874

4975
return new Promise((res, rej) => {
50-
const child = spawn('git', [
51-
'ls-tree',
52-
'--name-only',
53-
'-r',
54-
'HEAD',
55-
], {
76+
const child = spawn('git', args, {
5677
cwd: this.GITHUB_WORKSPACE,
5778
stdio: ['ignore', 'pipe', 'pipe'],
5879
})
@@ -65,10 +86,9 @@ export class GitHubResolver implements SourceLocationResolver {
6586
})
6687
child.on('exit', (code, signal) => {
6788
if (code || signal) {
68-
rej(`Could not list tree objects:\n` + err)
89+
rej(`Git command failed: ${JSON.stringify(args)}\n` + err)
6990
} else {
70-
const list = out.split('\n')
71-
res(list)
91+
res(out.trimEnd())
7292
}
7393
})
7494
})

src/error/XError.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ export class StackEntry {
117117

118118
const pos = e.position ? `:${e.position.line}:${e.position.column}` : ''
119119
if (useUrl && e.url && e.name) {
120-
return `${e.name} (${e.url}${pos})`
120+
return `${e.name} (${e.url})`
121121
} else if (useUrl && e.url) {
122-
return `${e.url}${pos}`
122+
return `${e.url}`
123123
} else if (e.name && e.file) {
124124
return `${e.name} (${e.file}${pos})`
125125
} else if (e.file) {

src/ui/cli/Error.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useTester } from '../TesterContext'
44
import { useSubscribers } from './useSubscribers'
55
import { Text } from 'ink'
66
import { Block, Line } from './Blocks'
7-
import { Link } from './Link'
87

98
export function StackEntryText({
109
entry,
@@ -17,14 +16,12 @@ export function StackEntryText({
1716
], [entry])
1817
tester.resolveErrorStackEntry(entry)
1918

20-
const {url} = entry.resolved.get()
19+
// A clickable link would be preferable,
20+
// but GitHub Actions logs don't support the escape sequence for hyperlinks.
21+
// See https://github.com/orgs/community/discussions/119709
2122

2223
return <Text color="redBright" dimColor>
23-
{`at `}
24-
{url
25-
? <Link url={url}>{String(entry)}</Link>
26-
: String(entry)
27-
}
24+
{`at ${entry.toString(true)}`}
2825
</Text>
2926
}
3027

src/ui/cli/Link.tsx

Lines changed: 0 additions & 32 deletions
This file was deleted.

util/link.tsx

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)