Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-01-15 15:10:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-01-15 15:10:42 +0300
commit0e11c62b96a79f7c5b40bb87c752a77f6fd986d0 (patch)
tree79a04b4420e98a9419cd91488206c4a5c3074a12
parentb7213d10f4f03736110b176cb45ad315e71cee01 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js24
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/index.js16
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/store/actions.js83
-rw-r--r--app/assets/javascripts/create_cluster/init_create_cluster.js8
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml1
-rw-r--r--app/views/clusters/clusters/new.html.haml1
-rw-r--r--app/views/layouts/header/_default.html.haml2
-rw-r--r--app/views/shared/members/_badge.html.haml2
-rw-r--r--changelogs/unreleased/use-dynamic-import-for-gapi.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-19353.yml5
-rw-r--r--doc/ci/multi_project_pipelines.md3
-rw-r--r--spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js47
-rw-r--r--spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js2
14 files changed, 148 insertions, 56 deletions
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js b/app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js
new file mode 100644
index 00000000000..b5f92fed8eb
--- /dev/null
+++ b/app/assets/javascripts/create_cluster/gke_cluster/gapi_loader.js
@@ -0,0 +1,24 @@
+// This is a helper module to lazily import the google APIs for the GKE cluster
+// integration without introducing an indirect global dependency on an
+// initialized window.gapi object.
+export default () => {
+ if (window.gapiPromise === undefined) {
+ // first time loading the module
+ window.gapiPromise = new Promise((resolve, reject) => {
+ // this callback is set as a query param to script.src URL
+ window.onGapiLoad = () => {
+ resolve(window.gapi);
+ };
+
+ const script = document.createElement('script');
+ // do not use script.onload, because gapi continues to load after the initial script load
+ script.type = 'text/javascript';
+ script.async = true;
+ script.src = 'https://apis.google.com/js/api.js?onload=onGapiLoad';
+ script.onerror = reject;
+ document.head.appendChild(script);
+ });
+ }
+
+ return window.gapiPromise;
+};
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/index.js b/app/assets/javascripts/create_cluster/gke_cluster/index.js
index 96043470b63..c02173fc510 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/index.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/index.js
@@ -1,10 +1,10 @@
-/* global gapi */
import Vue from 'vue';
import { deprecatedCreateFlash as Flash } from '~/flash';
import GkeProjectIdDropdown from './components/gke_project_id_dropdown.vue';
import GkeZoneDropdown from './components/gke_zone_dropdown.vue';
import GkeMachineTypeDropdown from './components/gke_machine_type_dropdown.vue';
import GkeSubmitButton from './components/gke_submit_button.vue';
+import gapiLoader from './gapi_loader';
import store from './store';
@@ -63,7 +63,7 @@ const gkeDropdownErrorHandler = () => {
Flash(CONSTANTS.GCP_API_ERROR);
};
-const initializeGapiClient = () => {
+const initializeGapiClient = (gapi) => () => {
const el = document.querySelector('.js-gke-cluster-creation');
if (!el) return false;
@@ -86,13 +86,9 @@ const initializeGapiClient = () => {
.catch(gkeDropdownErrorHandler);
};
-const initGkeDropdowns = () => {
- if (!gapi) {
- gkeDropdownErrorHandler();
- return false;
- }
-
- return gapi.load('client', initializeGapiClient);
-};
+const initGkeDropdowns = () =>
+ gapiLoader()
+ .then((gapi) => gapi.load('client', initializeGapiClient(gapi)))
+ .catch(gkeDropdownErrorHandler);
export default initGkeDropdowns;
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
index 62ff8358c87..8977053297a 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
@@ -1,5 +1,5 @@
-/* global gapi */
import * as types from './mutation_types';
+import gapiLoader from '../gapi_loader';
const gapiResourceListRequest = ({ resource, params, commit, mutation, payloadKey }) =>
new Promise((resolve, reject) => {
@@ -36,57 +36,64 @@ export const setIsValidatingProjectBilling = ({ commit }, isValidatingProjectBil
};
export const fetchProjects = ({ commit }) =>
- gapiResourceListRequest({
- resource: gapi.client.cloudresourcemanager.projects,
- params: {},
- commit,
- mutation: types.SET_PROJECTS,
- payloadKey: 'projects',
- });
+ gapiLoader().then((gapi) =>
+ gapiResourceListRequest({
+ resource: gapi.client.cloudresourcemanager.projects,
+ params: {},
+ commit,
+ mutation: types.SET_PROJECTS,
+ payloadKey: 'projects',
+ }),
+ );
export const validateProjectBilling = ({ dispatch, commit, state }) =>
- new Promise((resolve, reject) => {
- const request = gapi.client.cloudbilling.projects.getBillingInfo({
- name: `projects/${state.selectedProject.projectId}`,
- });
+ gapiLoader()
+ .then((gapi) => {
+ const request = gapi.client.cloudbilling.projects.getBillingInfo({
+ name: `projects/${state.selectedProject.projectId}`,
+ });
- commit(types.SET_ZONE, '');
- commit(types.SET_MACHINE_TYPE, '');
+ commit(types.SET_ZONE, '');
+ commit(types.SET_MACHINE_TYPE, '');
- return request.then(
+ return request;
+ })
+ .then(
(resp) => {
const { billingEnabled } = resp.result;
commit(types.SET_PROJECT_BILLING_STATUS, Boolean(billingEnabled));
dispatch('setIsValidatingProjectBilling', false);
- resolve();
},
- (resp) => {
+ (errorResp) => {
dispatch('setIsValidatingProjectBilling', false);
- reject(resp);
+ return errorResp;
},
);
- });
export const fetchZones = ({ commit, state }) =>
- gapiResourceListRequest({
- resource: gapi.client.compute.zones,
- params: {
- project: state.selectedProject.projectId,
- },
- commit,
- mutation: types.SET_ZONES,
- payloadKey: 'items',
- });
+ gapiLoader().then((gapi) =>
+ gapiResourceListRequest({
+ resource: gapi.client.compute.zones,
+ params: {
+ project: state.selectedProject.projectId,
+ },
+ commit,
+ mutation: types.SET_ZONES,
+ payloadKey: 'items',
+ }),
+ );
export const fetchMachineTypes = ({ commit, state }) =>
- gapiResourceListRequest({
- resource: gapi.client.compute.machineTypes,
- params: {
- project: state.selectedProject.projectId,
- zone: state.selectedZone,
- },
- commit,
- mutation: types.SET_MACHINE_TYPES,
- payloadKey: 'items',
- });
+ gapiLoader().then((gapi) =>
+ gapiResourceListRequest({
+ resource: gapi.client.compute.machineTypes,
+ params: {
+ project: state.selectedProject.projectId,
+ zone: state.selectedZone,
+ },
+ commit,
+ mutation: types.SET_MACHINE_TYPES,
+ payloadKey: 'items',
+ }),
+ );
diff --git a/app/assets/javascripts/create_cluster/init_create_cluster.js b/app/assets/javascripts/create_cluster/init_create_cluster.js
index 11e0d93f4fb..f97da3d55db 100644
--- a/app/assets/javascripts/create_cluster/init_create_cluster.js
+++ b/app/assets/javascripts/create_cluster/init_create_cluster.js
@@ -19,6 +19,10 @@ export default (document) => {
initGkeDropdowns();
+ if (isProjectLevelCluster(page)) {
+ initGkeNamespace();
+ }
+
import(/* webpackChunkName: 'eks_cluster' */ '~/create_cluster/eks_cluster')
.then(({ default: initCreateEKSCluster }) => {
const el = document.querySelector('.js-create-eks-cluster-form-container');
@@ -28,8 +32,4 @@ export default (document) => {
}
})
.catch(() => {});
-
- if (isProjectLevelCluster(page)) {
- initGkeNamespace();
- }
};
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index 573b96caae5..50e3d29f974 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -1,4 +1,3 @@
-= javascript_include_tag 'https://apis.google.com/js/api.js'
- external_link_icon = sprite_icon('external-link')
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- machine_type_link_url = 'https://cloud.google.com/compute/docs/machine-types'
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
index ff33fb46db8..74e336723ba 100644
--- a/app/views/clusters/clusters/new.html.haml
+++ b/app/views/clusters/clusters/new.html.haml
@@ -2,7 +2,6 @@
- page_title _('Kubernetes Cluster')
- active_tab = local_assigns.fetch(:active_tab, 'create')
- provider = params[:provider]
-= javascript_include_tag 'https://apis.google.com/js/api.js'
= render_gcp_signup_offer
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 1394f15cd15..f7e93182ca2 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -16,7 +16,7 @@
= logo_text
- if Gitlab.com_and_canary?
= link_to 'https://next.gitlab.com', class: 'canary-badge bg-transparent', target: :_blank do
- %span.color-label.has-tooltip.badge.badge-pill.green-badge
+ %span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
- if current_user
diff --git a/app/views/shared/members/_badge.html.haml b/app/views/shared/members/_badge.html.haml
index e304207f3e9..5f925ff0cad 100644
--- a/app/views/shared/members/_badge.html.haml
+++ b/app/views/shared/members/_badge.html.haml
@@ -1,4 +1,4 @@
- type ||= 'info'
%span.px-1.py-1
- %span{ class: "badge badge-#{type}" }= yield
+ %span{ class: "badge badge-pill gl-badge sm badge-#{type}" }= yield
diff --git a/changelogs/unreleased/use-dynamic-import-for-gapi.yml b/changelogs/unreleased/use-dynamic-import-for-gapi.yml
new file mode 100644
index 00000000000..811dfd7db67
--- /dev/null
+++ b/changelogs/unreleased/use-dynamic-import-for-gapi.yml
@@ -0,0 +1,5 @@
+---
+title: Dynamically load gapi on GKE cluster creation pages
+merge_request: 49512
+author:
+type: other
diff --git a/changelogs/unreleased/yo-gl-badge.yml b/changelogs/unreleased/yo-gl-badge.yml
new file mode 100644
index 00000000000..0c214026b0c
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge to members list badges
+merge_request: 51546
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-master-patch-19353.yml b/changelogs/unreleased/yo-master-patch-19353.yml
new file mode 100644
index 00000000000..b12133fdb9c
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-19353.yml
@@ -0,0 +1,5 @@
+---
+title: Update canary(next) badge style with new GitLab UI
+merge_request: 50965
+author: Yogi (@yo)
+type: other
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
index 1df196182c0..006d6bda0e0 100644
--- a/doc/ci/multi_project_pipelines.md
+++ b/doc/ci/multi_project_pipelines.md
@@ -13,6 +13,9 @@ type: reference
You can set up [GitLab CI/CD](README.md) across multiple projects, so that a pipeline
in one project can trigger a pipeline in another project.
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview see the [Multi-project pipelines demo](https://www.youtube.com/watch?v=g_PIwBM1J84).
+
GitLab CI/CD is a powerful continuous integration tool that works not only per project,
but also across projects with multi-project pipelines.
diff --git a/spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js b/spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js
new file mode 100644
index 00000000000..9e4d6996340
--- /dev/null
+++ b/spec/frontend/create_cluster/gke_cluster/gapi_loader_spec.js
@@ -0,0 +1,47 @@
+import gapiLoader from '~/create_cluster/gke_cluster/gapi_loader';
+
+describe('gapiLoader', () => {
+ // A mock for document.head.appendChild to intercept the script tag injection.
+ let mockDOMHeadAppendChild;
+
+ beforeEach(() => {
+ mockDOMHeadAppendChild = jest.spyOn(document.head, 'appendChild');
+ });
+
+ afterEach(() => {
+ mockDOMHeadAppendChild.mockRestore();
+ delete window.gapi;
+ delete window.gapiPromise;
+ delete window.onGapiLoad;
+ });
+
+ it('returns a promise', () => {
+ expect(gapiLoader()).toBeInstanceOf(Promise);
+ });
+
+ it('returns the same promise when already loading', () => {
+ const first = gapiLoader();
+ const second = gapiLoader();
+ expect(first).toBe(second);
+ });
+
+ it('resolves the promise when the script loads correctly', async () => {
+ mockDOMHeadAppendChild.mockImplementationOnce((script) => {
+ script.removeAttribute('src');
+ script.appendChild(
+ document.createTextNode(`window.gapi = 'hello gapi'; window.onGapiLoad()`),
+ );
+ document.head.appendChild(script);
+ });
+ await expect(gapiLoader()).resolves.toBe('hello gapi');
+ expect(mockDOMHeadAppendChild).toHaveBeenCalled();
+ });
+
+ it('rejects the promise when the script fails loading', async () => {
+ mockDOMHeadAppendChild.mockImplementationOnce((script) => {
+ script.onerror(new Error('hello error'));
+ });
+ await expect(gapiLoader()).rejects.toThrow('hello error');
+ expect(mockDOMHeadAppendChild).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js b/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
index eb58c4c6904..8852baafec7 100644
--- a/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
@@ -71,10 +71,12 @@ describe('GCP Cluster Dropdown Store Actions', () => {
beforeAll(() => {
originalGapi = window.gapi;
window.gapi = gapi;
+ window.gapiPromise = Promise.resolve(gapi);
});
afterAll(() => {
window.gapi = originalGapi;
+ delete window.gapiPromise;
});
describe('fetchProjects', () => {