Commit b42eafb0 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent c7c5fbd2bdfd
VERSION merge=ours
Dangerfile gitlab-language=ruby
db/schema.rb merge=merge_db_schema
......@@ -67,3 +67,18 @@ docs lint:
- bundle exec nanoc check internal_links
# Check the internal anchor links
- bundle exec nanoc check internal_anchors
graphql-docs-verify:
extends:
- .default-tags
- .default-retry
- .default-cache
- .default-only
- .default-before_script
- .only-graphql-changes
variables:
SETUP_DB: "false"
stage: test
needs: ["setup-test-env"]
script:
- bundle exec rake gitlab:graphql:check_docs
......@@ -53,7 +53,7 @@
- gitlab-org
- docker
gitlab:assets:compile:
gitlab:assets:compile pull-push-cache:
extends: .gitlab:assets:compile-metadata
only:
refs:
......@@ -63,9 +63,6 @@ gitlab:assets:compile:
gitlab:assets:compile pull-cache:
extends: .gitlab:assets:compile-metadata
except:
refs:
- master
cache:
policy: pull
......@@ -89,14 +86,14 @@ gitlab:assets:compile pull-cache:
# we override the max_old_space_size to prevent OOM errors
NODE_OPTIONS: --max_old_space_size=3584
cache:
key: "assets-compile:test:vendor_ruby:.yarn-cache:tmp_cache_assets_sprockets:v6"
key: "assets-compile:v7"
artifacts:
expire_in: 7d
paths:
- node_modules
- public/assets
compile-assets:
compile-assets pull-push-cache:
extends: .compile-assets-metadata
only:
refs:
......@@ -104,13 +101,25 @@ compile-assets:
cache:
policy: pull-push
compile-assets pull-cache:
extends: .compile-assets-metadata
except:
compile-assets pull-push-cache foss:
extends: [".compile-assets-metadata", ".only-ee-as-if-foss"]
only:
refs:
- master
cache:
policy: pull-push
key: "assets-compile:v7:foss"
compile-assets pull-cache:
extends: .compile-assets-metadata
cache:
policy: pull
compile-assets pull-cache foss:
extends: [".compile-assets-metadata", ".only-ee-as-if-foss"]
cache:
policy: pull
key: "assets-compile:v7:foss"
.only-code-frontend-job-base:
extends:
......@@ -121,7 +130,9 @@ compile-assets pull-cache:
- .default-before_script
- .only-code-changes
- .use-pg9
dependencies: ["compile-assets", "compile-assets pull-cache", "setup-test-env"]
stage: test
needs: ["setup-test-env", "compile-assets pull-cache"]
dependencies: ["setup-test-env", "compile-assets pull-cache"]
.karma-base:
extends: .only-code-frontend-job-base
......@@ -195,6 +206,7 @@ jest-foss:
- .default-cache
- .default-only
- .only-code-changes
stage: test
dependencies: []
cache:
key: "$CI_JOB_NAME"
......@@ -227,7 +239,9 @@ webpack-dev-server:
- .default-cache
- .default-only
- .only-code-changes
dependencies: ["setup-test-env", "compile-assets", "compile-assets pull-cache"]
stage: test
needs: ["setup-test-env", "compile-assets pull-cache"]
dependencies: ["setup-test-env", "compile-assets pull-cache"]
variables:
WEBPACK_MEMORY_TEST: "true"
script:
......
......@@ -71,6 +71,12 @@
- "doc/**/*"
- ".markdownlint.json"
.only-graphql-changes:
only:
changes:
- "{,ee/}app/graphql/**/*"
- "{,ee/}lib/gitlab/graphql/**/*"
.only-code-qa-changes:
only:
changes:
......@@ -153,4 +159,4 @@
.only-ee-as-if-foss:
extends: .only-ee
variables:
IS_GITLAB_EE: '0'
FOSS_ONLY: '1'
......@@ -11,7 +11,7 @@ pages:
variables:
- $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
stage: pages
dependencies: ["coverage", "karma", "gitlab:assets:compile"]
dependencies: ["coverage", "karma", "gitlab:assets:compile pull-cache"]
script:
- mv public/ .public/
- mkdir public/
......
......@@ -71,4 +71,4 @@ schedule:package-and-qa:
- .package-and-qa-base
- .only-code-qa-changes
- .only-canonical-schedules
needs: ["build-qa-image", "gitlab:assets:compile"]
needs: ["build-qa-image", "gitlab:assets:compile pull-cache"]
......@@ -53,6 +53,8 @@ setup-test-env:
.rspec-base:
extends: .only-code-rails-job-base
stage: test
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-assets pull-cache"]
dependencies: ["setup-test-env", "retrieve-tests-metadata", "compile-assets pull-cache"]
script:
- source scripts/rspec_helpers.sh
- rspec_paralellized_job "--tag ~quarantine --tag ~geo"
......@@ -69,6 +71,11 @@ setup-test-env:
reports:
junit: junit_rspec.xml
.rspec-base-foss:
extends: [".rspec-base", ".only-ee-as-if-foss"]
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-assets pull-cache foss"]
dependencies: ["setup-test-env", "retrieve-tests-metadata", "compile-assets pull-cache foss"]
.rspec-base-pg9:
extends:
- .rspec-base
......@@ -76,9 +83,8 @@ setup-test-env:
.rspec-base-pg9-foss:
extends:
- .rspec-base
- .rspec-base-foss
- .use-pg9
- .only-ee-as-if-foss
.rspec-base-pg10:
extends:
......@@ -106,10 +112,9 @@ rspec system pg9:
extends: .rspec-base-pg9
parallel: 24
# TODO: This requires FOSS assets
# rspec system pg9-foss:
# extends: .rspec-base-pg9-foss
# parallel: 24
rspec system pg9-foss:
extends: .rspec-base-pg9-foss
parallel: 24
rspec unit pg10:
extends: .rspec-base-pg10
......@@ -229,7 +234,9 @@ rspec fast_spec_helper:
static-analysis:
extends: .only-code-qa-rails-job-base
dependencies: ["setup-test-env", "compile-assets", "compile-assets pull-cache"]
stage: test
needs: ["setup-test-env", "compile-assets pull-cache"]
dependencies: ["setup-test-env", "compile-assets pull-cache"]
variables:
SETUP_DB: "false"
script:
......@@ -252,16 +259,16 @@ downtime_check:
variables:
- $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/
stage: test
dependencies: ["setup-test-env"]
needs: ["setup-test-env"]
dependencies: ["setup-test-env"]
.db-job-base:
extends:
- .only-code-rails-job-base
- .use-pg9
stage: test
dependencies: ["setup-test-env"]
needs: ["setup-test-env"]
dependencies: ["setup-test-env"]
# DB migration, rollback, and seed jobs
db:migrate:reset:
......
......@@ -81,7 +81,7 @@ schedule:review-build-cng:
extends:
- .review-build-cng-base
- .only-review-schedules
needs: ["gitlab:assets:compile"]
needs: ["gitlab:assets:compile pull-cache"]
.review-deploy-base:
extends:
......@@ -97,7 +97,7 @@ schedule:review-build-cng:
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "master"
GITLAB_HELM_CHART_REF: "v2.3.7"
GITLAB_EDITION: "ce"
environment:
name: review/${CI_COMMIT_REF_NAME}
......
......@@ -36,6 +36,7 @@ const Api = {
branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch',
createBranchPath: '/api/:version/projects/:id/repository/branches',
releasesPath: '/api/:version/projects/:id/releases',
releasePath: '/api/:version/projects/:id/releases/:tag_name',
mergeRequestsPipeline: '/api/:version/projects/:id/merge_requests/:merge_request_iid/pipelines',
adminStatisticsPath: 'api/:version/application/statistics',
......@@ -391,6 +392,22 @@ const Api = {
return axios.get(url);
},
release(projectPath, tagName) {
const url = Api.buildUrl(this.releasePath)
.replace(':id', encodeURIComponent(projectPath))
.replace(':tag_name', encodeURIComponent(tagName));
return axios.get(url);
},
updateRelease(projectPath, tagName, release) {
const url = Api.buildUrl(this.releasePath)
.replace(':id', encodeURIComponent(projectPath))
.replace(':tag_name', encodeURIComponent(tagName));
return axios.put(url, release);
},
adminStatistics() {
const url = Api.buildUrl(this.adminStatisticsPath);
return axios.get(url);
......
import ZenMode from '~/zen_mode';
import initEditRelease from '~/releases/detail';
document.addEventListener('DOMContentLoaded', () => {
new ZenMode(); // eslint-disable-line no-new
initEditRelease();
});
<script>
import { mapState, mapActions } from 'vuex';
import { GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
export default {
name: 'ReleaseDetailApp',
components: {
GlFormInput,
GlFormGroup,
GlButton,
MarkdownField,
},
directives: {
autofocusonshow,
},
computed: {
...mapState([
'isFetchingRelease',
'fetchError',
'markdownDocsPath',
'markdownPreviewPath',
'releasesPagePath',
]),
showForm() {
return !this.isFetchingRelease && !this.fetchError;
},
subtitleText() {
return sprintf(
__(
'Releases are based on Git tags. We recommend naming tags that fit within semantic versioning, for example %{codeStart}v1.0%{codeEnd}, %{codeStart}v2.0-pre%{codeEnd}.',
),
{
codeStart: '<code>',
codeEnd: '</code>',
},
false,
);
},
tagName() {
return this.$store.state.release.tagName;
},
releaseTitle: {
get() {
return this.$store.state.release.name;
},
set(title) {
this.updateReleaseTitle(title);
},
},
releaseNotes: {
get() {
return this.$store.state.release.description;
},
set(notes) {
this.updateReleaseNotes(notes);
},
},
},
created() {
this.fetchRelease();
},
methods: {
...mapActions([
'fetchRelease',
'updateRelease',
'updateReleaseTitle',
'updateReleaseNotes',
'navigateToReleasesPage',
]),
},
};
</script>
<template>
<div class="d-flex flex-column">
<p class="pt-3 js-subtitle-text" v-html="subtitleText"></p>
<form v-if="showForm" @submit.prevent="updateRelease()">
<div class="row">
<gl-form-group class="col-md-6 col-lg-5 col-xl-4">
<label for="git-ref">{{ __('Tag name') }}</label>
<gl-form-input
id="git-ref"
v-model="tagName"
type="text"
class="form-control"
aria-describedby="tag-name-help"
disabled
/>
<div id="tag-name-help" class="form-text text-muted">
{{ __('Choose an existing tag, or create a new one') }}
</div>
</gl-form-group>
</div>
<gl-form-group>
<label for="release-title">{{ __('Release title') }}</label>
<gl-form-input
id="release-title"
ref="releaseTitleInput"
v-model="releaseTitle"
v-autofocusonshow
autofocus
type="text"
class="form-control"
/>
</gl-form-group>
<gl-form-group>
<label for="release-notes">{{ __('Release notes') }}</label>
<div class="bordered-box pr-3 pl-3">
<markdown-field
:can-attach-file="true"
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
:add-spacing-classes="false"
class="prepend-top-10 append-bottom-10"
>
<textarea
id="release-notes"
slot="textarea"
v-model="releaseNotes"
class="note-textarea js-gfm-input js-autosize markdown-area"
dir="auto"
data-supports-quick-actions="false"
:aria-label="__('Release notes')"
:placeholder="__('Write your release notes or drag your files here…')"
@keydown.meta.enter="updateRelease()"
@keydown.ctrl.enter="updateRelease()"
>
</textarea>
</markdown-field>
</div>
</gl-form-group>
<div class="d-flex pt-3">
<gl-button
class="mr-auto js-submit-button"
variant="success"
type="submit"
:aria-label="__('Save changes')"
>
{{ __('Save changes') }}
</gl-button>
<gl-button
class="js-cancel-button"
variant="default"
type="button"
:aria-label="__('Cancel')"
@click="navigateToReleasesPage()"
>
{{ __('Cancel') }}
</gl-button>
</div>
</form>
</div>
</template>
import Vue from 'vue';
import ReleaseDetailApp from './components/app.vue';
import createStore from './store';
export default () => {
const el = document.getElementById('js-edit-release-page');
const store = createStore(el.dataset);
store.dispatch('setInitialState', el.dataset);
return new Vue({
el,
store,
components: { ReleaseDetailApp },
render(createElement) {
return createElement('release-detail-app');
},
});
};
import * as types from './mutation_types';
import api from '~/api';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
export const setInitialState = ({ commit }, initialState) =>
commit(types.SET_INITIAL_STATE, initialState);
export const requestRelease = ({ commit }) => commit(types.REQUEST_RELEASE);
export const receiveReleaseSuccess = ({ commit }, data) =>
commit(types.RECEIVE_RELEASE_SUCCESS, data);
export const receiveReleaseError = ({ commit }, error) => {
commit(types.RECEIVE_RELEASE_ERROR, error);
createFlash(s__('Release|Something went wrong while getting the release details'));
};
export const fetchRelease = ({ dispatch, state }) => {
dispatch('requestRelease');
return api
.release(state.projectId, state.tagName)
.then(({ data: release }) => {
const camelCasedRelease = convertObjectPropsToCamelCase(release, { deep: true });
dispatch('receiveReleaseSuccess', camelCasedRelease);
})
.catch(error => {
dispatch('receiveReleaseError', error);
});
};
export const updateReleaseTitle = ({ commit }, title) => commit(types.UPDATE_RELEASE_TITLE, title);
export const updateReleaseNotes = ({ commit }, notes) => commit(types.UPDATE_RELEASE_NOTES, notes);
export const requestUpdateRelease = ({ commit }) => commit(types.REQUEST_UPDATE_RELEASE);
export const receiveUpdateReleaseSuccess = ({ commit, dispatch }) => {
commit(types.RECEIVE_UPDATE_RELEASE_SUCCESS);
dispatch('navigateToReleasesPage');
};
export const receiveUpdateReleaseError = ({ commit }, error) => {
commit(types.RECEIVE_UPDATE_RELEASE_ERROR, error);
createFlash(s__('Release|Something went wrong while saving the release details'));
};
export const updateRelease = ({ dispatch, state }) => {
dispatch('requestUpdateRelease');
return api
.updateRelease(state.projectId, state.tagName, {
name: state.release.name,
description: state.release.description,
})
.then(() => dispatch('receiveUpdateReleaseSuccess'))
.catch(error => {
dispatch('receiveUpdateReleaseError', error);
});
};
export const navigateToReleasesPage = ({ state }) => {
redirectTo(state.releasesPagePath);
};
import Vue from 'vue';
import Vuex from 'vuex';
import * as actions from './actions';
import mutations from './mutations';
import state from './state';
Vue.use(Vuex);
export default () =>
new Vuex.Store({
actions,
mutations,
state,
});
export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
export const REQUEST_RELEASE = 'REQUEST_RELEASE';
export const RECEIVE_RELEASE_SUCCESS = 'RECEIVE_RELEASE_SUCCESS';
export const RECEIVE_RELEASE_ERROR = 'RECEIVE_RELEASE_ERROR';
export const UPDATE_RELEASE_TITLE = 'UPDATE_RELEASE_TITLE';
export const UPDATE_RELEASE_NOTES = 'UPDATE_RELEASE_NOTES';
export const REQUEST_UPDATE_RELEASE = 'REQUEST_UPDATE_RELEASE';
export const RECEIVE_UPDATE_RELEASE_SUCCESS = 'RECEIVE_UPDATE_RELEASE_SUCCESS';
export const RECEIVE_UPDATE_RELEASE_ERROR = 'RECEIVE_UPDATE_RELEASE_ERROR';
import * as types from './mutation_types';
export default {
[types.SET_INITIAL_STATE](state, initialState) {
Object.keys(state).forEach(key => {
state[key] = initialState[key];
});
},
[types.REQUEST_RELEASE](state) {
state.isFetchingRelease = true;
},
[types.RECEIVE_RELEASE_SUCCESS](state, data) {
state.fetchError = undefined;
state.isFetchingRelease = false;
state.release = data;
},
[types.RECEIVE_RELEASE_ERROR](state, error) {
state.fetchError = error;
state.isFetchingRelease = false;
state.release = undefined;
},
[types.UPDATE_RELEASE_TITLE](state, title) {
state.release.name = title;
},
[types.UPDATE_RELEASE_NOTES](state, notes) {
state.release.description = notes;
},
[types.REQUEST_UPDATE_RELEASE](state) {
state.isUpdatingRelease = true;
},
[types.RECEIVE_UPDATE_RELEASE_SUCCESS](state) {
state.updateError = undefined;
state.isUpdatingRelease = false;
},
[types.RECEIVE_UPDATE_RELEASE_ERROR](state, error) {
state.updateError = error;
state.isUpdatingRelease = false;
},
};
export default () => ({
projectId: null,