{{ $t('default') }}
+
+
+ {{ $t('unregistered') }}
+
+
{{ tagFilter }}
@@ -339,6 +480,16 @@ semaphore runner start --config ./config.runner.json
{{ $t('global') }}
+
+
+ {{ $t('unregistered') }}
+
@@ -377,6 +528,31 @@ semaphore runner start --config ./config.runner.json
+
+
+
+ mdi-sync
+
+
+
+ {{ $t('regenerateRegistrationToken') }}
+
+
+ {{ $t('askResetRunnerRegistration') }}
+
+
+
item.is_default);
}
+ if (this.unregisteredFilter) {
+ result = result.filter((item) => !item.registered);
+ }
if (this.tagFilter) {
result = result.filter((item) => item.tags && item.tags.includes(this.tagFilter));
}
@@ -533,9 +749,13 @@ semaphore runner start --no-config`;
newRunnerTokenDialog: null,
newRunner: null,
usageTab: null,
+ registerTab: null,
globalFilter: false,
defaultFilter: false,
tagFilter: null,
+ unregisteredFilter: false,
+ resetRegistrationDialog: false,
+ resetRegistrationRunner: null,
};
},
@@ -562,6 +782,47 @@ semaphore runner start --no-config`;
}
},
+ askRegenerateRegistrationToken(runner) {
+ // Regenerating for an already-registered runner is destructive (it resets the
+ // runner's token and forces it offline), so confirm first. For an unregistered
+ // runner there is nothing to lose, so do it right away.
+ if (runner.registered) {
+ this.resetRegistrationRunner = runner;
+ this.resetRegistrationDialog = true;
+ } else {
+ this.regenerateRegistrationToken(runner);
+ }
+ },
+
+ async regenerateRegistrationToken(runner) {
+ const projectId = this.getProjectIdOfItem(runner.id);
+
+ const url = projectId
+ ? `/api/project/${projectId}/runners/${runner.id}/registration-token`
+ : `/api/runners/${runner.id}/registration-token`;
+
+ try {
+ const { data } = await axios({
+ method: 'post',
+ url,
+ responseType: 'json',
+ });
+
+ // Reuse the same dialog shown right after creating an unregistered runner.
+ this.newRunner = { ...runner, registration_token: data.registration_token };
+ this.registerTab = null;
+ this.newRunnerTokenDialog = true;
+
+ // The runner's registration state may have changed (registered -> unregistered).
+ await this.loadItems();
+ } catch (e) {
+ EventBus.$emit('i-snackbar', {
+ color: 'error',
+ text: `Cannot regenerate registration token: ${e.message}`,
+ });
+ }
+ },
+
getStatusColor(runner) {
if (!runner.touched) {
return 'blue-grey lighten-3';
@@ -604,9 +865,18 @@ semaphore runner start --no-config`;
},
async loadItemsAndShowRunnerDetails(e) {
- if (e.item.token) {
+ if (e.item.token || e.item.registration_token) {
+ // A registered runner returns an auth token (and private key); show the
+ // details dialog with the connection instructions.
this.newRunnerTokenDialog = true;
this.newRunner = e.item;
+ } else if (e.action === 'new') {
+ // An unregistered runner is created with no token at all, so there is
+ // nothing to show — just confirm it was created.
+ EventBus.$emit('i-snackbar', {
+ color: 'success',
+ text: this.$t('runnerCreated'),
+ });
}
return this.loadItems();
},
@@ -659,6 +929,7 @@ semaphore runner start --no-config`;
text: this.$i18n.t('actions'),
value: 'actions',
sortable: false,
+ align: 'end',
},
];
},