Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
aadb3204ea
commit
04befb368f
|
|
@ -55,7 +55,7 @@ export default {
|
|||
<div>
|
||||
<div class="gl-mb-1">
|
||||
<gl-link :href="href" class="gl-font-weight-bold gl-text-gray-900!">{{ fullName }}</gl-link>
|
||||
<gl-badge v-if="isOwner" variant="info">{{ s__('Runner|Owner') }}</gl-badge>
|
||||
<gl-badge v-if="isOwner" variant="info">{{ s__('Runners|Owner') }}</gl-badge>
|
||||
</div>
|
||||
<div v-if="description">{{ description }}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ export default {
|
|||
onError(error) {
|
||||
this.deleting = false;
|
||||
const { message } = error;
|
||||
const title = sprintf(s__('Runner|Runner %{runnerName} failed to delete'), {
|
||||
const title = sprintf(s__('Runners|Runner %{runnerName} failed to delete'), {
|
||||
runnerName: this.runnerName,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -72,12 +72,19 @@ export default {
|
|||
},
|
||||
setBaseImageSize() {
|
||||
const { contentImg } = this.$refs;
|
||||
if (!contentImg || contentImg.offsetHeight === 0 || contentImg.offsetWidth === 0) return;
|
||||
if (!contentImg) return;
|
||||
if (contentImg.offsetHeight === 0 || contentImg.offsetWidth === 0) {
|
||||
this.baseImageSize = {
|
||||
height: contentImg.naturalHeight,
|
||||
width: contentImg.naturalWidth,
|
||||
};
|
||||
} else {
|
||||
this.baseImageSize = {
|
||||
height: contentImg.offsetHeight,
|
||||
width: contentImg.offsetWidth,
|
||||
};
|
||||
}
|
||||
|
||||
this.baseImageSize = {
|
||||
height: contentImg.offsetHeight,
|
||||
width: contentImg.offsetWidth,
|
||||
};
|
||||
this.onResize({ width: this.baseImageSize.width, height: this.baseImageSize.height });
|
||||
},
|
||||
setImageNaturalScale() {
|
||||
|
|
@ -96,6 +103,11 @@ export default {
|
|||
|
||||
const { height, width } = this.baseImageSize;
|
||||
|
||||
this.imageStyle = {
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
};
|
||||
|
||||
this.$parent.$emit(
|
||||
'setMaxScale',
|
||||
Math.round(((height + width) / (naturalHeight + naturalWidth)) * 100) / 100,
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ export default {
|
|||
/>
|
||||
</span>
|
||||
</div>
|
||||
<gl-intersection-observer @appear="onAppear">
|
||||
<gl-intersection-observer class="gl-flex-grow-1" @appear="onAppear">
|
||||
<gl-loading-icon v-if="showLoadingSpinner" size="lg" />
|
||||
<gl-icon
|
||||
v-else-if="showImageErrorIcon"
|
||||
|
|
@ -156,7 +156,7 @@ export default {
|
|||
v-show="showImage"
|
||||
:src="imageLink"
|
||||
:alt="filename"
|
||||
class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full design-img"
|
||||
class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full gl-w-auto design-img"
|
||||
data-qa-selector="design_image"
|
||||
:data-qa-filename="filename"
|
||||
:data-testid="`design-img-${id}`"
|
||||
|
|
|
|||
|
|
@ -5,16 +5,32 @@ export default {
|
|||
hasChildren: false,
|
||||
};
|
||||
},
|
||||
updated() {
|
||||
this.hasChildren = this.checkSlots();
|
||||
},
|
||||
mounted() {
|
||||
this.hasChildren = this.checkSlots();
|
||||
const setHasChildren = () => {
|
||||
this.hasChildren = Boolean(this.$el.innerText.trim());
|
||||
};
|
||||
|
||||
// Set initial.
|
||||
setHasChildren();
|
||||
|
||||
if (!this.hasChildren) {
|
||||
// Observe children changed.
|
||||
this.observer = new MutationObserver(() => {
|
||||
setHasChildren();
|
||||
|
||||
if (this.hasChildren) {
|
||||
this.observer.disconnect();
|
||||
this.observer = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
this.observer.observe(this.$el, { childList: true, subtree: true });
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkSlots() {
|
||||
return this.$scopedSlots.default?.()?.some((c) => c.elm?.innerText);
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -293,7 +293,10 @@ export default {
|
|||
return this.isWidgetPresent(WIDGET_TYPE_NOTES);
|
||||
},
|
||||
fetchByIid() {
|
||||
return this.glFeatures.useIidInWorkItemsPath && parseBoolean(getParameterByName('iid_path'));
|
||||
return (
|
||||
(this.glFeatures.useIidInWorkItemsPath && parseBoolean(getParameterByName('iid_path'))) ||
|
||||
false
|
||||
);
|
||||
},
|
||||
queryVariables() {
|
||||
return this.fetchByIid
|
||||
|
|
@ -572,7 +575,6 @@ export default {
|
|||
@error="updateError = $event"
|
||||
/>
|
||||
<work-item-created-updated
|
||||
v-if="workItemsMvcEnabled"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItemIid"
|
||||
:full-path="fullPath"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module Ci
|
|||
include Ci::HasRunnerExecutor
|
||||
include IgnorableColumns
|
||||
|
||||
ignore_column :machine_xid, remove_with: '15.10', remove_after: '2022-03-22'
|
||||
ignore_column :machine_xid, remove_with: '15.11', remove_after: '2022-03-22'
|
||||
|
||||
belongs_to :runner
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Enums
|
||||
class PackageMetadata
|
||||
PURL_TYPES = {
|
||||
composer: 1,
|
||||
conan: 2,
|
||||
gem: 3,
|
||||
golang: 4,
|
||||
maven: 5,
|
||||
npm: 6,
|
||||
nuget: 7,
|
||||
pypi: 8
|
||||
}.with_indifferent_access.freeze
|
||||
|
||||
def self.purl_types
|
||||
PURL_TYPES
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,6 +2,36 @@
|
|||
|
||||
module Ci
|
||||
class ArchiveTraceService
|
||||
include ::Gitlab::ExclusiveLeaseHelpers
|
||||
|
||||
EXCLUSIVE_LOCK_KEY = 'archive_trace_service:batch_execute:lock'
|
||||
LOCK_TIMEOUT = 56.minutes
|
||||
LOOP_TIMEOUT = 55.minutes
|
||||
LOOP_LIMIT = 2000
|
||||
BATCH_SIZE = 100
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def batch_execute(worker_name:)
|
||||
start_time = Time.current
|
||||
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
|
||||
Ci::Build.with_stale_live_trace.find_each(batch_size: BATCH_SIZE).with_index do |build, index|
|
||||
break if Time.current - start_time > LOOP_TIMEOUT
|
||||
|
||||
if index > LOOP_LIMIT
|
||||
Sidekiq.logger.warn(class: worker_name, message: 'Loop limit reached.', job_id: build.id)
|
||||
break
|
||||
end
|
||||
|
||||
begin
|
||||
execute(build, worker_name: worker_name)
|
||||
rescue StandardError
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def execute(job, worker_name:)
|
||||
unless job.trace.archival_attempts_available?
|
||||
Sidekiq.logger.warn(class: worker_name, message: 'The job is out of archival attempts.', job_id: job.id)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- add_to_breadcrumbs _('Runners'), admin_runners_path
|
||||
- breadcrumb_title s_('Runner|New')
|
||||
- breadcrumb_title s_('Runners|New')
|
||||
- page_title s_('Runners|Create an instance runner')
|
||||
|
||||
#js-admin-new-runner{ data: {
|
||||
|
|
|
|||
|
|
@ -9,14 +9,20 @@ module Ci
|
|||
include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
|
||||
|
||||
feature_category :continuous_integration
|
||||
deduplicate :until_executed, including_scheduled: true
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def perform
|
||||
# Archive stale live traces which still resides in redis or database
|
||||
# This could happen when Ci::ArchiveTraceWorker sidekiq jobs were lost by receiving SIGKILL
|
||||
# More details in https://gitlab.com/gitlab-org/gitlab-foss/issues/36791
|
||||
Ci::Build.with_stale_live_trace.find_each(batch_size: 100) do |build|
|
||||
Ci::ArchiveTraceService.new.execute(build, worker_name: self.class.name)
|
||||
|
||||
if Feature.enabled?(:deduplicate_archive_traces_cron_worker)
|
||||
Ci::ArchiveTraceService.new.batch_execute(worker_name: self.class.name)
|
||||
else
|
||||
Ci::Build.with_stale_live_trace.find_each(batch_size: 100) do |build|
|
||||
Ci::ArchiveTraceService.new.execute(build, worker_name: self.class.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: deduplicate_archive_traces_cron_worker
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110305
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/389632
|
||||
milestone: '15.9'
|
||||
type: development
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
||||
|
|
@ -60,3 +60,12 @@ ISO3166::Data.register(
|
|||
currency_code: "UAH",
|
||||
start_of_week: "monday"
|
||||
)
|
||||
|
||||
# Updating the display name of Taiwan, from `Taiwan, Province of China` to `Taiwan`
|
||||
# See issue: https://gitlab.com/gitlab-org/gitlab/-/issues/349333
|
||||
ISO3166::Data.register(
|
||||
ISO3166::Data.new('TW')
|
||||
.call
|
||||
.deep_symbolize_keys
|
||||
.merge({ name: 'Taiwan' })
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
table_name: pm_checkpoints
|
||||
classes:
|
||||
- PackageMetadata::Checkpoint
|
||||
feature_categories:
|
||||
- license_compliance
|
||||
description: Tracks position of last synced file.
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109713
|
||||
milestone: '15.9'
|
||||
gitlab_schema: gitlab_pm
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPackageMetadataCheckpoints < Gitlab::Database::Migration[2.1]
|
||||
def up
|
||||
create_table :pm_checkpoints, id: false do |t|
|
||||
t.integer :sequence, null: false
|
||||
t.timestamps_with_timezone
|
||||
t.integer :purl_type, null: false, primary_key: true
|
||||
t.integer :chunk, null: false, limit: 2
|
||||
end
|
||||
|
||||
change_column(:pm_checkpoints, :purl_type, :integer, limit: 2)
|
||||
drop_sequence(:pm_checkpoints, :purl_type, 'pm_checkpoints_purl_type_seq')
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :pm_checkpoints
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
e5498ebd6ea0c18271078236a4f64b447fa5c55318b92c04f12a66834a38f67d
|
||||
|
|
@ -19816,6 +19816,14 @@ CREATE SEQUENCE plans_id_seq
|
|||
|
||||
ALTER SEQUENCE plans_id_seq OWNED BY plans.id;
|
||||
|
||||
CREATE TABLE pm_checkpoints (
|
||||
sequence integer NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
purl_type smallint NOT NULL,
|
||||
chunk smallint NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE pm_licenses (
|
||||
id bigint NOT NULL,
|
||||
spdx_identifier text NOT NULL,
|
||||
|
|
@ -27045,6 +27053,9 @@ ALTER TABLE ONLY plan_limits
|
|||
ALTER TABLE ONLY plans
|
||||
ADD CONSTRAINT plans_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY pm_checkpoints
|
||||
ADD CONSTRAINT pm_checkpoints_pkey PRIMARY KEY (purl_type);
|
||||
|
||||
ALTER TABLE ONLY pm_licenses
|
||||
ADD CONSTRAINT pm_licenses_pkey PRIMARY KEY (id);
|
||||
|
||||
|
|
|
|||
|
|
@ -777,6 +777,7 @@ gantt
|
|||
Introduce auto-partitioning mechanisms :5_1, 2023-09-01, 120d
|
||||
New partitions are being created automatically :milestone, part3, 2023-12-01, 1min
|
||||
Partitioning is made available on self-managed :milestone, part4, 2024-01-01, 1min
|
||||
```
|
||||
|
||||
## Conclusions
|
||||
|
||||
|
|
|
|||
|
|
@ -352,6 +352,13 @@ scope.
|
|||
| GitLab Runner | `15.9` | Label Prometheus metrics with unique system ID. |
|
||||
| GitLab Runner | `15.8` | Prepare `register` command to fail if runner server-side configuration options are passed together with a new `glrt-` token. |
|
||||
|
||||
### Stage 2a - Prepare GitLab Runner Helm Chart and GitLab Runner Operator
|
||||
|
||||
| Component | Milestone | Issue | Changes |
|
||||
|------------------|----------:|-------|---------|
|
||||
|GitLab Runner Helm Chart| `%15.10` | Update the Runner Helm Chart to support registration with the authentication token. |
|
||||
|GitLab Runner Operator| `%15.10` | Update the Runner Operator to support registration with the authentication token. |
|
||||
|
||||
### Stage 3 - Database changes
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|
|
@ -368,14 +375,18 @@ scope.
|
|||
| GitLab Rails app | `%15.9` | Use runner token + `system_id` JSON parameters in `POST /jobs/request` request in the [heartbeat request](https://gitlab.com/gitlab-org/gitlab/blob/c73c96a8ffd515295842d72a3635a8ae873d688c/lib/api/ci/helpers/runner.rb#L14-20) to update the `ci_runner_machines` cache/table. |
|
||||
| GitLab Rails app | `%15.9` | [Feature flag] Enable runner creation workflow (`create_runner_workflow`). |
|
||||
| GitLab Rails app | `%15.9` | Implement `create_{instance|group|project}_runner` permissions. |
|
||||
| GitLab Rails app | `%15.10` | Rename `ci_runner_machines.machine_xid` column to `system_xid` to be consistent with `system_id` passed in APIs. |
|
||||
| GitLab Rails app | `%15.9` | Rename `ci_runner_machines.machine_xid` column to `system_xid` to be consistent with `system_id` passed in APIs. |
|
||||
| GitLab Rails app | `%15.10` | Drop `ci_runner_machines.machine_xid` column. |
|
||||
| GitLab Rails app | `%15.11` | Remove the ignore rule for `ci_runner_machines.machine_xid` column. |
|
||||
|
||||
### Stage 4 - New UI
|
||||
### Stage 4 - Create runners from the UI
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|------------------|----------:|---------|
|
||||
| GitLab Rails app | `%15.9` | Implement new GraphQL user-authenticated API to create a new runner. |
|
||||
| GitLab Rails app | `%15.9` | [Add prefix to newly generated runner authentication tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/383198). |
|
||||
| GitLab Rails app | `%15.10` | Return token and runner ID information from `/runners/verify` REST endpoint. |
|
||||
| GitLab Runner | `%15.10` | [Modify register command to allow new flow with glrt- prefixed authentication tokens](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/29613). |
|
||||
| GitLab Rails app | `%15.10` | Implement UI to create new runner. |
|
||||
| GitLab Rails app | `%15.10` | GraphQL changes to `CiRunner` type. |
|
||||
| GitLab Rails app | `%15.10` | UI changes to runner details view (listing of platform, architecture, IP address, etc.) (?) |
|
||||
|
|
|
|||
|
|
@ -113,22 +113,20 @@ NOTE:
|
|||
To protect, update, or unprotect an environment, you must have at least the
|
||||
Maintainer role.
|
||||
|
||||
### Optional settings
|
||||
|
||||
#### Allow self-approval
|
||||
### Allow self-approval **(PREMIUM)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/381418) in GitLab 15.8.
|
||||
|
||||
By default, a user who triggered a deployment pipeline can't self-approve the deployment jobs.
|
||||
You can allow the self-approval by the following settings:
|
||||
By default, the user who triggers a deployment pipeline can't also approve the deployment job.
|
||||
To allow self-approval of a deployment job:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > CI/CD**.
|
||||
1. Expand **Protected environments**.
|
||||
1. From the **Approval options**, check **Allow pipeline triggerer to approve deployment**.
|
||||
1. From the **Approval options**, select the **Allow pipeline triggerer to approve deployment** checkbox.
|
||||
|
||||
By enabling this, when a pipeline runs, deployment jobs will automatically be approved in the pipeline
|
||||
if the triggerer is allowed to approve, otherwise nothing happens.
|
||||
When a pipeline runs, deployment jobs are automatically approved in the pipeline if the user who
|
||||
triggered the deployment is allowed to approve.
|
||||
|
||||
## Approve or reject a deployment
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,15 @@ Use uppercase for **Alpha**. For example: **The XYZ feature is in Alpha.** or **
|
|||
You might also want to link to [this section](../../../policy/alpha-beta-support.md#alpha-features)
|
||||
in the handbook when writing about Alpha features.
|
||||
|
||||
## analytics
|
||||
|
||||
Use lowercase for **analytics** and its variations, like **contribution analytics** and **issue analytics**.
|
||||
However, if the UI has different capitalization, make the documentation match the UI.
|
||||
|
||||
For example:
|
||||
|
||||
- You can view merge request analytics for a project. They are displayed on the Merge Request Analytics dashboard.
|
||||
|
||||
## and/or
|
||||
|
||||
Instead of **and/or**, use **or** or rewrite the sentence to spell out both options.
|
||||
|
|
|
|||
|
|
@ -183,4 +183,4 @@ update your agent configuration file with the location of these projects.
|
|||
WARNING:
|
||||
The project with the agent's
|
||||
configuration file can be private or public. Other projects with Kubernetes manifests must be public. Support for private manifest projects is tracked
|
||||
in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/283885).
|
||||
in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7704).
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ After you set up your identity provider to work with GitLab, you must configure
|
|||

|
||||
|
||||
NOTE:
|
||||
The certificate [fingerprint algorithm](../../../integration/saml.md#configure-saml-on-your-idp) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#google-workspace-setup-notes)), use a secure signature algorithm.
|
||||
The certificate [fingerprint algorithm](../../../integration/saml.md#configure-saml-on-your-idp) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#set-up-google-workspace)), use a secure signature algorithm.
|
||||
|
||||
### Additional configuration information
|
||||
|
||||
|
|
@ -240,37 +240,38 @@ If using [Group Sync](#group-sync), customize the name of the group claim to mat
|
|||
|
||||
See our [example configuration page](example_saml_config.md#azure-active-directory).
|
||||
|
||||
### Google Workspace setup notes
|
||||
### Set up Google Workspace
|
||||
|
||||
Follow the Google Workspace documentation on
|
||||
[setting up SSO with Google as your identity provider](https://support.google.com/a/answer/6087519?hl=en)
|
||||
with the notes below for consideration.
|
||||
1. [Set up SSO with Google as your identity provider](https://support.google.com/a/answer/6087519?hl=en).
|
||||
The following GitLab settings correspond to the Google Workspace fields.
|
||||
|
||||
| GitLab setting | Google Workspace field |
|
||||
|:-------------------------------------|:-----------------------|
|
||||
| Identifier | Entity ID |
|
||||
| Assertion consumer service URL | ACS URL |
|
||||
| GitLab single sign-on URL | Start URL |
|
||||
| Identity provider single sign-on URL | SSO URL |
|
||||
| GitLab setting | Google Workspace field |
|
||||
|:-------------------------------------|:-----------------------|
|
||||
| Identifier | **Entity ID** |
|
||||
| Assertion consumer service URL | **ACS URL** |
|
||||
| GitLab single sign-on URL | **Start URL** |
|
||||
| Identity provider single sign-on URL | **SSO URL** |
|
||||
|
||||
NOTE:
|
||||
Google Workspace displays a SHA256 fingerprint. To retrieve the SHA1 fingerprint required by GitLab for [configuring SAML](#configure-gitlab), download the certificate and calculate
|
||||
the SHA1 certificate fingerprint using this sample command: `openssl x509 -noout -fingerprint -sha1 -inform pem -in "GoogleIDPCertificate-domain.com.pem"`.
|
||||
1. Google Workspace displays a SHA256 fingerprint. To retrieve the SHA1 fingerprint
|
||||
required by GitLab to [configure SAML](#configure-gitlab):
|
||||
1. Download the certificate.
|
||||
1. Run this command:
|
||||
|
||||
The recommended attributes and claims settings are:
|
||||
```shell
|
||||
openssl x509 -noout -fingerprint -sha1 -inform pem -in "GoogleIDPCertificate-domain.com.pem"
|
||||
```
|
||||
|
||||
- **Primary email** set to `email`.
|
||||
- **First name** set to `first_name`.
|
||||
- **Last name** set to `last_name`.
|
||||
1. Set these values:
|
||||
- For **Primary email**: `email`.
|
||||
- For **First name**: `first_name`.
|
||||
- For **Last name**: `last_name`.
|
||||
- For **Name ID format**: `EMAIL`.
|
||||
- For **NameID**: `Basic Information > Primary email`.
|
||||
|
||||
For NameID, the following settings are recommended:
|
||||
On the GitLab SAML SSO page, when you select **Verify SAML Configuration**, disregard
|
||||
the warning that recommends setting the **NameID** format to `persistent`.
|
||||
|
||||
- **Name ID format** is set to `EMAIL`.
|
||||
- **NameID** set to `Basic Information > Primary email`.
|
||||
|
||||
When selecting **Verify SAML Configuration** on the GitLab SAML SSO page, disregard the warning recommending setting the NameID format to "persistent".
|
||||
|
||||
See our [example configuration page](example_saml_config.md#google-workspace).
|
||||
For details, see the [example configuration page](example_saml_config.md#google-workspace).
|
||||
|
||||
### Okta setup notes
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 9.0 KiB |
|
|
@ -86,13 +86,28 @@ Visual Studio Code:
|
|||
- From the GitLab interface:
|
||||
1. Go to the project's overview page.
|
||||
1. Select **Clone**.
|
||||
1. Under either the **HTTPS** or **SSH** method, select **Clone with Visual Studio Code**.
|
||||
1. Under **Open in your IDE**, select **Visual Studio Code (SSH)** or **Visual Studio Code (HTTPS)**.
|
||||
1. Select a folder to clone the project into.
|
||||
|
||||
After Visual Studio Code clones your project, it opens the folder.
|
||||
- From Visual Studio Code, with the [extension](vscode.md) installed, use the
|
||||
extension's [`Git: Clone` command](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#clone-gitlab-projects).
|
||||
|
||||
### Clone and open in IntelliJ IDEA
|
||||
|
||||
All projects can be cloned into [IntelliJ IDEA](https://www.jetbrains.com/idea/)
|
||||
from the GitLab user interface.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- The [Jetbrains Toolbox App](https://www.jetbrains.com/toolbox-app/) must be also be installed.
|
||||
|
||||
To do this:
|
||||
|
||||
1. Go to the project's overview page.
|
||||
1. Select **Clone**.
|
||||
1. Under **Open in your IDE**, select **IntelliJ IDEA (SSH)** or **IntelliJ IDEA (HTTPS)**.
|
||||
|
||||
## Download the code in a repository
|
||||
|
||||
> Support for [including Git LFS blobs](../../../topics/git/lfs#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ called `my-project` under your username, the project is created at `https://gitl
|
|||
To view your personal projects:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects > View all projects**.
|
||||
1. In the **Your projects** tab, select **Personal**.
|
||||
1. In the **Yours** tab, select **Personal**.
|
||||
|
||||
## Delete a project
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def favicon
|
||||
'favicon_pending'
|
||||
'favicon_status_pending'
|
||||
end
|
||||
|
||||
def group
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace :tw do
|
|||
end
|
||||
|
||||
def directory
|
||||
@directory ||= File.dirname(path)
|
||||
@directory ||= "#{File.dirname(path)}/"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -123,16 +123,20 @@ namespace :tw do
|
|||
mappings << DocumentOwnerMapping.new(relative_file, writer) if document.has_a_valid_group?
|
||||
end
|
||||
|
||||
deduplicated_mappings = Set.new
|
||||
|
||||
mappings.each do |mapping|
|
||||
transformed_mappings = mappings.map do |mapping|
|
||||
if mapping.writer_owns_directory?(mappings)
|
||||
deduplicated_mappings.add("#{mapping.directory}/ #{mapping.writer}")
|
||||
DocumentOwnerMapping.new(mapping.directory, mapping.writer)
|
||||
else
|
||||
deduplicated_mappings.add("#{mapping.path} #{mapping.writer}")
|
||||
DocumentOwnerMapping.new(mapping.path, mapping.writer)
|
||||
end
|
||||
end
|
||||
|
||||
deduplicated_mappings = Set.new
|
||||
|
||||
transformed_mappings
|
||||
.reject { |mapping| transformed_mappings.any? { |m| m.path == mapping.directory && m.writer == mapping.writer } }
|
||||
.each { |mapping| deduplicated_mappings.add("#{mapping.path} #{mapping.writer}") }
|
||||
|
||||
new_docs_owners = deduplicated_mappings.sort.join("\n")
|
||||
|
||||
codeowners_path = Rails.root.join('.gitlab/CODEOWNERS')
|
||||
|
|
|
|||
|
|
@ -8735,6 +8735,9 @@ msgstr ""
|
|||
msgid "Choose your framework"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ci config already present"
|
||||
msgstr ""
|
||||
|
||||
msgid "CiCdAnalytics|Date range: %{range}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -11600,7 +11603,7 @@ msgstr ""
|
|||
msgid "Couldn't find event type filters where audit event type(s): %{missing_filters}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Country"
|
||||
msgid "Country / Region"
|
||||
msgstr ""
|
||||
|
||||
msgid "Counts"
|
||||
|
|
@ -31826,7 +31829,7 @@ msgstr ""
|
|||
msgid "Please select a Jira project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select a country"
|
||||
msgid "Please select a country / region"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select a group"
|
||||
|
|
@ -33083,6 +33086,9 @@ msgstr ""
|
|||
msgid "Project milestone"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project must have default branch"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project name"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -36891,6 +36897,9 @@ msgstr ""
|
|||
msgid "Runners|Never expires"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|New"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|New group runners can be registered"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -37004,6 +37013,9 @@ msgstr ""
|
|||
msgid "Runners|Runner %{name} was deleted"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner %{runnerName} failed to delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner Registration"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -37255,15 +37267,6 @@ msgstr ""
|
|||
msgid "Runners|shared"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runner|New"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runner|Owner"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runner|Runner %{runnerName} failed to delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Running"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -24,4 +24,26 @@ RSpec.describe 'User views issue designs', :js, feature_category: :design_manage
|
|||
|
||||
expect(page).to have_selector('.js-design-image')
|
||||
end
|
||||
|
||||
context 'when svg file is loaded in design detail' do
|
||||
let_it_be(:file) { Rails.root.join('spec/fixtures/svg_without_attr.svg') }
|
||||
let_it_be(:design) { create(:design, :with_file, filename: 'svg_without_attr.svg', file: file, issue: issue) }
|
||||
|
||||
before do
|
||||
visit designs_project_issue_path(
|
||||
project,
|
||||
issue,
|
||||
{ vueroute: design.filename }
|
||||
)
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'check if svg is loading' do
|
||||
expect(page).to have_selector(
|
||||
".js-design-image > img[alt='svg_without_attr.svg']",
|
||||
count: 1,
|
||||
visible: :hidden
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg viewBox="0 0 50 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generator: Sketch 3.3.2 (12043) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Slice 1</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<script>alert('FAIL')</script>
|
||||
<defs></defs>
|
||||
<path d="m49.014 19-.067-.18-6.784-17.696a1.792 1.792 0 0 0-3.389.182l-4.579 14.02H15.651l-4.58-14.02a1.795 1.795 0 0 0-3.388-.182l-6.78 17.7-.071.175A12.595 12.595 0 0 0 5.01 33.556l.026.02.057.044 10.32 7.734 5.12 3.87 3.11 2.351a2.102 2.102 0 0 0 2.535 0l3.11-2.352 5.12-3.869 10.394-7.779.029-.022a12.595 12.595 0 0 0 4.182-14.554Z"
|
||||
fill="#E24329"/>
|
||||
<path d="m49.014 19-.067-.18a22.88 22.88 0 0 0-9.12 4.103L24.931 34.187l9.485 7.167 10.393-7.779.03-.022a12.595 12.595 0 0 0 4.175-14.554Z"
|
||||
fill="#FC6D26"/>
|
||||
<path d="m15.414 41.354 5.12 3.87 3.11 2.351a2.102 2.102 0 0 0 2.535 0l3.11-2.352 5.12-3.869-9.484-7.167-9.51 7.167Z"
|
||||
fill="#FCA326"/>
|
||||
<path d="M10.019 22.923a22.86 22.86 0 0 0-9.117-4.1L.832 19A12.595 12.595 0 0 0 5.01 33.556l.026.02.057.044 10.32 7.734 9.491-7.167L10.02 22.923Z"
|
||||
fill="#FC6D26"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -1,5 +1,19 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Design management large image component renders SVG with proper height and width 1`] = `
|
||||
<div
|
||||
class="gl-mx-auto gl-my-auto js-design-image"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<img
|
||||
alt="test"
|
||||
class="mh-100 img-fluid"
|
||||
src="mockImage.svg"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Design management large image component renders image 1`] = `
|
||||
<div
|
||||
class="gl-mx-auto gl-my-auto js-design-image"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,16 @@ describe('Design management large image component', () => {
|
|||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders SVG with proper height and width', () => {
|
||||
createComponent({
|
||||
isLoading: false,
|
||||
image: 'mockImage.svg',
|
||||
name: 'test',
|
||||
});
|
||||
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('sets correct classes and styles if imageStyle is set', async () => {
|
||||
createComponent(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@ exports[`Design management list item component with notes renders item with mult
|
|||
>
|
||||
<!---->
|
||||
|
||||
<gl-intersection-observer-stub>
|
||||
<gl-intersection-observer-stub
|
||||
class="gl-flex-grow-1"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<img
|
||||
alt="test"
|
||||
class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full design-img"
|
||||
class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full gl-w-auto design-img"
|
||||
data-qa-filename="test"
|
||||
data-qa-selector="design_image"
|
||||
data-testid="design-img-1"
|
||||
|
|
@ -98,12 +100,14 @@ exports[`Design management list item component with notes renders item with sing
|
|||
>
|
||||
<!---->
|
||||
|
||||
<gl-intersection-observer-stub>
|
||||
<gl-intersection-observer-stub
|
||||
class="gl-flex-grow-1"
|
||||
>
|
||||
<!---->
|
||||
|
||||
<img
|
||||
alt="test"
|
||||
class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full design-img"
|
||||
class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full gl-w-auto design-img"
|
||||
data-qa-filename="test"
|
||||
data-qa-selector="design_image"
|
||||
data-testid="design-img-1"
|
||||
|
|
|
|||
|
|
@ -767,17 +767,10 @@ describe('WorkItemDetail component', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('does not render created/updated by default', async () => {
|
||||
it('renders created/updated', async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findCreatedUpdated().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders created/updated when the work_items_mvc flag is on', async () => {
|
||||
createComponent({ workItemsMvcEnabled: true });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findCreatedUpdated().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe 'countries', feature_category: :onboarding do
|
||||
it 'configures locals to EN' do
|
||||
expect(ISO3166.configuration.locales).to eq([:en])
|
||||
end
|
||||
|
||||
it 'initialises Ukraine with custom country name' do
|
||||
expect(ISO3166::Country['UA'].data["name"]).to be('Ukraine (except the Crimea, Donetsk, and Luhansk regions)')
|
||||
end
|
||||
|
||||
it 'initialises Taiwan with custom country name' do
|
||||
expect(ISO3166::Country['TW'].data["name"]).to be('Taiwan')
|
||||
end
|
||||
end
|
||||
|
|
@ -131,7 +131,7 @@ RSpec.describe Gitlab::Ci::Status::Bridge::Factory, feature_category: :continuou
|
|||
expect(status.text).to eq 'waiting'
|
||||
expect(status.group).to eq 'waiting-for-resource'
|
||||
expect(status.icon).to eq 'status_pending'
|
||||
expect(status.favicon).to eq 'favicon_pending'
|
||||
expect(status.favicon).to eq 'favicon_status_pending'
|
||||
expect(status.illustration).to include(:image, :size, :title)
|
||||
expect(status).not_to have_details
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ RSpec.describe Gitlab::Ci::Status::WaitingForResource do
|
|||
end
|
||||
|
||||
describe '#favicon' do
|
||||
it { expect(subject.favicon).to eq 'favicon_pending' }
|
||||
it { expect(subject.favicon).to eq 'favicon_status_pending' }
|
||||
end
|
||||
|
||||
describe '#group' do
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache, feature_category: :r
|
|||
let(:fixture_dir_glob) { Dir.glob(File.join(Rails.root, 'spec', 'fixtures', 'whats_new', '*.yml')).grep(/\d*_(\d*_\d*)\.yml$/) }
|
||||
|
||||
before do
|
||||
allow(Dir).to receive(:glob).with(Rails.root.join('data', 'whats_new', '*.yml')).and_return(fixture_dir_glob)
|
||||
allow(Dir).to receive(:glob).and_call_original
|
||||
allow(Dir).to receive(:glob).with(described_class.whats_new_path).and_return(fixture_dir_glob)
|
||||
Gitlab::CurrentSettings.update!(whats_new_variant: ApplicationSetting.whats_new_variants[:all_tiers])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::ArchiveTraceService, '#execute' do
|
||||
RSpec.describe Ci::ArchiveTraceService, '#execute', feature_category: :continuous_integration do
|
||||
subject { described_class.new.execute(job, worker_name: Ci::ArchiveTraceWorker.name) }
|
||||
|
||||
context 'when job is finished' do
|
||||
|
|
@ -192,4 +192,69 @@ RSpec.describe Ci::ArchiveTraceService, '#execute' do
|
|||
expect(job.trace_metadata.archival_attempts).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#batch_execute' do
|
||||
subject { described_class.new.batch_execute(worker_name: Ci::ArchiveTraceWorker.name) }
|
||||
|
||||
let_it_be_with_reload(:job) { create(:ci_build, :success, :trace_live, finished_at: 1.day.ago) }
|
||||
let_it_be_with_reload(:job2) { create(:ci_build, :success, :trace_live, finished_at: 1.day.ago) }
|
||||
|
||||
it 'archives multiple traces' do
|
||||
expect { subject }.not_to raise_error
|
||||
|
||||
expect(job.reload.job_artifacts_trace).to be_exist
|
||||
expect(job2.reload.job_artifacts_trace).to be_exist
|
||||
end
|
||||
|
||||
it 'processes traces independently' do
|
||||
allow_next_instance_of(Gitlab::Ci::Trace) do |instance|
|
||||
orig_method = instance.method(:archive!)
|
||||
allow(instance).to receive(:archive!) do
|
||||
raise('Unexpected error') if instance.job.id == job.id
|
||||
|
||||
orig_method.call
|
||||
end
|
||||
end
|
||||
|
||||
expect { subject }.not_to raise_error
|
||||
|
||||
expect(job.reload.job_artifacts_trace).to be_nil
|
||||
expect(job2.reload.job_artifacts_trace).to be_exist
|
||||
end
|
||||
|
||||
context 'when timeout is reached' do
|
||||
before do
|
||||
stub_const("#{described_class}::LOOP_TIMEOUT", 0.seconds)
|
||||
end
|
||||
|
||||
it 'stops executing traces' do
|
||||
expect { subject }.not_to raise_error
|
||||
|
||||
expect(job.reload.job_artifacts_trace).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when loop limit is reached' do
|
||||
before do
|
||||
stub_const("#{described_class}::LOOP_LIMIT", -1)
|
||||
end
|
||||
|
||||
it 'skips archiving' do
|
||||
expect(job.trace).not_to receive(:archive!)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'stops executing traces' do
|
||||
expect(Sidekiq.logger).to receive(:warn).with(
|
||||
class: Ci::ArchiveTraceWorker.name,
|
||||
message: "Loop limit reached.",
|
||||
job_id: job.id)
|
||||
|
||||
expect { subject }.not_to raise_error
|
||||
|
||||
expect(job.reload.job_artifacts_trace).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::ArchiveTracesCronWorker do
|
||||
RSpec.describe Ci::ArchiveTracesCronWorker, feature_category: :continuous_integration do
|
||||
subject { described_class.new.perform }
|
||||
|
||||
let(:finished_at) { 1.day.ago }
|
||||
|
|
@ -34,14 +34,28 @@ RSpec.describe Ci::ArchiveTracesCronWorker do
|
|||
|
||||
it_behaves_like 'archives trace'
|
||||
|
||||
it 'executes service' do
|
||||
it 'batch_execute service' do
|
||||
expect_next_instance_of(Ci::ArchiveTraceService) do |instance|
|
||||
expect(instance).to receive(:execute).with(build, anything)
|
||||
expect(instance).to receive(:batch_execute).with(worker_name: "Ci::ArchiveTracesCronWorker")
|
||||
end
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
context "with FF deduplicate_archive_traces_cron_worker false" do
|
||||
before do
|
||||
stub_feature_flags(deduplicate_archive_traces_cron_worker: false)
|
||||
end
|
||||
|
||||
it 'calls execute service' do
|
||||
expect_next_instance_of(Ci::ArchiveTraceService) do |instance|
|
||||
expect(instance).to receive(:execute).with(build, worker_name: "Ci::ArchiveTracesCronWorker")
|
||||
end
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the job finished recently' do
|
||||
let(:finished_at) { 1.hour.ago }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue