Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
44b16c9776
commit
ca1a45a955
|
|
@ -1 +1 @@
|
|||
967661bb7027d5b38e01bd26f3ed3887d078410c
|
||||
c8d9c76d7f3ab259d0b743b2c79a678e88832a85
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
ed8e69891a82913e19430e094c192833ea5cb066
|
||||
40c7b25469a48f2eb811a9f797d412a2b9923433
|
||||
|
|
|
|||
|
|
@ -5,8 +5,12 @@ query flowMetricsCommitsQuery(
|
|||
$endDate: Time!
|
||||
$labelNames: [String!]
|
||||
) {
|
||||
flowMetricsCommits(fullPath: $fullPath, from: $startDate, to: $endDate, labelNames: $labelNames)
|
||||
@client {
|
||||
flowMetricsCommits(
|
||||
fullPath: $fullPath
|
||||
startDate: $startDate
|
||||
endDate: $endDate
|
||||
labelNames: $labelNames
|
||||
) @client {
|
||||
value
|
||||
identifier
|
||||
links
|
||||
|
|
|
|||
|
|
@ -5,8 +5,13 @@ const NO_COMMIT_DATA_ERROR = 'No commit data returned';
|
|||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
flowMetricsCommits(_, { fullPath, ...params }) {
|
||||
return getValueStreamSummaryMetrics(fullPath, params)
|
||||
flowMetricsCommits(_, { fullPath, startDate, endDate, labelNames, ...params }) {
|
||||
return getValueStreamSummaryMetrics(fullPath, {
|
||||
...params,
|
||||
created_after: startDate,
|
||||
created_before: endDate,
|
||||
label_names: labelNames,
|
||||
})
|
||||
.then(({ data = [] }) => {
|
||||
const commits = data.filter((metric) => metric.identifier === FLOW_METRICS.COMMITS);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ type FlowMetricsCommits {
|
|||
extend type Query {
|
||||
flowMetricsCommits(
|
||||
fullPath: ID!
|
||||
from: Time!
|
||||
to: Time!
|
||||
startDate: Time!
|
||||
endDate: Time!
|
||||
labelNames: [String!]
|
||||
): FlowMetricsCommits
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import WikiHeader from './components/wiki_header.vue';
|
|||
import WikiContent from './components/wiki_content.vue';
|
||||
import WikiEditForm from './components/wiki_form.vue';
|
||||
import WikiAlert from './components/wiki_alert.vue';
|
||||
import eventHub, { EVENT_EDIT_WIKI_DONE, EVENT_EDIT_WIKI_START } from './event_hub';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -37,8 +38,10 @@ export default {
|
|||
|
||||
if (this.isEditing) {
|
||||
url.searchParams.set('edit', 'true');
|
||||
eventHub.$emit(EVENT_EDIT_WIKI_START);
|
||||
} else {
|
||||
url.searchParams.delete('edit');
|
||||
eventHub.$emit(EVENT_EDIT_WIKI_DONE);
|
||||
}
|
||||
|
||||
window.history.pushState({}, '', url);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
import createEventHub from '~/helpers/event_hub_factory';
|
||||
|
||||
export default createEventHub();
|
||||
|
||||
export const EVENT_EDIT_WIKI_START = Symbol('eventEditWikiStart');
|
||||
export const EVENT_EDIT_WIKI_DONE = Symbol('eventEditWikiDone');
|
||||
|
|
@ -5,6 +5,7 @@ import wikiPageQuery from '~/wikis/graphql/wiki_page.query.graphql';
|
|||
import SkeletonNote from '~/vue_shared/components/notes/skeleton_note.vue';
|
||||
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||
import { TYPENAME_PROJECT, TYPENAME_GROUP } from '~/graphql_shared/constants';
|
||||
import eventHub, { EVENT_EDIT_WIKI_DONE, EVENT_EDIT_WIKI_START } from '../../event_hub';
|
||||
import OrderedLayout from './ordered_layout.vue';
|
||||
import PlaceholderNote from './placeholder_note.vue';
|
||||
import WikiNotesActivityHeader from './wiki_notes_activity_header.vue';
|
||||
|
|
@ -75,6 +76,7 @@ export default {
|
|||
id: index,
|
||||
isSkeletonNote: true,
|
||||
})),
|
||||
isEditingPage: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -82,6 +84,15 @@ export default {
|
|||
return this.$apollo.queries.wikiPage;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
eventHub.$on(EVENT_EDIT_WIKI_START, () => {
|
||||
this.isEditingPage = true;
|
||||
});
|
||||
|
||||
eventHub.$on(EVENT_EDIT_WIKI_DONE, () => {
|
||||
this.isEditingPage = false;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
setPlaceHolderNote(note) {
|
||||
this.placeholderNote = note;
|
||||
|
|
@ -109,7 +120,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="!isEditingPage">
|
||||
<wiki-notes-activity-header />
|
||||
<ordered-layout :slot-keys="slotKeys">
|
||||
<template #form>
|
||||
|
|
|
|||
|
|
@ -13,15 +13,17 @@ module IssuableCollectionsAction
|
|||
|
||||
# rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
def issues
|
||||
@issues = issuables_collection
|
||||
.non_archived
|
||||
.page(params[:page])
|
||||
|
||||
@issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @issues).data
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.atom { render layout: 'xml' }
|
||||
format.atom do
|
||||
@issues = issuables_collection
|
||||
.non_archived
|
||||
.page(params[:page])
|
||||
|
||||
@issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @issues).data
|
||||
|
||||
render layout: 'xml'
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable Gitlab/ModuleWithInstanceVariables
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ class WikiPage
|
|||
set_attributes if persisted?
|
||||
end
|
||||
|
||||
def meta
|
||||
WikiPage::Meta.find_by_canonical_slug(slug, container)
|
||||
end
|
||||
|
||||
# The escaped URL path of this page.
|
||||
def slug
|
||||
attributes[:slug].presence || ::Wiki.preview_slug(title, format)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ class WikiPage
|
|||
joins(:slugs).where(slug_table_name => { canonical: true, slug: slug })
|
||||
end
|
||||
|
||||
delegate :wiki, to: :container
|
||||
|
||||
class << self
|
||||
# Return the (updated) WikiPage::Meta record for a given wiki page
|
||||
#
|
||||
|
|
@ -100,6 +102,10 @@ class WikiPage
|
|||
end
|
||||
end
|
||||
|
||||
def wiki_page
|
||||
wiki.find_page(canonical_slug, load_content: true)
|
||||
end
|
||||
|
||||
def container
|
||||
project || namespace
|
||||
end
|
||||
|
|
|
|||
|
|
@ -141,14 +141,12 @@ You can impersonate a user in the following ways:
|
|||
1. On the left sidebar, at the bottom, select **Admin**.
|
||||
1. On the left sidebar, select **Overview > Users**.
|
||||
1. From the list of users, select a user.
|
||||
1. Select **Impersonate**.
|
||||
1. On the top right, select **Impersonate**.
|
||||
- With the API, using [impersonation tokens](../api/rest/authentication.md#impersonation-tokens).
|
||||
|
||||
All impersonation activities are [captured with audit events](audit_event_reports.md#user-impersonation).
|
||||
By default, impersonation is enabled. GitLab can be configured to [disable impersonation](../api/rest/authentication.md#disable-impersonation).
|
||||
|
||||

|
||||
|
||||
### User identities
|
||||
|
||||
> - The ability to see a user's SCIM identity was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294608) in GitLab 15.3.
|
||||
|
|
@ -163,7 +161,7 @@ When using authentication providers, administrators can see the identities for a
|
|||
This list shows the user's identities, including SCIM identities. Administrators can use this information to troubleshoot SCIM-related issues and confirm
|
||||
the identities being used for an account.
|
||||
|
||||
### User Permission Export
|
||||
### User permission export
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
|
|
@ -172,7 +170,7 @@ DETAILS:
|
|||
An administrator can export user permissions for all users in the GitLab instance from the **Admin** area's Users page.
|
||||
The export lists direct membership the users have in groups and projects.
|
||||
|
||||
The following data is included in the export:
|
||||
The export process exports the first 100,000 users, and includes this data:
|
||||
|
||||
- Username
|
||||
- Email
|
||||
|
|
@ -181,9 +179,11 @@ The following data is included in the export:
|
|||
- Access level ([Project](../user/permissions.md#project-members-permissions) and [Group](../user/permissions.md#group-members-permissions))
|
||||
- Date of last activity. For a list of activities that populate this column, see the [Users API documentation](../api/users.md#list-a-users-activity).
|
||||
|
||||
Only the first 100,000 user accounts are exported.
|
||||
To do this:
|
||||
|
||||

|
||||
1. On the left sidebar, at the bottom, select **Admin**.
|
||||
1. Select **Overview > Users**.
|
||||
1. On the top right, select **Export permissions as CSV** (**{export}**).
|
||||
|
||||
### Users statistics
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@ DETAILS:
|
|||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** Self-managed
|
||||
|
||||
> - Target roles [introduced](https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/461) in GitLab 14.8 [with a flag](../administration/feature_flags.md) named `role_targeted_broadcast_messages`. Disabled by default.
|
||||
> - Theme [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83251) and background color removed in GitLab 14.10.
|
||||
|
||||
GitLab can display two types of broadcast messages to users of a GitLab instance:
|
||||
|
||||
- Banners
|
||||
|
|
@ -22,25 +19,37 @@ Broadcast messages can be managed using the [broadcast messages API](../api/broa
|
|||
|
||||
## Banners
|
||||
|
||||
Banners are shown on the top of a page and optionally in the command line as a Git remote response.
|
||||
Banners are shown on the top of a page, and optionally in the command line as a Git remote response.
|
||||
|
||||

|
||||

|
||||
|
||||
```shell
|
||||
$ git push
|
||||
...
|
||||
remote:
|
||||
remote: **Welcome** to GitLab :wave:
|
||||
remote: **Welcome to GitLab** :wave:
|
||||
remote:
|
||||
...
|
||||
```
|
||||
|
||||
If more than one banner is active at one time, they are displayed at the top of the page in order of creation. In the command line, only the latest banner is shown.
|
||||
If more than one banner is active at one time, they are displayed at the top of the page in order of
|
||||
creation. In the command line, only the latest banner is shown.
|
||||
|
||||
## Notifications
|
||||
|
||||
Notifications are shown on the bottom right of a page and can contain placeholders. A placeholder is replaced with an attribute of the active user. Placeholders must be surrounded by curly braces, for example `{{name}}`.
|
||||
The available placeholders are:
|
||||
GitLab shows notifications on the bottom right of a page. They can contain placeholders,
|
||||
which are replaced with the attributes of the current user:
|
||||
|
||||

|
||||
|
||||
```markdown
|
||||
{{name}}, would you like to give us feedback?
|
||||
<a href="example.com">Take our survey!</a>
|
||||
```
|
||||
|
||||
If more than one notification is active at one time, only the newest is shown.
|
||||
|
||||
Notifications support these placeholders:
|
||||
|
||||
- `{{email}}`
|
||||
- `{{name}}`
|
||||
|
|
@ -48,11 +57,7 @@ The available placeholders are:
|
|||
- `{{username}}`
|
||||
- `{{instance_id}}`
|
||||
|
||||
If the user is not signed in, user related values are empty.
|
||||
|
||||

|
||||
|
||||
If more than one notification is active at one time, only the newest is shown.
|
||||
If the user is not signed in, user-related values are empty.
|
||||
|
||||
## Add a broadcast message
|
||||
|
||||
|
|
@ -61,25 +66,34 @@ To display messages to users on your GitLab instance, add a broadcast message.
|
|||
To add a broadcast message:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin**.
|
||||
1. Select **Messages**.
|
||||
1. Select **Add new message**.
|
||||
1. Add the text for the message to the **Message** field. You can style a message's content using Markdown, emoji, and the `a` and `br` HTML tags.
|
||||
The `br` tag inserts a line break. The `a` HTML tag accepts `class` and `style` attributes with the following CSS properties:
|
||||
- `color`
|
||||
- `border`
|
||||
- `background`
|
||||
- `padding`
|
||||
- `margin`
|
||||
- `text-decoration`
|
||||
1. On the left sidebar, select **Messages**.
|
||||
1. On the right, select **Add new message**.
|
||||
1. Add your **Message** text:
|
||||
- Message contents can include Markdown, emoji, and the `a` and `br` HTML tags.
|
||||
- The `br` tag inserts a line break.
|
||||
- The `a` HTML tag accepts `class` and `style` attributes with the following CSS properties:
|
||||
- `color`
|
||||
- `border`
|
||||
- `background`
|
||||
- `padding`
|
||||
- `margin`
|
||||
- `text-decoration`
|
||||
1. For **Type**, select `banner` or `notification`.
|
||||
1. Select a **Theme**. The default theme is `indigo`.
|
||||
1. Select the **Dismissable** checkbox to enable users to dismiss the broadcast message.
|
||||
1. Optional. Clear the **Git remote responses** checkbox to prevent broadcast messages from being displayed in the command line as Git remote responses.
|
||||
1. Optional. Select **Target roles** to only show the broadcast message to users with the selected roles. The message displays on group, subgroup, and project pages, and does not display in Git remote responses.
|
||||
1. If required, add a **Target Path** to only show the broadcast message on URLs matching that path. You can use the wildcard character `*` to match multiple URLs, for example `mygroup/myproject*`.
|
||||
1. To enable users to dismiss the broadcast message, select **Dismissable**.
|
||||
1. Optional. To skip showing the broadcast message in the command line as a Git remote response, select clear the **Git remote responses**.
|
||||
1. Optional. To show the message only to a subset of users, select **Target broadcast message**:
|
||||
- Show to all users on all pages.
|
||||
- Show to all users on specific matching pages.
|
||||
- Show only to users who have specific roles on groups or project pages. This setting displays your message on
|
||||
group, subgroup, and project pages, but does not display in Git remote responses.
|
||||
1. If required, select the **Target roles** to show the broadcast message to.
|
||||
1. If required, add a **Target Path** to only show the broadcast message on URLs matching that path.
|
||||
Use the wildcard character `*` to match multiple URLs, like `mygroup/myproject*`.
|
||||
1. Select a date and time (UTC) for the message to start and end.
|
||||
1. Select **Add broadcast message**.
|
||||
|
||||
When a broadcast message expires, it no longer displays in the user interface but is still listed in the
|
||||
When a broadcast message expires, it no longer displays in the user interface, but is still listed in the
|
||||
list of broadcast messages.
|
||||
|
||||
## Edit a broadcast message
|
||||
|
|
@ -107,15 +121,3 @@ To delete a broadcast message:
|
|||
1. From the list of broadcast messages, select the delete button for the message.
|
||||
|
||||
When a broadcast message is deleted, it's removed from the list of broadcast messages.
|
||||
|
||||
<!-- ## Troubleshooting
|
||||
|
||||
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
|
||||
one might have when setting this up, or when something is changed, or on upgrading, it's
|
||||
important to describe those, too. Think of things that may go wrong and include them here.
|
||||
This is important to minimize requests for support, and to avoid doc comments with
|
||||
questions that you know someone might ask.
|
||||
|
||||
Each scenario can be a third-level heading, for example `### Getting error message X`.
|
||||
If you have none to add when creating a doc, leave this section in place
|
||||
but commented out to help encourage others to add to it in the future. -->
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
|
|
@ -1377,6 +1377,7 @@ job:
|
|||
them fail with a [`could not retrieve the needed artifacts` error](../jobs/job_artifacts_troubleshooting.md#error-message-this-job-could-not-start-because-it-could-not-retrieve-the-needed-artifacts).
|
||||
Set the expiry time to be longer, or use [`dependencies`](#dependencies) in later jobs
|
||||
to ensure they don't try to fetch expired artifacts.
|
||||
- `artifacts:expire_in` doesn't affect GitLab Pages deployments. To configure Pages deployments' expiry, use [`pages:pages.expire_in`](#pagespagesexpire_in).
|
||||
|
||||
#### `artifacts:expose_as`
|
||||
|
||||
|
|
@ -3534,8 +3535,9 @@ Use `expire_in` to specify how long a deployment should be available before
|
|||
it expires. After the deployment is expired, it's deactivated by a cron
|
||||
job running every 10 minutes.
|
||||
|
||||
Extra deployments expire by default. To prevent them from expiring, set the
|
||||
value to `never`.
|
||||
By default, [parallel deployments](../../user/project/pages/index.md#parallel-deployments) expire
|
||||
automatically after 24 hours.
|
||||
To disable this behavior, set the value to `never`.
|
||||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a `pages` job.
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ Amazon Q can analyze Java 8 or 11 code and determine the necessary Java changes
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- You must [have a runner configured for your project](https://docs.gitlab.com/runner/register/).
|
||||
- You must [have a runner and a CI/CD pipeline configured for your project](../../ci/index.md).
|
||||
|
||||
To upgrade Java:
|
||||
|
||||
|
|
@ -69,7 +69,10 @@ To upgrade Java:
|
|||
1. Save the issue. Then, in a comment, type `/q transform`.
|
||||
1. Select **Comment**.
|
||||
|
||||
A merge request with the code changes needed for the upgrade is created.
|
||||
A CI/CD job starts. A comment is displayed with the details and a link to the job.
|
||||
|
||||
- If the job is successful, a merge request with the code changes needed for the upgrade is created.
|
||||
- If the job fails, a comment provides details about potential fixes.
|
||||
|
||||
## Use GitLab Duo with Amazon Q in a merge request
|
||||
|
||||
|
|
|
|||
|
|
@ -33,11 +33,13 @@ To set up GitLab Duo with Amazon Q, you must:
|
|||
- [Create an identity provider](#create-an-iam-identity-provider)
|
||||
- [Create an IAM role](#create-an-iam-role)
|
||||
- [Enter the ARN in GitLab and enable Amazon Q](#enter-the-arn-in-gitlab-and-enable-amazon-q)
|
||||
- [Add the Amazon Q user to your project](#add-the-amazon-q-user-to-your-project)
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- You must have a self-managed GitLab instance:
|
||||
- With an HTTPS URL that can be accessed by Amazon Q.
|
||||
- With an HTTPS URL that can be accessed by Amazon Q (the SSL certificate must not be self-signed).
|
||||
For more details about SSL, see [Configure SSL for a Linux package installation](https://docs.gitlab.com/omnibus/settings/ssl/).
|
||||
- With an Ultimate subscription that is synchronized with GitLab. (No trial access.)
|
||||
- With the `amazon_q_integration` [feature flag enabled](../../administration/feature_flags.md).
|
||||
- GitLab Duo features [must be turned on](../gitlab_duo/turn_on_off.md#turn-on-beta-and-experimental-features).
|
||||
|
|
@ -70,6 +72,9 @@ Now, create an AWS identity provider:
|
|||
Next, you must create an IAM role that trusts the IAM identity provider and can
|
||||
access Amazon Q.
|
||||
|
||||
NOTE:
|
||||
After you set up the IAM role, you cannot change the AWS account that's associated with the role.
|
||||
|
||||
1. In the AWS IAM console, select **Access Management > Roles > Create role**.
|
||||
1. Select **Web identity**.
|
||||
1. For **Web identity**, select the provider URL you entered earlier.
|
||||
|
|
@ -165,7 +170,24 @@ Prerequisites:
|
|||
1. Select **Save changes**.
|
||||
|
||||
When you save, an API should contact the AI Gateway to create an OAuth application on Amazon Q.
|
||||
To confirm that it was successful, check the logs for a `204`.
|
||||
|
||||
To confirm that it was successful:
|
||||
|
||||
- In the Amazon CloudWatch console log, check for a `204` status code. For more information, see
|
||||
[What is Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html)?
|
||||
- In GitLab, a notification that says `Amazon Q settings have been saved` is displayed.
|
||||
- In GitLab, on the left sidebar, select **Applications**. The Amazon Q OAuth application is displayed.
|
||||
|
||||
## Add the Amazon Q user to your project
|
||||
|
||||
Now add the Amazon Q service account user as a member of your project.
|
||||
|
||||
1. In GitLab, on the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Manage > Members**.
|
||||
1. In the upper-right corner, select **Invite members**.
|
||||
1. For **Username, name, or email address**, select **Amazon Q Service**.
|
||||
1. For **Select a role**, select **Developer**.
|
||||
1. Select **Invite**.
|
||||
|
||||
### Configure the AI gateway
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ DETAILS:
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/162826) in GitLab 17.4.
|
||||
|
||||
You can configure your Pages deployments to be automatically deleted after
|
||||
a period of time has passed by specifying a duration at `pages.expire_in`:
|
||||
a period of time has passed by specifying a duration at [`pages.expire_in`](../../../ci/yaml/index.md#pagespagesexpire_in):
|
||||
|
||||
```yaml
|
||||
deploy-pages:
|
||||
|
|
@ -202,15 +202,16 @@ deploy-pages:
|
|||
```
|
||||
|
||||
By default, [parallel deployments](#parallel-deployments) expire
|
||||
automatically after 24 hours. To disable this behavior, set `pages.expire_in` to `never`.
|
||||
automatically after 24 hours.
|
||||
To disable this behavior, set `pages.expire_in` to `never`.
|
||||
|
||||
Expired deployments are stopped by a cron job that runs every 10 minutes.
|
||||
Stopped deployments are subsequently deleted by another cron job that also
|
||||
runs every 10 minutes. To recover it, follow the steps described in
|
||||
[Recover a stopped deployment](#recover-a-stopped-deployment).
|
||||
|
||||
A stopped or deleted deployment is no longer available on the web. Users will
|
||||
see a 404 Not found error page at its URL, until another deployment is created
|
||||
A stopped or deleted deployment is no longer available on the web.
|
||||
Users see a `404 Not found` error page at its URL, until another deployment is created
|
||||
with the same URL configuration.
|
||||
|
||||
The previous YAML example uses [user-defined job names](#user-defined-job-names).
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ module Gitlab
|
|||
UnexpectedIdentityError = Class.new(IdentityError)
|
||||
TooManyIdentitiesLinkedError = Class.new(IdentityError)
|
||||
MissingCompositeIdentityError = Class.new(::Gitlab::Access::AccessDeniedError)
|
||||
MissingServiceAccountError = Class.new(::Gitlab::Access::AccessDeniedError)
|
||||
|
||||
# TODO: why is this called 3 times in doorkeeper_access_spec.rb specs?
|
||||
def self.link_from_oauth_token(oauth_token)
|
||||
|
|
@ -41,6 +42,14 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def self.link_from_web_request(service_account:, scoped_user:)
|
||||
raise MissingServiceAccountError, 'service account is required' unless service_account
|
||||
|
||||
fabricate(service_account).tap do |identity|
|
||||
identity.link!(scoped_user) if identity&.composite?
|
||||
end
|
||||
end
|
||||
|
||||
def self.sidekiq_restore!(job)
|
||||
ids = Array(job[COMPOSITE_IDENTITY_SIDEKIQ_ARG])
|
||||
|
||||
|
|
|
|||
|
|
@ -50166,6 +50166,15 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|All types"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Allow except on these packages"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Allowed licenses"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Allowlist details"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -50280,6 +50289,15 @@ msgstr ""
|
|||
msgid "SecurityOrchestration|Delete policy: %{policy}"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Denied licenses"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Deny except on these packages"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Denylist details"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration|Description"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -213,7 +213,6 @@ spec/frontend/lib/utils/breadcrumbs_spec.js
|
|||
spec/frontend/lib/utils/confirm_via_gl_modal/confirm_action_spec.js
|
||||
spec/frontend/members/components/app_spec.js
|
||||
spec/frontend/members/components/modals/leave_modal_spec.js
|
||||
spec/frontend/members/components/table/drawer/role_details_drawer_spec.js
|
||||
spec/frontend/members/components/table/max_role_spec.js
|
||||
spec/frontend/members/components/table/members_pagination_spec.js
|
||||
spec/frontend/members/components/table/members_table_spec.js
|
||||
|
|
@ -288,7 +287,6 @@ spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
|
|||
spec/frontend/sidebar/components/confidential/confidentiality_dropdown_spec.js
|
||||
spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
|
||||
spec/frontend/sidebar/components/incidents/escalation_status_spec.js
|
||||
spec/frontend/sidebar/components/incidents/sidebar_escalation_status_spec.js
|
||||
spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_labels_view_spec.js
|
||||
spec/frontend/sidebar/components/labels/labels_select_vue/labels_select_root_spec.js
|
||||
spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_spec.js
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ RSpec.describe DashboardController, feature_category: :code_review_workflow do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
describe 'GET issues' do
|
||||
it_behaves_like 'issuables list meta-data', :issue, :issues
|
||||
it_behaves_like 'issuables requiring filter', :issues
|
||||
describe 'GET issues.atom' do
|
||||
it_behaves_like 'issuables list meta-data', :issue, :issues, format: :atom
|
||||
it_behaves_like 'issuables requiring filter', :issues, format: :atom
|
||||
|
||||
it 'includes tasks in issue list' do
|
||||
task = create(:work_item, :task, project: project, author: user)
|
||||
|
||||
get :issues, params: { author_id: user.id }
|
||||
get :issues, params: { author_id: user.id }, format: :atom
|
||||
|
||||
expect(assigns[:issues].map(&:id)).to include(task.id)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ end
|
|||
RSpec.shared_examples 'default branch pipeline' do
|
||||
it 'is valid' do
|
||||
expect(pipeline.yaml_errors).to be nil
|
||||
expect(pipeline.errors).to be_empty
|
||||
expect(pipeline.status).to eq('created')
|
||||
expect(jobs).to include(expected_job_name)
|
||||
end
|
||||
|
|
@ -113,6 +114,7 @@ end
|
|||
RSpec.shared_examples 'merge request pipeline' do
|
||||
it "succeeds with expected job" do
|
||||
expect(pipeline.yaml_errors).to be nil
|
||||
expect(pipeline.errors).to be_empty
|
||||
expect(pipeline.status).to eq('created')
|
||||
expect(jobs).to include(expected_job_name)
|
||||
end
|
||||
|
|
@ -123,6 +125,7 @@ RSpec.shared_examples 'merge train pipeline' do
|
|||
|
||||
it "succeeds with expected job" do
|
||||
expect(pipeline.yaml_errors).to be nil
|
||||
expect(pipeline.errors).to be_empty
|
||||
expect(pipeline.status).to eq('created')
|
||||
expect(jobs).to include('pre-merge-checks')
|
||||
expect(jobs).not_to include('upload-frontend-fixtures')
|
||||
|
|
|
|||
|
|
@ -37,14 +37,15 @@ FactoryBot.define do
|
|||
|
||||
factory :wiki_page_meta, class: 'WikiPage::Meta' do
|
||||
title { generate(:wiki_page_title) }
|
||||
project { association(:project) unless namespace.present? || container.present? }
|
||||
container do
|
||||
@overrides[:project] ||
|
||||
@overrides[:namespace] ||
|
||||
association(:project)
|
||||
end
|
||||
|
||||
trait :for_wiki_page do
|
||||
transient do
|
||||
wiki_page { association(:wiki_page, container: container) }
|
||||
end
|
||||
|
||||
container { @overrides[:wiki_page]&.container || association(:project) }
|
||||
wiki_page { association(:wiki_page, container: container) }
|
||||
container { @overrides[:wiki_page]&.container || container }
|
||||
title { wiki_page.title }
|
||||
|
||||
initialize_with do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe 'Project wikis', :js, feature_category: :wiki, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/508966' do
|
||||
RSpec.describe 'Project wikis', :js, feature_category: :wiki do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
let(:wiki) { create(:project_wiki, user: user, project: project) }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ describe('~/analytics/shared/graphql/resolvers', () => {
|
|||
|
||||
describe('flowMetricsCommits', () => {
|
||||
const mockFullPath = 'fake/namespace/path';
|
||||
const mockParams = { startDate: '2024-12-11', endDate: '2024-12-11' };
|
||||
const mockParams = { startDate: '2024-11-11', endDate: '2024-12-11' };
|
||||
const requestParams = {
|
||||
fullPath: mockFullPath,
|
||||
...mockParams,
|
||||
|
|
@ -39,7 +39,10 @@ describe('~/analytics/shared/graphql/resolvers', () => {
|
|||
it('will set the request parameters', async () => {
|
||||
await mockResolvers.Query.flowMetricsCommits(null, requestParams);
|
||||
|
||||
expect(api.getValueStreamSummaryMetrics).toHaveBeenCalledWith(mockFullPath, mockParams);
|
||||
expect(api.getValueStreamSummaryMetrics).toHaveBeenCalledWith(mockFullPath, {
|
||||
created_after: '2024-11-11',
|
||||
created_before: '2024-12-11',
|
||||
});
|
||||
});
|
||||
|
||||
it('will only return the commit data', async () => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { GlDrawer, GlAlert } from '@gitlab/ui';
|
|||
import { nextTick } from 'vue';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import RoleDetailsDrawer from '~/members/components/table/drawer/role_details_drawer.vue';
|
||||
import MembersTableCell from '~/members/components/table/members_table_cell.vue';
|
||||
import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue';
|
||||
import MemberAvatar from '~/members/components/table/member_avatar.vue';
|
||||
import RoleSelector from '~/members/components/role_selector.vue';
|
||||
import { roleDropdownItems } from '~/members/utils';
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@ import PlaceholderNote from '~/pages/shared/wikis/wiki_notes/components/placehol
|
|||
import SkeletonNote from '~/vue_shared/components/notes/skeleton_note.vue';
|
||||
import WikiDiscussion from '~/pages/shared/wikis/wiki_notes/components/wiki_discussion.vue';
|
||||
import WikiPageQuery from '~/wikis/graphql/wiki_page.query.graphql';
|
||||
import WikiNotesActivityHeader from '~/pages/shared/wikis/wiki_notes/components/wiki_notes_activity_header.vue';
|
||||
import eventHub, {
|
||||
EVENT_EDIT_WIKI_DONE,
|
||||
EVENT_EDIT_WIKI_START,
|
||||
} from '~/pages/shared/wikis/event_hub';
|
||||
import { note, noteableId } from '../mock_data';
|
||||
|
||||
describe('WikiNotesApp', () => {
|
||||
|
|
@ -40,6 +45,26 @@ describe('WikiNotesApp', () => {
|
|||
wrapper = createWrapper();
|
||||
});
|
||||
|
||||
describe('when editing a wiki page', () => {
|
||||
beforeEach(async () => {
|
||||
eventHub.$emit(EVENT_EDIT_WIKI_START);
|
||||
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('should hide notes when editing a wiki page', () => {
|
||||
expect(wrapper.findComponent(WikiNotesActivityHeader).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should show notes when editing a wiki page is done', async () => {
|
||||
eventHub.$emit(EVENT_EDIT_WIKI_DONE);
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.findComponent(WikiNotesActivityHeader).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should render skeleton notes before content loads', () => {
|
||||
wrapper = createWrapper();
|
||||
const skeletonNotes = wrapper.findAllComponents(SkeletonNote);
|
||||
|
|
|
|||
|
|
@ -153,11 +153,7 @@ describe('SidebarEscalationStatus', () => {
|
|||
});
|
||||
|
||||
it('updates the status', () => {
|
||||
// Sometimes status has a intermediate wrapping component. A quirk of vue-test-utils
|
||||
// means that in that case 'value' is exposed as a prop. If no wrapping component
|
||||
// exists it is exposed as an attribute.
|
||||
const statusValue =
|
||||
findStatusComponent().props('value') || findStatusComponent().attributes('value');
|
||||
const statusValue = findStatusComponent().props('value');
|
||||
expect(statusValue).toBe(STATUS_ACKNOWLEDGED);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -123,6 +123,80 @@ RSpec.describe Gitlab::Auth::Identity, :request_store, feature_category: :system
|
|||
end
|
||||
end
|
||||
|
||||
describe '.link_from_web_request' do
|
||||
context 'when composite identity feature flag is enabled' do
|
||||
context 'when service_account has composite identity enforced' do
|
||||
before do
|
||||
allow(primary_user).to receive(:has_composite_identity?).and_return(true)
|
||||
end
|
||||
|
||||
it 'creates and links identity with scope user' do
|
||||
identity = described_class.link_from_web_request(
|
||||
service_account: primary_user,
|
||||
scoped_user: scoped_user
|
||||
)
|
||||
|
||||
expect(identity.primary_user).to eq(primary_user)
|
||||
expect(identity.scoped_user).to eq(scoped_user)
|
||||
expect(identity).to be_linked
|
||||
end
|
||||
|
||||
context 'when trying to link different scoped users' do
|
||||
let(:another_scope_user) { create(:user) }
|
||||
|
||||
it 'raises IdentityLinkMismatchError when trying to link different scoped users' do
|
||||
identity = described_class.link_from_web_request(
|
||||
service_account: primary_user,
|
||||
scoped_user: scoped_user
|
||||
)
|
||||
|
||||
expect do
|
||||
identity.link!(another_scope_user)
|
||||
end.to raise_error(described_class::IdentityLinkMismatchError)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when service_account does not have composite identity enforced' do
|
||||
it 'creates identity without linking' do
|
||||
identity = described_class.link_from_web_request(
|
||||
service_account: primary_user,
|
||||
scoped_user: scoped_user
|
||||
)
|
||||
|
||||
expect(identity).not_to be_linked
|
||||
end
|
||||
end
|
||||
|
||||
context 'when composite identity feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(composite_identity: false)
|
||||
end
|
||||
|
||||
it 'creates identity without linking' do
|
||||
identity = described_class.link_from_web_request(
|
||||
service_account: primary_user,
|
||||
scoped_user: scoped_user
|
||||
)
|
||||
|
||||
expect(identity.primary_user).to eq(primary_user)
|
||||
expect(identity).not_to be_linked
|
||||
end
|
||||
end
|
||||
|
||||
context 'when service_account is not present' do
|
||||
it 'raises an error' do
|
||||
expect do
|
||||
described_class.link_from_web_request(
|
||||
service_account: nil,
|
||||
scoped_user: scoped_user
|
||||
)
|
||||
end.to raise_error(described_class::MissingServiceAccountError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.sidekiq_restore!' do
|
||||
context 'when job has primary and scoped identity stored' do
|
||||
let(:job) { { 'jid' => 123, 'sqci' => [primary_user.id, scoped_user.id] } }
|
||||
|
|
|
|||
|
|
@ -185,6 +185,17 @@ RSpec.describe WikiPage::Meta, feature_category: :wiki do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#wiki_page' do
|
||||
let(:wiki_page) { create(:wiki_page, container: project, content: 'test content') }
|
||||
let(:meta) { create(:wiki_page_meta, :for_wiki_page, container: project, wiki_page: wiki_page) }
|
||||
|
||||
subject { meta.wiki_page }
|
||||
|
||||
it 'finds the wiki page for the meta record' do
|
||||
expect(subject).to eq(wiki_page)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.find_or_create' do
|
||||
let(:old_title) { generate(:wiki_page_title) }
|
||||
let(:last_known_slug) { generate(:sluggified_title) }
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'issuables list meta-data' do |issuable_type, action = nil|
|
||||
RSpec.shared_examples 'issuables list meta-data' do |issuable_type, action = nil, format: :html|
|
||||
include ProjectForksHelper
|
||||
|
||||
def get_action(action, project, extra_params = {})
|
||||
if action
|
||||
get action, params: { author_id: project.creator.id }.merge(extra_params)
|
||||
get action, params: { author_id: project.creator.id }.merge(extra_params), format: format
|
||||
else
|
||||
get :index, params: { namespace_id: project.namespace, project_id: project }.merge(extra_params)
|
||||
get :index, params: { namespace_id: project.namespace, project_id: project }.merge(extra_params), format: format
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -19,6 +19,8 @@ RSpec.shared_examples 'issuables list meta-data' do |issuable_type, action = nil
|
|||
end
|
||||
end
|
||||
|
||||
let(:format) { format }
|
||||
|
||||
let!(:issuables) do
|
||||
%w[fix improve/awesome].map do |source_branch|
|
||||
create_issuable(issuable_type, project, source_branch: source_branch)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'issuables requiring filter' do |action|
|
||||
RSpec.shared_examples 'issuables requiring filter' do |action, format: :html|
|
||||
it "doesn't load any issuables if no filter is set" do
|
||||
expect_any_instance_of(described_class).not_to receive(:issuables_collection)
|
||||
|
||||
get action
|
||||
|
||||
expect(response).to render_template(action)
|
||||
get action, format: format
|
||||
end
|
||||
|
||||
it "loads issuables if at least one filter is set" do
|
||||
expect_any_instance_of(described_class).to receive(:issuables_collection).and_call_original
|
||||
|
||||
get action, params: { author_id: user.id }
|
||||
get action, params: { author_id: user.id }, format: format
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ RSpec.shared_examples 'User updates wiki page' do
|
|||
expect(page).to have_content('My awesome wiki!')
|
||||
end
|
||||
|
||||
it 'does not show comments when editing' do
|
||||
expect(page).not_to have_content('Activity')
|
||||
end
|
||||
|
||||
it 'updates entry in redirects.yml file on changing page path' do
|
||||
wiki.repository.update_file(
|
||||
user, '.gitlab/redirects.yml',
|
||||
|
|
|
|||
|
|
@ -57,6 +57,17 @@ RSpec.shared_examples 'wiki_page' do |container_type|
|
|||
subject { persisted_page }
|
||||
end
|
||||
|
||||
describe '#meta' do
|
||||
let(:wiki_page) { create(:wiki_page, container: container, content: 'test content') }
|
||||
let!(:meta) { create(:wiki_page_meta, :for_wiki_page, container: container, wiki_page: wiki_page) }
|
||||
|
||||
subject { wiki_page.meta }
|
||||
|
||||
it 'finds the meta record for the page' do
|
||||
expect(subject).to eq(meta)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#front_matter' do
|
||||
let(:wiki_page) { create(:wiki_page, container: container, content: content) }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue