summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components/runner_instructions
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/runner_instructions')
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql8
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql14
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue246
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue249
4 files changed, 266 insertions, 251 deletions
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
index ff0626167a9..76f152e5453 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
@@ -1,4 +1,4 @@
-query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) {
+query getRunnerPlatforms {
runnerPlatforms {
nodes {
name
@@ -11,10 +11,4 @@ query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) {
}
}
}
- project(fullPath: $projectPath) {
- id
- }
- group(fullPath: $groupPath) {
- id
- }
}
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
index 643c1991807..c0248a35e3f 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
@@ -1,15 +1,5 @@
-query runnerSetupInstructions(
- $platform: String!
- $architecture: String!
- $projectId: ID!
- $groupId: ID!
-) {
- runnerSetup(
- platform: $platform
- architecture: $architecture
- projectId: $projectId
- groupId: $groupId
- ) {
+query runnerSetupInstructions($platform: String!, $architecture: String!) {
+ runnerSetup(platform: $platform, architecture: $architecture) {
installInstructions
registerInstructions
}
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
index 1d6db576942..d886a67fff7 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
@@ -1,155 +1,31 @@
<script>
-import {
- GlAlert,
- GlButton,
- GlModal,
- GlModalDirective,
- GlButtonGroup,
- GlDropdown,
- GlDropdownItem,
- GlIcon,
-} from '@gitlab/ui';
-import { __, s__ } from '~/locale';
-import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
-import {
- PLATFORMS_WITHOUT_ARCHITECTURES,
- INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES,
-} from './constants';
-import getRunnerPlatforms from './graphql/queries/get_runner_platforms.query.graphql';
-import getRunnerSetupInstructions from './graphql/queries/get_runner_setup.query.graphql';
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import RunnerInstructionsModal from './runner_instructions_modal.vue';
export default {
components: {
- GlAlert,
GlButton,
- GlButtonGroup,
- GlDropdown,
- GlDropdownItem,
- GlModal,
- GlIcon,
- ModalCopyButton,
+ RunnerInstructionsModal,
},
directives: {
GlModalDirective,
},
- inject: {
- projectPath: {
- default: '',
- },
- groupPath: {
- default: '',
- },
- },
- apollo: {
- runnerPlatforms: {
- query: getRunnerPlatforms,
- variables() {
- return {
- projectPath: this.projectPath,
- groupPath: this.groupPath,
- };
- },
- error() {
- this.showAlert = true;
- },
- result({ data }) {
- this.project = data?.project;
- this.group = data?.group;
-
- this.selectPlatform(this.platforms[0].name);
- },
- },
+ modalId: 'runner-instructions-modal',
+ i18n: {
+ buttonText: s__('Runners|Show Runner installation instructions'),
},
data() {
return {
- showAlert: false,
- selectedPlatformArchitectures: [],
- selectedPlatform: {
- name: '',
- },
- selectedArchitecture: {},
- runnerPlatforms: {},
- instructions: {},
- project: {},
- group: {},
+ opened: false,
};
},
- computed: {
- isPlatformSelected() {
- return Object.keys(this.selectedPlatform).length > 0;
- },
- instructionsEmpty() {
- return Object.keys(this.instructions).length === 0;
- },
- groupId() {
- return this.group?.id ?? '';
- },
- projectId() {
- return this.project?.id ?? '';
- },
- platforms() {
- return this.runnerPlatforms?.nodes;
- },
- hasArchitecureList() {
- return !PLATFORMS_WITHOUT_ARCHITECTURES.includes(this.selectedPlatform?.name);
- },
- instructionsWithoutArchitecture() {
- return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.instructions;
- },
- runnerInstallationLink() {
- return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.link;
- },
- },
methods: {
- selectPlatform(name) {
- this.selectedPlatform = this.platforms.find((platform) => platform.name === name);
- if (this.hasArchitecureList) {
- this.selectedPlatformArchitectures = this.selectedPlatform?.architectures?.nodes;
- [this.selectedArchitecture] = this.selectedPlatformArchitectures;
- this.selectArchitecture(this.selectedArchitecture);
- }
- },
- selectArchitecture(architecture) {
- this.selectedArchitecture = architecture;
-
- this.$apollo.addSmartQuery('instructions', {
- variables() {
- return {
- platform: this.selectedPlatform.name,
- architecture: this.selectedArchitecture.name,
- projectId: this.projectId,
- groupId: this.groupId,
- };
- },
- query: getRunnerSetupInstructions,
- update(data) {
- return data?.runnerSetup;
- },
- error() {
- this.showAlert = true;
- },
- });
- },
- toggleAlert(state) {
- this.showAlert = state;
+ onClick() {
+ // lazily mount modal to prevent premature instructions requests
+ this.opened = true;
},
},
- modalId: 'installation-instructions-modal',
- i18n: {
- installARunner: s__('Runners|Install a Runner'),
- architecture: s__('Runners|Architecture'),
- downloadInstallBinary: s__('Runners|Download and Install Binary'),
- downloadLatestBinary: s__('Runners|Download Latest Binary'),
- registerRunner: s__('Runners|Register Runner'),
- method: __('Method'),
- fetchError: s__('Runners|An error has occurred fetching instructions'),
- instructions: s__('Runners|Show Runner installation instructions'),
- copyInstructions: s__('Runners|Copy instructions'),
- },
- closeButton: {
- text: __('Close'),
- attributes: [{ variant: 'default' }],
- },
};
</script>
<template>
@@ -158,104 +34,10 @@ export default {
v-gl-modal-directive="$options.modalId"
class="gl-mt-4"
data-testid="show-modal-button"
+ @click="onClick"
>
- {{ $options.i18n.instructions }}
+ {{ $options.i18n.buttonText }}
</gl-button>
- <gl-modal
- :modal-id="$options.modalId"
- :title="$options.i18n.installARunner"
- :action-secondary="$options.closeButton"
- >
- <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
- {{ $options.i18n.fetchError }}
- </gl-alert>
- <h5>{{ __('Environment') }}</h5>
- <gl-button-group class="gl-mb-5">
- <gl-button
- v-for="platform in platforms"
- :key="platform.name"
- data-testid="platform-button"
- @click="selectPlatform(platform.name)"
- >
- {{ platform.humanReadableName }}
- </gl-button>
- </gl-button-group>
- <template v-if="hasArchitecureList">
- <template v-if="isPlatformSelected">
- <h5>
- {{ $options.i18n.architecture }}
- </h5>
- <gl-dropdown class="gl-mb-5" :text="selectedArchitecture.name">
- <gl-dropdown-item
- v-for="architecture in selectedPlatformArchitectures"
- :key="architecture.name"
- data-testid="architecture-dropdown-item"
- @click="selectArchitecture(architecture)"
- >
- {{ architecture.name }}
- </gl-dropdown-item>
- </gl-dropdown>
- <div class="gl-display-flex gl-align-items-center gl-mb-5">
- <h5>{{ $options.i18n.downloadInstallBinary }}</h5>
- <gl-button
- class="gl-ml-auto"
- :href="selectedArchitecture.downloadLocation"
- download
- data-testid="binary-download-button"
- >
- {{ $options.i18n.downloadLatestBinary }}
- </gl-button>
- </div>
- </template>
- <template v-if="!instructionsEmpty">
- <div class="gl-display-flex">
- <pre
- class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
- data-testid="binary-instructions"
- >
-
- {{ instructions.installInstructions }}
- </pre
- >
- <modal-copy-button
- :title="$options.i18n.copyInstructions"
- :text="instructions.installInstructions"
- :modal-id="$options.modalId"
- css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
- category="tertiary"
- />
- </div>
-
- <hr />
- <h5 class="gl-mb-5">{{ $options.i18n.registerRunner }}</h5>
- <h5 class="gl-mb-5">{{ $options.i18n.method }}</h5>
- <div class="gl-display-flex">
- <pre
- class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
- data-testid="runner-instructions"
- >
- {{ instructions.registerInstructions }}
- </pre
- >
- <modal-copy-button
- :title="$options.i18n.copyInstructions"
- :text="instructions.registerInstructions"
- :modal-id="$options.modalId"
- css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
- category="tertiary"
- />
- </div>
- </template>
- </template>
- <template v-else>
- <div>
- <p>{{ instructionsWithoutArchitecture }}</p>
- <gl-button :href="runnerInstallationLink">
- <gl-icon name="external-link" />
- {{ s__('Runners|View installation instructions') }}
- </gl-button>
- </div>
- </template>
- </gl-modal>
+ <runner-instructions-modal v-if="opened" :modal-id="$options.modalId" />
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
new file mode 100644
index 00000000000..795b4f58ac5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
@@ -0,0 +1,249 @@
+<script>
+import {
+ GlAlert,
+ GlButton,
+ GlModal,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+ GlLoadingIcon,
+ GlSkeletonLoader,
+} from '@gitlab/ui';
+import { isEmpty } from 'lodash';
+import { __, s__ } from '~/locale';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+import {
+ PLATFORMS_WITHOUT_ARCHITECTURES,
+ INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES,
+} from './constants';
+import getRunnerPlatformsQuery from './graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructionsQuery from './graphql/queries/get_runner_setup.query.graphql';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ GlIcon,
+ GlLoadingIcon,
+ GlSkeletonLoader,
+ ModalCopyButton,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ },
+ apollo: {
+ platforms: {
+ query: getRunnerPlatformsQuery,
+ update(data) {
+ return data?.runnerPlatforms?.nodes.map(({ name, humanReadableName, architectures }) => {
+ return {
+ name,
+ humanReadableName,
+ architectures: architectures?.nodes || [],
+ };
+ });
+ },
+ result() {
+ // Select first platform by default
+ if (this.platforms?.[0]) {
+ this.selectPlatform(this.platforms[0]);
+ }
+ },
+ error() {
+ this.toggleAlert(true);
+ },
+ },
+ instructions: {
+ query: getRunnerSetupInstructionsQuery,
+ skip() {
+ return !this.selectedPlatform;
+ },
+ variables() {
+ return {
+ platform: this.selectedPlatformName,
+ architecture: this.selectedArchitectureName || '',
+ };
+ },
+ update(data) {
+ return data?.runnerSetup;
+ },
+ error() {
+ this.toggleAlert(true);
+ },
+ },
+ },
+ data() {
+ return {
+ platforms: [],
+ selectedPlatform: null,
+ selectedArchitecture: null,
+ showAlert: false,
+ instructions: {},
+ };
+ },
+ computed: {
+ platformsEmpty() {
+ return isEmpty(this.platforms);
+ },
+ instructionsEmpty() {
+ return isEmpty(this.instructions);
+ },
+ selectedPlatformName() {
+ return this.selectedPlatform?.name;
+ },
+ selectedArchitectureName() {
+ return this.selectedArchitecture?.name;
+ },
+ hasArchitecureList() {
+ return !PLATFORMS_WITHOUT_ARCHITECTURES.includes(this.selectedPlatformName);
+ },
+ instructionsWithoutArchitecture() {
+ return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatformName]?.instructions;
+ },
+ runnerInstallationLink() {
+ return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatformName]?.link;
+ },
+ },
+ methods: {
+ selectPlatform(platform) {
+ this.selectedPlatform = platform;
+
+ if (!platform.architectures?.some(({ name }) => name === this.selectedArchitectureName)) {
+ // Select first architecture when current value is not available
+ this.selectArchitecture(platform.architectures[0]);
+ }
+ },
+ selectArchitecture(architecture) {
+ this.selectedArchitecture = architecture;
+ },
+ toggleAlert(state) {
+ this.showAlert = state;
+ },
+ },
+ i18n: {
+ installARunner: s__('Runners|Install a runner'),
+ architecture: s__('Runners|Architecture'),
+ downloadInstallBinary: s__('Runners|Download and install binary'),
+ downloadLatestBinary: s__('Runners|Download latest binary'),
+ registerRunnerCommand: s__('Runners|Command to register runner'),
+ fetchError: s__('Runners|An error has occurred fetching instructions'),
+ copyInstructions: s__('Runners|Copy instructions'),
+ },
+ closeButton: {
+ text: __('Close'),
+ attributes: [{ variant: 'default' }],
+ },
+};
+</script>
+<template>
+ <gl-modal
+ :modal-id="modalId"
+ :title="$options.i18n.installARunner"
+ :action-secondary="$options.closeButton"
+ >
+ <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
+ {{ $options.i18n.fetchError }}
+ </gl-alert>
+
+ <gl-skeleton-loader v-if="platformsEmpty && $apollo.loading" />
+
+ <template v-if="!platformsEmpty">
+ <h5>
+ {{ __('Environment') }}
+ </h5>
+ <gl-button-group class="gl-mb-3">
+ <gl-button
+ v-for="platform in platforms"
+ :key="platform.name"
+ :selected="selectedPlatform && selectedPlatform.name === platform.name"
+ data-testid="platform-button"
+ @click="selectPlatform(platform)"
+ >
+ {{ platform.humanReadableName }}
+ </gl-button>
+ </gl-button-group>
+ </template>
+ <template v-if="hasArchitecureList">
+ <template v-if="selectedPlatform">
+ <h5>
+ {{ $options.i18n.architecture }}
+ <gl-loading-icon v-if="$apollo.loading" inline />
+ </h5>
+
+ <gl-dropdown class="gl-mb-3" :text="selectedArchitectureName">
+ <gl-dropdown-item
+ v-for="architecture in selectedPlatform.architectures"
+ :key="architecture.name"
+ :is-check-item="true"
+ :is-checked="selectedArchitectureName === architecture.name"
+ data-testid="architecture-dropdown-item"
+ @click="selectArchitecture(architecture)"
+ >
+ {{ architecture.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ <div class="gl-display-flex gl-align-items-center gl-mb-3">
+ <h5>{{ $options.i18n.downloadInstallBinary }}</h5>
+ <gl-button
+ class="gl-ml-auto"
+ :href="selectedArchitecture.downloadLocation"
+ download
+ icon="download"
+ data-testid="binary-download-button"
+ >
+ {{ $options.i18n.downloadLatestBinary }}
+ </gl-button>
+ </div>
+ </template>
+ <template v-if="!instructionsEmpty">
+ <div class="gl-display-flex">
+ <pre
+ class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="binary-instructions"
+ >{{ instructions.installInstructions }}</pre
+ >
+ <modal-copy-button
+ :title="$options.i18n.copyInstructions"
+ :text="instructions.installInstructions"
+ :modal-id="$options.modalId"
+ css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ />
+ </div>
+
+ <h5 class="gl-mb-3">{{ $options.i18n.registerRunnerCommand }}</h5>
+ <div class="gl-display-flex">
+ <pre
+ class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="register-command"
+ >{{ instructions.registerInstructions }}</pre
+ >
+ <modal-copy-button
+ :title="$options.i18n.copyInstructions"
+ :text="instructions.registerInstructions"
+ :modal-id="$options.modalId"
+ css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ />
+ </div>
+ </template>
+ </template>
+ <template v-else>
+ <div>
+ <p>{{ instructionsWithoutArchitecture }}</p>
+ <gl-button :href="runnerInstallationLink">
+ <gl-icon name="external-link" />
+ {{ s__('Runners|View installation instructions') }}
+ </gl-button>
+ </div>
+ </template>
+ </gl-modal>
+</template>