Skip to content

Commit b2654da

Browse files
authored
Use the build number for requests from /latestXXX builds (#1205)
1 parent 68ef091 commit b2654da

21 files changed

Lines changed: 127 additions & 54 deletions

File tree

openapi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ components:
612612
synthetic: false
613613
placeholder: false
614614
agent: "linux"
615-
url: "/job/my-pipeline/1/stages?selected-node=6"
615+
url: "/job/my-pipeline/1/stages/?selected-node=6"
616616

617617
StepListExample:
618618
summary: Example step list

src/main/frontend/common/RestClient.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,28 @@ export interface ConsoleLogData {
6464
consoleAnnotator: string;
6565
}
6666

67+
function fixStaleStageURL(stages: StageInfo[]) {
68+
for (const stage of stages) {
69+
stage.url = stage.url.replace("stages?", "stages/?");
70+
fixStaleStageURL(stage.children);
71+
}
72+
}
73+
6774
export async function getRunStatusFromPath(url: string): Promise<RunStatus> {
68-
const response = await fetch(url + "stages/tree");
75+
const response = await fetch(`${url}stages/tree`);
6976
if (!response.ok) {
7077
throw response.statusText;
7178
}
7279
const text = await response.text();
7380
const json = JSON.parse(text);
81+
// Trees of completed builds are cached. The response may have been generated by a previous release without the URL normalization. We can remove the normalization from the frontend in a few months time.
82+
fixStaleStageURL(json.data.stages);
7483
json.data.raw = text;
7584
return json.data;
7685
}
7786

78-
export async function getRunSteps(): Promise<AllStepsData> {
79-
const response = await fetch("allSteps");
87+
export async function getRunSteps(url: string): Promise<AllStepsData> {
88+
const response = await fetch(`${url}stages/allSteps`);
8089
if (!response.ok) throw response.statusText;
8190
const text = await response.text();
8291
const json = JSON.parse(text);
@@ -85,6 +94,7 @@ export async function getRunSteps(): Promise<AllStepsData> {
8594
}
8695

8796
export async function getConsoleTextOffset(
97+
url: string,
8898
stepId: string,
8999
startByte: number,
90100
consoleAnnotator: string,
@@ -93,7 +103,7 @@ export async function getConsoleTextOffset(
93103
if (consoleAnnotator) headers.set("X-ConsoleAnnotator", consoleAnnotator);
94104
try {
95105
const response = await fetch(
96-
`../execution/node/${stepId}/log/logText/progressiveHtml?start=${startByte.toString()}`,
106+
`${url}execution/node/${stepId}/log/logText/progressiveHtml?start=${startByte.toString()}`,
97107
{ headers },
98108
);
99109
if (!response.ok) throw response.statusText;
@@ -113,9 +123,12 @@ export async function getConsoleTextOffset(
113123
}
114124
}
115125

116-
export async function getExceptionText(stepId: string): Promise<string[]> {
126+
export async function getExceptionText(
127+
url: string,
128+
stepId: string,
129+
): Promise<string[]> {
117130
try {
118-
const response = await fetch(`exceptionText?nodeId=${stepId}`);
131+
const response = await fetch(`${url}stages/exceptionText?nodeId=${stepId}`);
119132
if (!response.ok) throw response.statusText;
120133
const text = await response.text();
121134
if (!text) return [];

src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLine.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ export interface ConsoleLineProps {
1010
content: string;
1111
stepId: string;
1212
startByte: number;
13+
currentRunPath: string;
1314
}
1415

1516
// Console output line
1617
export const ConsoleLine = memo(function ConsoleLine(props: ConsoleLineProps) {
17-
const baseURL = `?start-byte=${props.startByte}&selected-node=${props.stepId}`;
18+
const baseURL = `${props.currentRunPath}stages/?start-byte=${props.startByte}&selected-node=${props.stepId}`;
1819
const id = `log-${props.stepId}-${props.lineNumber}`;
1920
return (
2021
<pre

src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogCard.spec.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ describe("ConsoleLogCard", () => {
5252
tailLogs: true,
5353
scrollToTail: () => {},
5454
stopTailingLogs: () => {},
55+
currentRunPath: "/jenkins/job/name/1/",
5556
} as ConsoleLogCardProps;
5657
beforeEach(function () {
5758
(DefaultTestProps.fetchLogText as Mock).mockReset();

src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogCard.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,16 @@ export default function ConsoleLogCard({
3939
fetchLogText,
4040
onStepToggle,
4141
fetchExceptionText,
42+
currentRunPath,
4243
}: ConsoleLogCardProps) {
43-
const handleToggle = (e: ReactMouseEvent<HTMLElement>) => {
44+
const handleToggle = (e: ReactMouseEvent<HTMLAnchorElement>) => {
4445
// Only prevent left clicks
4546
if (e.button !== 0 || e.metaKey || e.ctrlKey) {
4647
return;
4748
}
4849

4950
e.preventDefault();
50-
51-
history.replaceState({}, "", `?selected-node=` + step.id);
51+
history.replaceState({}, "", e.currentTarget.href);
5252

5353
onStepToggle(step.id);
5454
};
@@ -68,7 +68,7 @@ export default function ConsoleLogCard({
6868
})}
6969
>
7070
<a
71-
href={`?selected-node=` + step.id}
71+
href={currentRunPath + `stages/?selected-node=` + step.id}
7272
onClick={handleToggle}
7373
key={`step-action-area-${step.id}`}
7474
>
@@ -122,7 +122,7 @@ export default function ConsoleLogCard({
122122

123123
<Tooltip content={messages.format(LocalizedMessageKey.consoleNewTab)}>
124124
<a
125-
href={`log?nodeId=${step.id}`}
125+
href={`${currentRunPath}stages/log?nodeId=${step.id}`}
126126
className={"jenkins-button jenkins-button--tertiary"}
127127
target="_blank"
128128
rel="noreferrer"
@@ -153,6 +153,7 @@ export default function ConsoleLogCard({
153153
fetchLogText={fetchLogText}
154154
fetchExceptionText={fetchExceptionText}
155155
onStepToggle={onStepToggle}
156+
currentRunPath={currentRunPath}
156157
/>
157158
)}
158159
</div>
@@ -193,6 +194,7 @@ const ConsoleLogBody = memo(function ConsoleLogBody({
193194
stepBuffers,
194195
fetchLogText,
195196
fetchExceptionText,
197+
currentRunPath,
196198
}: ConsoleLogCardBodyProps) {
197199
const [stepBuffer, setStepBuffer] = useState<StepLogBufferInfo>({
198200
...(stepBuffers.get(stepId) || defaultStepBuffer()),
@@ -265,6 +267,7 @@ const ConsoleLogBody = memo(function ConsoleLogBody({
265267
fetchExceptionText={fetchExceptionText}
266268
stepId={stepId}
267269
stepState={stepState}
270+
currentRunPath={currentRunPath}
268271
/>
269272
</Suspense>
270273
</div>
@@ -284,6 +287,7 @@ export type ConsoleLogCardProps = {
284287
tailLogs: boolean;
285288
scrollToTail: (stepId: string, element: HTMLDivElement) => void;
286289
stopTailingLogs: () => void;
290+
currentRunPath: string;
287291
};
288292

289293
export type ConsoleLogCardBodyProps = {
@@ -299,4 +303,5 @@ export type ConsoleLogCardBodyProps = {
299303
tailLogs: boolean;
300304
scrollToTail: (stepId: string, element: HTMLDivElement) => void;
301305
stopTailingLogs: () => void;
306+
currentRunPath: string;
302307
};

src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogStream.spec.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ describe("ConsoleLogStream", () => {
4949
tailLogs: false,
5050
stopTailingLogs: () => {},
5151
scrollToTail: () => {},
52+
currentRunPath: "/jenkins/job/name/1/",
5253
} as ConsoleLogStreamProps;
5354

5455
it("renders step console", async () => {

src/main/frontend/pipeline-console-view/pipeline-console/main/ConsoleLogStream.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default function ConsoleLogStream({
1818
updateLogBufferIfChanged,
1919
fetchLogText,
2020
fetchExceptionText,
21+
currentRunPath,
2122
}: ConsoleLogStreamProps) {
2223
const logRef = useRef<HTMLDivElement>(null);
2324
const [logVisible, setLogVisible] = useState(true);
@@ -100,6 +101,7 @@ export default function ConsoleLogStream({
100101
stepId={stepId}
101102
startByte={logBuffer.startByte}
102103
stopTailingLogs={stopTailingLogs}
104+
currentRunPath={currentRunPath}
103105
/>
104106
))}
105107
</div>
@@ -119,4 +121,5 @@ export interface ConsoleLogStreamProps {
119121
tailLogs: boolean;
120122
stopTailingLogs: () => void;
121123
scrollToTail: (stepId: string, element: HTMLDivElement) => void;
124+
currentRunPath: string;
122125
}

src/main/frontend/pipeline-console-view/pipeline-console/main/DataTreeView.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default function DataTreeView({
2121
stages,
2222
selected,
2323
onNodeSelect,
24+
currentRunPath,
2425
}: DataTreeViewProps) {
2526
const { search, setSearch, visibleStatuses } = useFilter();
2627
const filteredStages = filterStageTree(search, visibleStatuses, stages);
@@ -90,6 +91,7 @@ export default function DataTreeView({
9091
stage={stage}
9192
selected={String(selected)}
9293
onSelect={onNodeSelect}
94+
currentRunPath={currentRunPath}
9395
/>
9496
))}
9597
</ol>
@@ -108,6 +110,7 @@ const TreeNode = memo(function TreeNode({
108110
stage,
109111
selected,
110112
onSelect,
113+
currentRunPath,
111114
}: TreeNodeProps) {
112115
const { search, visibleStatuses, allVisible } = useFilter();
113116
const hasChildren = stage.children && stage.children.length > 0;
@@ -145,16 +148,16 @@ const TreeNode = memo(function TreeNode({
145148
>
146149
<div className="pgv-tree-item-container">
147150
<a
148-
href={`?selected-node=` + stage.id}
151+
href={currentRunPath + `stages/?selected-node=` + stage.id}
149152
onClick={(e) => {
150153
// Only prevent left clicks
151154
if (e.button !== 0 || e.metaKey || e.ctrlKey) {
152155
return;
153156
}
154157

155158
e.preventDefault();
159+
history.replaceState({}, "", e.currentTarget.href);
156160

157-
history.replaceState({}, "", `?selected-node=` + stage.id);
158161
if (!isSelected) {
159162
onSelect(String(stage.id));
160163
}
@@ -223,6 +226,7 @@ const TreeNode = memo(function TreeNode({
223226
stage={child}
224227
selected={selected}
225228
onSelect={onSelect}
229+
currentRunPath={currentRunPath}
226230
/>
227231
))}
228232
</ol>
@@ -264,10 +268,12 @@ interface DataTreeViewProps {
264268
stages: StageInfo[];
265269
selected?: number;
266270
onNodeSelect: (nodeId: string) => void;
271+
currentRunPath: string;
267272
}
268273

269274
interface TreeNodeProps {
270275
stage: StageInfo;
271276
selected: string;
272277
onSelect: (id: string) => void;
278+
currentRunPath: string;
273279
}

src/main/frontend/pipeline-console-view/pipeline-console/main/NoStageStepsFallback.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ async function fetchData(url: string): Promise<StepLogBufferInfo> {
1919
}
2020

2121
interface NoStageStepsFallbackProps {
22-
url: string;
22+
currentRunPath: string;
2323
tailLogs: boolean;
2424
scrollToTail: (stepId: string, element: HTMLDivElement) => void;
2525
}
@@ -32,13 +32,13 @@ export function NoStageStepsFallback(props: NoStageStepsFallbackProps) {
3232
});
3333

3434
useEffect(() => {
35-
fetchData(props.url)
35+
fetchData(props.currentRunPath)
3636
.then((data) => {
3737
setLogBuffer(data);
3838
return data;
3939
})
4040
.catch((err) => console.log(err));
41-
}, [props.url]);
41+
}, [props.currentRunPath]);
4242

4343
return (
4444
<div className={"pgv-stage-steps"}>
@@ -52,6 +52,7 @@ export function NoStageStepsFallback(props: NoStageStepsFallbackProps) {
5252
stepId={""}
5353
stepState={Result.success}
5454
fetchExceptionText={async () => logBuffer}
55+
currentRunPath={props.currentRunPath}
5556
/>
5657
</div>
5758
</div>

src/main/frontend/pipeline-console-view/pipeline-console/main/PipelineConsole.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export default function PipelineConsole() {
127127
</div>
128128
) : (
129129
<DataTreeView
130+
currentRunPath={currentRunPath}
130131
onNodeSelect={handleStageSelect}
131132
selected={openStage?.id}
132133
stages={stages}
@@ -153,6 +154,7 @@ export default function PipelineConsole() {
153154
onStepToggle={onStepToggle}
154155
fetchLogText={fetchLogText}
155156
fetchExceptionText={fetchExceptionText}
157+
currentRunPath={currentRunPath}
156158
/>
157159
)}
158160
</div>
@@ -162,7 +164,7 @@ export default function PipelineConsole() {
162164

163165
{!loading && stages.length === 0 && (
164166
<NoStageStepsFallback
165-
url={currentRunPath}
167+
currentRunPath={currentRunPath}
166168
tailLogs={tailLogs}
167169
scrollToTail={scrollToTail}
168170
/>

0 commit comments

Comments
 (0)