Skip to content

Commit

Permalink
Add ability to rerun and cancel Runs
Browse files Browse the repository at this point in the history
- Standalone Run resources can be rerun from the list page
  (i.e. not child of a Pipeline)
- Any Run that is currently running (i.e. status == Unknown)
can be stopped
- Update StatusIcon to render running state to match behaviour
  described in the Runs documentation
  • Loading branch information
AlanGreene authored and tekton-robot committed Aug 19, 2022
1 parent 09788aa commit 63fe449
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 9 deletions.
8 changes: 6 additions & 2 deletions packages/components/src/components/StatusIcon/StatusIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const typeClassNames = {
export default function StatusIcon({
DefaultIcon,
hasWarning,
isCustomTask,
reason,
status,
title,
Expand All @@ -73,8 +74,6 @@ export default function StatusIcon({
(status === 'Unknown' && reason === 'Pending')
) {
statusClass = 'pending';
} else if (isRunning(reason, status)) {
statusClass = 'running';
} else if (
status === 'True' ||
(status === 'terminated' && reason === 'Completed')
Expand All @@ -94,6 +93,11 @@ export default function StatusIcon({
(status === 'Unknown' && reason === 'PipelineRunCouldntCancel')
) {
statusClass = 'error';
} else if (
isRunning(reason, status) ||
(isCustomTask && status === 'Unknown')
) {
statusClass = 'running';
}

const Icon = icons[type]?.[statusClass] || DefaultIcon;
Expand Down
35 changes: 34 additions & 1 deletion src/api/runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { deleteRequest, get } from './comms';
import { getGenerateNamePrefixForRerun } from '@tektoncd/dashboard-utils';
import deepClone from 'lodash.clonedeep';

import { deleteRequest, get, patch, post } from './comms';
import {
getQueryParams,
getTektonAPI,
Expand Down Expand Up @@ -62,3 +65,33 @@ export function useRun(params, queryConfig) {
webSocketURL
});
}

export function cancelRun({ name, namespace }) {
const payload = [
{ op: 'replace', path: '/spec/status', value: 'RunCancelled' }
];

const uri = getTektonAPI('runs', { name, namespace, version: 'v1alpha1' });
return patch(uri, payload);
}

export function rerunRun(run) {
const { annotations, labels, name, namespace } = run.metadata;

const payload = deepClone(run);
payload.metadata = {
annotations,
generateName: getGenerateNamePrefixForRerun(name),
labels: {
...labels,
'dashboard.tekton.dev/rerunOf': name
},
namespace
};

delete payload.status;
delete payload.spec?.status;

const uri = getTektonAPI('runs', { namespace, version: 'v1alpha1' });
return post(uri, payload).then(({ body }) => body);
}
38 changes: 38 additions & 0 deletions src/api/runs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ import fetchMock from 'fetch-mock';
import * as API from './runs';
import * as utils from './utils';

it('cancelRun', () => {
const name = 'foo';
const namespace = 'foospace';
const returnedRun = { fake: 'Run' };
const payload = [
{ op: 'replace', path: '/spec/status', value: 'RunCancelled' }
];
fetchMock.patch(`end:${name}`, returnedRun);
return API.cancelRun({ name, namespace }).then(response => {
expect(fetchMock.lastOptions()).toMatchObject({
body: JSON.stringify(payload)
});
expect(response).toEqual(returnedRun);
fetchMock.restore();
});
});

it('deleteRun', () => {
const name = 'foo';
const data = { fake: 'Run' };
Expand Down Expand Up @@ -85,3 +102,24 @@ it('useRun', () => {
})
);
});

it('rerunRun', () => {
const filter = 'end:/runs/';
const originalRun = {
metadata: { name: 'fake_run' },
spec: { status: 'fake_status' },
status: 'fake_status'
};
const newRun = { metadata: { name: 'fake_run_rerun' } };
fetchMock.post(filter, { body: newRun, status: 201 });
return API.rerunRun(originalRun).then(data => {
const body = JSON.parse(fetchMock.lastCall(filter)[1].body);
expect(body.metadata.generateName).toMatch(
new RegExp(originalRun.metadata.name)
);
expect(body.status).toBeUndefined();
expect(body.spec.status).toBeUndefined();
expect(data).toEqual(newRun);
fetchMock.restore();
});
});
7 changes: 6 additions & 1 deletion src/containers/Run/Run.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ function getRunStatusIcon(run) {
}
const { reason, status } = getStatus(run);
return (
<StatusIcon DefaultIcon={UndefinedIcon} reason={reason} status={status} />
<StatusIcon
DefaultIcon={UndefinedIcon}
isCustomTask
reason={reason}
status={status}
/>
);
}

Expand Down
65 changes: 60 additions & 5 deletions src/containers/Runs/Runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
ALL_NAMESPACES,
getFilters,
getStatus,
isRunning,
urls,
useTitleSync
} from '@tektoncd/dashboard-utils';
Expand All @@ -43,7 +42,9 @@ import {

import { ListPageLayout } from '..';
import {
cancelRun,
deleteRun,
rerunRun,
useIsReadOnly,
useRuns,
useSelectedNamespace
Expand Down Expand Up @@ -85,7 +86,12 @@ function getRunStatus(run) {
function getRunStatusIcon(run) {
const { reason, status } = getStatus(run);
return (
<StatusIcon DefaultIcon={UndefinedIcon} reason={reason} status={status} />
<StatusIcon
DefaultIcon={UndefinedIcon}
isCustomTask
reason={reason}
status={status}
/>
);
}

Expand Down Expand Up @@ -169,6 +175,17 @@ function Runs({ intl }) {
setToBeDeleted([]);
}

function cancel(run) {
cancelRun({
name: run.metadata.name,
namespace: run.metadata.namespace
});
}

function rerun(run) {
rerunRun(run);
}

function deleteResource(run) {
const { name, namespace: resourceNamespace } = run.metadata;
return deleteRun({ name, namespace: resourceNamespace }).catch(err => {
Expand Down Expand Up @@ -196,7 +213,44 @@ function Runs({ intl }) {
}

return [
// TODO: rerun?
{
action: rerun,
actionText: intl.formatMessage({
id: 'dashboard.rerun.actionText',
defaultMessage: 'Rerun'
}),
disable: resource => !!resource.metadata.labels?.['tekton.dev/pipeline']
},
{
actionText: intl.formatMessage({
id: 'dashboard.cancelTaskRun.actionText',
defaultMessage: 'Stop'
}),
action: cancel,
disable: resource => {
const { status } = getStatus(resource);
return status && status !== 'Unknown';
},
modalProperties: {
heading: intl.formatMessage({
id: 'dashboard.cancelRun.heading',
defaultMessage: 'Stop Run'
}),
primaryButtonText: intl.formatMessage({
id: 'dashboard.cancelRun.primaryText',
defaultMessage: 'Stop Run'
}),
body: resource =>
intl.formatMessage(
{
id: 'dashboard.cancelRun.body',
defaultMessage:
'Are you sure you would like to stop Run {name}?'
},
{ name: resource.metadata.name }
)
}
},
{
actionText: intl.formatMessage({
id: 'dashboard.actions.deleteButton',
Expand All @@ -205,9 +259,10 @@ function Runs({ intl }) {
action: deleteResource,
danger: true,
disable: resource => {
const { reason, status } = getStatus(resource);
return isRunning(reason, status);
const { status } = getStatus(resource);
return status === 'Unknown';
},
hasDivider: true,
modalProperties: {
danger: true,
heading: intl.formatMessage(
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_de.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "PipelineRun stoppen",
"dashboard.cancelPipelineRun.primaryText": "PipelineRun stoppen",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "",
"dashboard.cancelTaskRun.body": "",
"dashboard.cancelTaskRun.heading": "",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "Stop PipelineRun",
"dashboard.cancelPipelineRun.primaryText": "Stop PipelineRun",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "Allow any currently executing tasks to complete but do not schedule any new non-finally tasks, then execute finally tasks",
"dashboard.cancelRun.body": "Are you sure you would like to stop Run {name}?",
"dashboard.cancelRun.heading": "Stop Run",
"dashboard.cancelRun.primaryText": "Stop Run",
"dashboard.cancelTaskRun.actionText": "Stop",
"dashboard.cancelTaskRun.body": "Are you sure you would like to stop TaskRun {name}?",
"dashboard.cancelTaskRun.heading": "Stop TaskRun",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_es.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "Detener PipelineRun",
"dashboard.cancelPipelineRun.primaryText": "Detener PipelineRun",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "",
"dashboard.cancelTaskRun.body": "",
"dashboard.cancelTaskRun.heading": "",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "Arrêt de PipelineRun",
"dashboard.cancelPipelineRun.primaryText": "Arrêter PipelineRun",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "",
"dashboard.cancelTaskRun.body": "",
"dashboard.cancelTaskRun.heading": "",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_it.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "Arresta esecuzione pipeline",
"dashboard.cancelPipelineRun.primaryText": "Arresta esecuzione pipeline",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "",
"dashboard.cancelTaskRun.body": "",
"dashboard.cancelTaskRun.heading": "",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "PipelineRunを停止",
"dashboard.cancelPipelineRun.primaryText": "PipelineRunを停止",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "停止",
"dashboard.cancelTaskRun.body": "TaskRun {name}を停止してもよろしいですか?",
"dashboard.cancelTaskRun.heading": "TaskRunを停止",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "PipelineRun 중지",
"dashboard.cancelPipelineRun.primaryText": "PipelineRun 중지",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "",
"dashboard.cancelTaskRun.body": "",
"dashboard.cancelTaskRun.heading": "",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "Parar o PipelineRun",
"dashboard.cancelPipelineRun.primaryText": "Parar o PipelineRun",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "",
"dashboard.cancelTaskRun.body": "",
"dashboard.cancelTaskRun.heading": "",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_zh-Hans.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "停止 PipelineRun",
"dashboard.cancelPipelineRun.primaryText": "停止 PipelineRun",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "停止",
"dashboard.cancelTaskRun.body": "您确定要停止 TaskRun {name} 吗",
"dashboard.cancelTaskRun.heading": "停止 TaskRun",
Expand Down
3 changes: 3 additions & 0 deletions src/nls/messages_zh-Hant.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dashboard.cancelPipelineRun.heading": "停止 PipelineRun",
"dashboard.cancelPipelineRun.primaryText": "停止 PipelineRun",
"dashboard.cancelPipelineRun.stoppedRunFinally.description": "",
"dashboard.cancelRun.body": "",
"dashboard.cancelRun.heading": "",
"dashboard.cancelRun.primaryText": "",
"dashboard.cancelTaskRun.actionText": "",
"dashboard.cancelTaskRun.body": "",
"dashboard.cancelTaskRun.heading": "",
Expand Down

0 comments on commit 63fe449

Please sign in to comment.