Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-02-01 15:18:50 +00:00
parent 1ae73e5bfc
commit 3bdc719293
44 changed files with 554 additions and 315 deletions

View file

@ -11,36 +11,9 @@
metrics: "${METRICS_FILE}"
expire_in: 31d
# Disabled since it causes intermittent SIGSEGV in CI:
# https://gitlab.com/gitlab-org/gitlab/-/issues/350296
.memory-static:
extends: .only-code-memory-job-base
stage: test
needs: ["setup-test-env"]
variables:
SETUP_DB: "false"
MEMORY_BUNDLE_MEM_FILE: "tmp/memory_bundle_mem.txt"
MEMORY_BUNDLE_OBJECTS_FILE: "tmp/memory_bundle_objects.txt"
script:
# Uses two different reports from the 'derailed_benchmars' gem.
# Loads each of gems in the Gemfile and checks how much memory they consume when they are required.
# 'derailed_benchmarks' internally uses 'get_process_mem'
- bundle exec derailed bundle:mem > "${MEMORY_BUNDLE_MEM_FILE}"
- scripts/generate-gems-size-metrics-static "${MEMORY_BUNDLE_MEM_FILE}" >> "${METRICS_FILE}"
# Outputs detailed information about objects created while gems are loaded.
# 'derailed_benchmarks' internally uses 'memory_profiler'
- bundle exec derailed bundle:objects > "${MEMORY_BUNDLE_OBJECTS_FILE}"
- scripts/generate-gems-memory-metrics-static "${MEMORY_BUNDLE_OBJECTS_FILE}" >> "${METRICS_FILE}"
artifacts:
paths:
- "${METRICS_FILE}"
- "${MEMORY_BUNDLE_MEM_FILE}"
- "${MEMORY_BUNDLE_OBJECTS_FILE}"
# Show memory usage caused by invoking require per gem.
# Unlike `memory-static`, it hits the app with one request to ensure that any last minute require-s have been called.
# Hits the app with one request to ensure that any last minute require-s have been called.
# The application is booted in `production` environment.
# All tests are run without a webserver (directly using Rack::Mock by default).
memory-on-boot:

View file

@ -97,14 +97,8 @@ RSpec/FilePath:
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
Max: 28
Max: 25
AllowSubject: true
Exclude:
- 'spec/migrations/**/*.rb'
- 'spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb'
- 'spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb'
- 'ee/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb'
Naming/FileName:
ExpectMatchingDefinition: true

View file

@ -0,0 +1,11 @@
---
RSpec/MultipleMemoizedHelpers:
Exclude:
- spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
- spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
- spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
- spec/requests/api/ci/runner/jobs_artifacts_spec.rb
- ee/spec/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids_spec.rb
- ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb
- ee/spec/services/ee/boards/issues/move_service_spec.rb
- ee/spec/services/security/store_report_service_spec.rb

View file

@ -17,7 +17,6 @@ Style/OpenStructUse:
- spec/factories/go_module_versions.rb
- spec/factories/wiki_pages.rb
- spec/features/projects/clusters_spec.rb
- spec/finders/template_finder_spec.rb
- spec/graphql/mutations/branches/create_spec.rb
- spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
- spec/graphql/mutations/clusters/agents/create_spec.rb

View file

@ -1 +1 @@
1.52.0
1.53.0

View file

@ -15,7 +15,7 @@ import getAlertsQuery from '~/graphql_shared/queries/get_alerts.query.graphql';
import { fetchPolicies } from '~/lib/graphql';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { joinPaths, visitUrl } from '~/lib/utils/url_utility';
import { s__, __ } from '~/locale';
import { s__, __, n__ } from '~/locale';
import AlertStatus from '~/vue_shared/alert_details/components/alert_status.vue';
import {
tdClass,
@ -32,8 +32,11 @@ const TH_TEST_ID = { 'data-testid': 'alert-management-severity-sort' };
const TWELVE_HOURS_IN_MS = 12 * 60 * 60 * 1000;
const MAX_VISIBLE_ASSIGNEES = 4;
export default {
trackAlertListViewsOptions,
MAX_VISIBLE_ASSIGNEES,
i18n: {
noAlertsMsg: s__(
'AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list.',
@ -258,6 +261,13 @@ export default {
this.serverErrorMessage = '';
this.isErrorAlertDismissed = true;
},
assigneesBadgeSrOnlyText(item) {
return n__(
'%d additional assignee',
'%d additional assignees',
item.assignees.nodes.length - MAX_VISIBLE_ASSIGNEES,
);
},
},
};
</script>
@ -365,10 +375,11 @@ export default {
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
:max-visible="4"
:max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
:badge-sr-only-text="assigneesBadgeSrOnlyText(item)"
>
<template #avatar="{ avatar }">
<gl-avatar-link

View file

@ -12,7 +12,7 @@ import {
} from '@gitlab/ui';
import { isValidSlaDueAt } from 'ee_else_ce/vue_shared/components/incidents/utils';
import { visitUrl, mergeUrlParams, joinPaths } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { s__, n__ } from '~/locale';
import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
import SeverityToken from '~/sidebar/components/severity/severity.vue';
import Tracking from '~/tracking';
@ -38,6 +38,8 @@ import {
import getIncidentsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
import getIncidents from '../graphql/queries/get_incidents.query.graphql';
const MAX_VISIBLE_ASSIGNEES = 4;
export default {
trackIncidentCreateNewOptions,
trackIncidentListViewsOptions,
@ -94,6 +96,7 @@ export default {
thAttr: TH_PUBLISHED_TEST_ID,
},
],
MAX_VISIBLE_ASSIGNEES,
components: {
GlLoadingIcon,
GlTable,
@ -295,6 +298,13 @@ export default {
errorAlertDismissed() {
this.isErrorAlertDismissed = true;
},
assigneesBadgeSrOnlyText(item) {
return n__(
'%d additional assignee',
'%d additional assignees',
item.assignees.nodes.length - MAX_VISIBLE_ASSIGNEES,
);
},
isValidSlaDueAt,
},
};
@ -391,10 +401,11 @@ export default {
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
:max-visible="4"
:max-visible="$options.MAX_VISIBLE_ASSIGNEES"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
:badge-sr-only-text="assigneesBadgeSrOnlyText(item)"
>
<template #avatar="{ avatar }">
<gl-avatar-link

View file

@ -69,11 +69,11 @@ export default class CreateMergeRequestDropdown {
this.regexps = {
branch: {
createBranchPath: new RegExp('(branch_name=)(.+?)(?=&issue)'),
createMrPath: new RegExp('(branch_name=)(.+?)(?=&ref)'),
createMrPath: new RegExp('(source_branch%5D=)(.+?)(?=&)'),
},
ref: {
createBranchPath: new RegExp('(ref=)(.+?)$'),
createMrPath: new RegExp('(ref=)(.+?)$'),
createMrPath: new RegExp('(target_branch%5D=)(.+?)$'),
},
};
@ -167,23 +167,18 @@ export default class CreateMergeRequestDropdown {
}
createMergeRequest() {
this.isCreatingMergeRequest = true;
return new Promise(() => {
this.isCreatingMergeRequest = true;
return axios
.post(this.createMrPath, {
target_project_id: canCreateConfidentialMergeRequest()
? confidentialMergeRequestState.selectedProject.id
: null,
})
.then(({ data }) => {
this.mergeRequestCreated = true;
window.location.href = data.url;
})
.catch(() =>
createFlash({
message: __('Failed to create merge request. Please try again.'),
}),
);
return this.createBranch().then(() => {
window.location.href = canCreateConfidentialMergeRequest()
? this.createMrPath.replace(
this.projectPath,
confidentialMergeRequestState.selectedProject.pathWithNamespace,
)
: this.createMrPath;
});
});
}
disable() {
@ -562,5 +557,7 @@ export default class CreateMergeRequestDropdown {
this.regexps[target].createMrPath,
pathReplacement,
);
this.wrapperEl.dataset.createMrPath = this.createMrPath;
}
}

View file

@ -1,12 +1,11 @@
<script>
import { GlAlert, GlLink, GlSprintf, GlEmptyState } from '@gitlab/ui';
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapState, mapMutations } from 'vuex';
import { retrieveAlert } from '~/jira_connect/subscriptions/utils';
import { SET_ALERT } from '../store/mutation_types';
import SubscriptionsList from './subscriptions_list.vue';
import AddNamespaceButton from './add_namespace_button.vue';
import SignInButton from './sign_in_button.vue';
import SignInPage from '../pages/sign_in.vue';
import SubscriptionsPage from '../pages/subscriptions.vue';
import UserLink from './user_link.vue';
import CompatibilityAlert from './compatibility_alert.vue';
@ -16,12 +15,10 @@ export default {
GlAlert,
GlLink,
GlSprintf,
GlEmptyState,
SubscriptionsList,
AddNamespaceButton,
SignInButton,
UserLink,
CompatibilityAlert,
SignInPage,
SubscriptionsPage,
},
inject: {
usersPath: {
@ -84,43 +81,9 @@ export default {
<user-link :user-signed-in="userSignedIn" :has-subscriptions="hasSubscriptions" />
<h2 class="gl-text-center gl-mb-7">{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
<div class="jira-connect-app-body gl-mx-auto gl-px-5 gl-mb-7">
<template v-if="hasSubscriptions">
<div class="gl-display-flex gl-justify-content-end">
<sign-in-button v-if="!userSignedIn" :users-path="usersPath" />
<add-namespace-button v-else />
</div>
<subscriptions-list />
</template>
<template v-else>
<div v-if="!userSignedIn" class="gl-text-center">
<p class="gl-mb-7">{{ s__('JiraService|Sign in to GitLab.com to get started.') }}</p>
<sign-in-button class="gl-mb-7" :users-path="usersPath">
{{ __('Sign in to GitLab') }}
</sign-in-button>
<p>
{{
s__(
'Integrations|Note: this integration only works with accounts on GitLab.com (SaaS).',
)
}}
</p>
</div>
<gl-empty-state
v-else
:title="s__('Integrations|No linked namespaces')"
:description="
s__(
'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
)
"
>
<template #actions>
<add-namespace-button />
</template>
</gl-empty-state>
</template>
<div class="gl-layout-w-limited gl-mx-auto gl-px-5 gl-mb-7">
<sign-in-page v-if="!userSignedIn" :has-subscriptions="hasSubscriptions" />
<subscriptions-page v-else :has-subscriptions="hasSubscriptions" />
</div>
</div>
</template>

View file

@ -1,6 +1,7 @@
<script>
import { GlButton } from '@gitlab/ui';
import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
import { s__ } from '~/locale';
export default {
components: {
@ -25,12 +26,15 @@ export default {
this.signInURL = await getGitlabSignInURL(this.usersPath);
},
},
i18n: {
defaultButtonText: s__('Integrations|Sign in to GitLab'),
},
};
</script>
<template>
<gl-button category="primary" variant="info" :href="signInURL" target="_blank">
<slot>
{{ s__('Integrations|Sign in to add namespaces') }}
{{ $options.i18n.defaultButtonText }}
</slot>
</gl-button>
</template>

View file

@ -0,0 +1,40 @@
<script>
import { s__ } from '~/locale';
import SubscriptionsList from '../components/subscriptions_list.vue';
import SignInButton from '../components/sign_in_button.vue';
export default {
name: 'SignInPage',
components: {
SubscriptionsList,
SignInButton,
},
inject: ['usersPath'],
props: {
hasSubscriptions: {
type: Boolean,
required: true,
},
},
i18n: {
signinButtonTextWithSubscriptions: s__('Integrations|Sign in to add namespaces'),
signInText: s__('JiraService|Sign in to GitLab.com to get started.'),
},
};
</script>
<template>
<div v-if="hasSubscriptions">
<div class="gl-display-flex gl-justify-content-end">
<sign-in-button :users-path="usersPath">
{{ $options.i18n.signinButtonTextWithSubscriptions }}
</sign-in-button>
</div>
<subscriptions-list />
</div>
<div v-else class="gl-text-center">
<p class="gl-mb-7">{{ $options.i18n.signInText }}</p>
<sign-in-button class="gl-mb-7" :users-path="usersPath" />
</div>
</template>

View file

@ -0,0 +1,43 @@
<script>
import { GlEmptyState } from '@gitlab/ui';
import SubscriptionsList from '../components/subscriptions_list.vue';
import AddNamespaceButton from '../components/add_namespace_button.vue';
export default {
name: 'SubscriptionsPage',
components: {
GlEmptyState,
SubscriptionsList,
AddNamespaceButton,
},
props: {
hasSubscriptions: {
type: Boolean,
required: true,
},
},
};
</script>
<template>
<div v-if="hasSubscriptions">
<div class="gl-display-flex gl-justify-content-end">
<add-namespace-button />
</div>
<subscriptions-list />
</div>
<gl-empty-state
v-else
:title="s__('Integrations|No linked namespaces')"
:description="
s__(
'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
)
"
>
<template #actions>
<add-namespace-button />
</template>
</gl-empty-state>
</template>

View file

@ -1,10 +1,13 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
export default {
components: {
GlLoadingIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
commitRef: {
type: String,
@ -41,7 +44,13 @@ export default {
<template>
<tr class="tree-item">
<td colspan="3" class="tree-item-file-name" @click.self="clickRow">
<td
v-gl-tooltip.left.viewport
:title="__('Go to parent directory')"
colspan="3"
class="tree-item-file-name"
@click.self="clickRow"
>
<gl-loading-icon
v-if="parentPath === loadingPath"
size="sm"

View file

@ -40,10 +40,6 @@ $header-height: 40px;
max-width: 1000px;
}
.jira-connect-app-body {
max-width: 768px;
}
// needed for external_link
svg.s16 {
width: 16px;

View file

@ -92,6 +92,8 @@ class Projects::CommitController < Projects::ApplicationController
end
def branches
return git_not_found! unless commit
# branch_names_contains/tag_names_contains can take a long time when there are thousands of
# branches/tags - each `git branch --contains xxx` request can consume a cpu core.
# so only do the query when there are a manageable number of branches/tags

View file

@ -178,6 +178,10 @@ class Blob < SimpleDelegator
end
end
def symlink?
mode == MODE_SYMLINK
end
def extension
@extension ||= extname.downcase.delete('.')
end

View file

@ -162,6 +162,23 @@ module Ci
)
end
scope :group_or_instance_wide, -> (group) do
group_and_ancestor_runners =
if ::Feature.enabled?(:ci_find_runners_by_ci_mirrors, group, default_enabled: :yaml)
belonging_to_group_and_ancestors(group.id)
else
legacy_belonging_to_group(group.id, include_ancestors: true)
end
from_union(
[
group_and_ancestor_runners,
instance_type
],
remove_duplicates: false
)
end
scope :assignable_for, ->(project) do
# FIXME: That `to_sql` is needed to workaround a weird Rails bug.
# Without that, placeholders would miss one and couldn't match.

View file

@ -21,7 +21,7 @@ module Branches
error("Failed to create branch '#{branch_name}': invalid reference name '#{ref}'")
end
rescue Gitlab::Git::PreReceiveError => e
Gitlab::ErrorTracking.track_exception(e, pre_receive_message: e.raw_message, branch_name: branch_name, ref: ref)
Gitlab::ErrorTracking.log_exception(e, pre_receive_message: e.raw_message, branch_name: branch_name, ref: ref)
error(e.message)
end

View file

@ -9,7 +9,7 @@
= copy_file_path_button(blob.path)
%small.mr-1
- if blob.mode == Blob::MODE_SYMLINK
- if blob.symlink?
= _('Symbolic link') << ' ·'
= number_to_human_size(blob.raw_size)

View file

@ -6,8 +6,8 @@
- create_mr_text = can_create_confidential_merge_request? ? _('Create confidential merge request') : _('Create merge request')
- can_create_path = can_create_branch_project_issue_path(@project, @issue)
- create_mr_path = create_merge_request_project_issue_path(@project, @issue, branch_name: @issue.to_branch_name, ref: @project.default_branch)
- create_branch_path = project_branches_path(@project, branch_name: @issue.to_branch_name, ref: @project.default_branch, issue_iid: @issue.iid)
- create_mr_path = project_new_merge_request_path(@project, merge_request: { source_branch: @issue.to_branch_name, target_branch: @project.default_branch })
- create_branch_path = project_branches_path(@project, branch_name: @issue.to_branch_name, ref: @project.default_branch, issue_iid: @issue.iid, format: :json)
- refs_path = refs_namespace_project_path(@project.namespace, @project, search: '')
.create-mr-dropdown-wrap.d-inline-block.full-width-mobile.js-create-mr{ data: { project_path: @project.full_path, project_id: @project.id, can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path, is_confidential: can_create_confidential_merge_request?.to_s } }

View file

@ -448,8 +448,7 @@ Example response:
## List project's runners
List all runners (specific and shared) available in the project. Shared runners
are listed if at least one shared runner is defined.
List all runners available in the project, including from ancestor groups and any shared runners.
```plaintext
GET /projects/:id/runners
@ -567,8 +566,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## List group's runners
List all runners (specific and shared) available in the group as well it's ancestor groups.
Shared runners are listed if at least one shared runner is defined.
List all runners available in the group as well as its ancestor groups, including any shared runners.
```plaintext
GET /groups/:id/runners

View file

@ -74,13 +74,13 @@ we might want to follow these three tracks described below.
<!-- markdownlint-disable MD029 -->
1. Partition builds queuing tables
2. Archive CI/CD data into partitioned database schema
3. Migrate archived builds metadata out of primary database
1. Partition CI/CD builds queuing database tables
2. Partition CI/CD pipelines database tables
3. Reduce the rate of builds metadata table growth
<!-- markdownlint-enable MD029 -->
### Migrate archived builds metadata out of primary database
### Reduce the rate of builds metadata table growth
Once a build (or a pipeline) gets archived, it is no longer possible to resume
pipeline processing in such pipeline. It means that all the metadata, we store
@ -98,15 +98,16 @@ be able to use de-duplication of metadata entries and other normalization
strategies to consume less storage while retaining ability to query this
dataset. Technical evaluation will be required to find the best solution here.
Epic: [Migrate archived builds metadata out of primary database](https://gitlab.com/groups/gitlab-org/-/epics/7216).
Epic: [Reduce the rate of builds metadata table growth](https://gitlab.com/groups/gitlab-org/-/epics/7434).
### Archive CI/CD data into partitioned database schema
### Partition CI/CD pipelines database tables
After we move CI/CD metadata to a different store, the problem of having
billions of rows describing pipelines, builds and artifacts, remains. We still
need to keep reference to the metadata we store in object storage and we still
do need to be able to retrieve this information reliably in bulk (or search
through it).
After we move CI/CD metadata to a different store, or reduce the rate of
metadata growth in a different way, the problem of having billions of rows
describing pipelines, builds and artifacts, remains. We still need to keep
reference to the metadata we might store in object storage and we still do need
to be able to retrieve this information reliably in bulk (or search through
it).
It means that by moving data to object storage we might not be able to reduce
the number of rows in CI/CD tables. Moving data to object storage should help
@ -132,9 +133,9 @@ partitioning on the application level.
Partitioning rarely accessed data should also follow the policy defined for
builds archival, to make it consistent and reliable.
Epic: [Archive CI/CD data into partitioned database schema](https://gitlab.com/groups/gitlab-org/-/epics/5417).
Epic: [Partition CI/CD pipelines database tables](https://gitlab.com/groups/gitlab-org/-/epics/5417).
### Partition builds queuing tables
### Partition CI/CD builds queuing database tables
While working on the [CI/CD Scale](../ci_scale/index.md) blueprint, we have
introduced a [new architecture for queuing CI/CD builds](https://gitlab.com/groups/gitlab-org/-/epics/5909#note_680407908)
@ -156,7 +157,7 @@ for builds archival. Instead we should leverage a long-standing policy saying
that builds created more 24 hours ago need to be removed from the queue. This
business rule is present in the product since the inception of GitLab CI.
Epic: [Partition builds queuing tables](https://gitlab.com/gitlab-org/gitlab/-/issues/347027).
Epic: [Partition CI/CD builds queuing database tables](https://gitlab.com/groups/gitlab-org/-/epics/7438).
## Principles
@ -215,9 +216,9 @@ pipelines data, although a user provided partition identifier may be required.
All three tracks can be worked on in parallel:
1. [Migrate archived build metadata to object storage](https://gitlab.com/groups/gitlab-org/-/epics/7216).
1. [Partition CI/CD data that have been archived](https://gitlab.com/groups/gitlab-org/-/epics/5417).
1. [Partition CI/CD queuing tables using list partitioning](https://gitlab.com/gitlab-org/gitlab/-/issues/347027)
1. [Reduce the rate of builds metadata table growth](https://gitlab.com/groups/gitlab-org/-/epics/7434).
1. [Partition CI/CD pipelines database tables](https://gitlab.com/groups/gitlab-org/-/epics/5417).
1. [Partition CI/CD queuing tables using list partitioning](https://gitlab.com/groups/gitlab-org/-/epics/7438)
## Status

View file

@ -316,6 +316,11 @@ Instead of:
Use **expand** instead of **open** when you are talking about expanding or collapsing a section in the UI.
## FAQ
We want users to find information quickly, and they rarely search for the term **FAQ**.
Information in FAQs belongs with other similar information, under an easily searchable topic title.
## field
Use **box** instead of **field** or **text box**.
@ -371,6 +376,11 @@ Use title case for **GitLab Runner**. This is the product you install. See also
Use **GitLab self-managed** to refer to the product license for GitLab instances managed by customers themselves.
## guide
We want to speak directly to users. On `docs.gitlab.com`, do not use **guide** as part of a page title.
For example, **Snowplow Guide**. Instead, speak about the feature itself, and how to use it. For example, **Use Snowplow to do xyz**.
## Guest
When writing about the Guest role:

View file

@ -232,12 +232,7 @@ module API
use :pagination
end
get ':id/runners' do
runners = if ::Feature.enabled?(:ci_find_runners_by_ci_mirrors, user_group, default_enabled: :yaml)
::Ci::Runner.belonging_to_group_and_ancestors(user_group.id)
else
::Ci::Runner.legacy_belonging_to_group(user_group.id, include_ancestors: true)
end
runners = ::Ci::Runner.group_or_instance_wide(user_group)
runners = apply_filter(runners, params)
present paginate(runners), with: Entities::Ci::Runner

View file

@ -116,6 +116,26 @@ msgid_plural "%d URLs scanned"
msgstr[0] ""
msgstr[1] ""
msgid "%d additional approver"
msgid_plural "%d additional approvers"
msgstr[0] ""
msgstr[1] ""
msgid "%d additional assignee"
msgid_plural "%d additional assignees"
msgstr[0] ""
msgstr[1] ""
msgid "%d additional commenter"
msgid_plural "%d additional commenters"
msgstr[0] ""
msgstr[1] ""
msgid "%d additional committer"
msgid_plural "%d additional committers"
msgstr[0] ""
msgstr[1] ""
msgid "%d approver"
msgid_plural "%d approvers"
msgstr[0] ""
@ -14758,9 +14778,6 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
msgid "Failed to create merge request. Please try again."
msgstr ""
msgid "Failed to create new access token: %{token_response_message}"
msgstr ""
@ -15780,6 +15797,9 @@ msgstr ""
msgid "Geo|Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr ""
msgid "Geo|All"
msgstr ""
msgid "Geo|All %{replicable_name}"
msgstr ""
@ -16632,6 +16652,9 @@ msgstr ""
msgid "Go to parent"
msgstr ""
msgid "Go to parent directory"
msgstr ""
msgid "Go to previous page"
msgstr ""
@ -19317,9 +19340,6 @@ msgstr ""
msgid "Integrations|No linked namespaces"
msgstr ""
msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
msgstr ""
msgid "Integrations|Projects using custom settings"
msgstr ""
@ -19356,6 +19376,9 @@ msgstr ""
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
msgstr ""
msgid "Integrations|Sign in to GitLab"
msgstr ""
msgid "Integrations|Sign in to add namespaces"
msgstr ""
@ -23596,9 +23619,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr ""
msgid "NetworkPolicies|.yaml"
msgstr ""
msgid "NetworkPolicies|.yaml mode"
msgstr ""
@ -23677,9 +23697,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
msgid "NetworkPolicies|Rule"
msgstr ""
msgid "NetworkPolicies|Rule mode"
msgstr ""
@ -31924,6 +31941,9 @@ msgstr ""
msgid "SecurityOrchestration|Status"
msgstr ""
msgid "SecurityOrchestration|Summary"
msgstr ""
msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr ""
@ -34942,7 +34962,10 @@ msgstr ""
msgid "SuperSonics|current subscription"
msgstr ""
msgid "SuperSonics|history subscriptions"
msgid "SuperSonics|future subscriptions"
msgstr ""
msgid "SuperSonics|past subscriptions"
msgstr ""
msgid "Support"

View file

@ -56,7 +56,7 @@
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "2.2.0",
"@gitlab/ui": "33.1.0",
"@gitlab/ui": "34.0.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.4-1",
"@rails/ujs": "6.1.4-1",

View file

@ -1,19 +0,0 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
abort "usage: #{__FILE__} <memory_bundle_objects_file_name>" unless ARGV.length == 1
memory_bundle_objects_file_name = ARGV.first
full_report = File.readlines(memory_bundle_objects_file_name)
allocated_str = full_report[1]
retained_str = full_report[2]
allocated_stats = /Total allocated: (?<bytes>.*) bytes \((?<objects>.*) objects\)/.match(allocated_str)
retained_stats = /Total retained: (?<bytes>.*) bytes \((?<objects>.*) objects\)/.match(retained_str)
abort 'failed to process the benchmark output' unless allocated_stats && retained_stats
puts "memory_static_objects_allocated_mb #{(allocated_stats[:bytes].to_f / (1024 * 1024)).round(1)}"
puts "memory_static_objects_retained_mb #{(retained_stats[:bytes].to_f / (1024 * 1024)).round(1)}"
puts "memory_static_objects_allocated_items #{allocated_stats[:objects]}"
puts "memory_static_objects_retained_items #{retained_stats[:objects]}"

View file

@ -1,31 +0,0 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
abort "usage: #{__FILE__} <memory_bundle_mem_file_name>" unless ARGV.length == 1
memory_bundle_mem_file_name = ARGV.first
full_report = File.readlines(memory_bundle_mem_file_name)
def total_size(memory_bundle_mem_report)
stats = /TOP: (?<total_mibs_str>.*) MiB/.match(memory_bundle_mem_report.first)
abort 'failed to process the benchmark output' unless stats
"gem_total_size_mb #{stats[:total_mibs_str].to_f.round(1)}"
end
TOP_LEVEL_GEM_LOG_FORMAT = /^ (?<gem_name>\S.*):\s*(?<gem_size>\d[.\d]*)\s*MiB/.freeze
def all_gems(memory_bundle_mem_report)
memory_bundle_mem_report.map do |line|
TOP_LEVEL_GEM_LOG_FORMAT.match(line)
end.compact
end
def gems_as_metrics(gems_match_data)
gems_match_data.map do |gem|
gem_name = gem[:gem_name]
gem_size_mb = gem[:gem_size].to_f.round(1)
"gem_size_mb{name=\"#{gem_name}\"} #{gem_size_mb}"
end
end
puts total_size(full_report)
puts gems_as_metrics(all_gems(full_report)).sort(&:casecmp)

View file

@ -183,6 +183,18 @@ RSpec.describe Projects::CommitController do
expect(assigns(:tags)).to eq([])
expect(assigns(:tags_limit_exceeded)).to be_truthy
end
context 'when commit is not found' do
it 'responds with 404' do
get(:branches, params: {
namespace_id: project.namespace,
project_id: project,
id: '11111111111111111111111111111111111111'
})
expect(response).to be_not_found
end
end
end
describe 'POST revert' do

View file

@ -71,16 +71,10 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
perform_enqueued_jobs do
select_dropdown_option('create-mr')
expect(page).to have_content('Draft: Resolve "Cherry-Coloured Funk"')
expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first))
wait_for_requests
expect(page).to have_content('New merge request')
expect(page).to have_content("From #{issue.to_branch_name} into #{project.default_branch}")
expect(page).to have_current_path(project_new_merge_request_path(project, merge_request: { source_branch: issue.to_branch_name, target_branch: project.default_branch }))
end
visit project_issue_path(project, issue)
expect(page).to have_content("created merge request !1 to address this issue")
expect(page).to have_content('mentioned in merge request !1')
end
it 'creates a branch' do
@ -100,17 +94,10 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
perform_enqueued_jobs do
select_dropdown_option('create-mr', branch_name)
expect(page).to have_content('Draft: Resolve "Cherry-Coloured Funk"')
expect(page).to have_content('Request to merge custom-branch-name into')
expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first))
wait_for_requests
expect(page).to have_content('New merge request')
expect(page).to have_content("From #{branch_name} into #{project.default_branch}")
expect(page).to have_current_path(project_new_merge_request_path(project, merge_request: { source_branch: branch_name, target_branch: project.default_branch }))
end
visit project_issue_path(project, issue)
expect(page).to have_content("created merge request !1 to address this issue")
expect(page).to have_content('mentioned in merge request !1')
end
it 'creates a branch' do

View file

@ -153,7 +153,12 @@ RSpec.describe TemplateFinder do
let(:params) { {} }
subject(:result) { described_class.new(type, project, params).template_names.values.flatten.map { |el| OpenStruct.new(el) } }
let(:template_name_struct) { Struct.new(:name, :id, :key, :project_id, keyword_init: true) }
subject(:result) do
described_class.new(type, project, params).template_names.values.flatten
.map { |el| template_name_struct.new(el) }
end
where(:type, :vendored_name) do
:dockerfiles | 'Binary'

View file

@ -59,7 +59,7 @@ describe('CreateMergeRequestDropdown', () => {
describe('updateCreatePaths', () => {
it('escapes branch names correctly', () => {
dropdown.createBranchPath = `${TEST_HOST}/branches?branch_name=some-branch&issue=42`;
dropdown.createMrPath = `${TEST_HOST}/create_merge_request?branch_name=some-branch&ref=main`;
dropdown.createMrPath = `${TEST_HOST}/create_merge_request?merge_request%5Bsource_branch%5D=test&merge_request%5Btarget_branch%5D=master`;
dropdown.updateCreatePaths('branch', 'contains#hash');
@ -68,7 +68,7 @@ describe('CreateMergeRequestDropdown', () => {
);
expect(dropdown.createMrPath).toBe(
`${TEST_HOST}/create_merge_request?branch_name=contains%23hash&ref=main`,
`${TEST_HOST}/create_merge_request?merge_request%5Bsource_branch%5D=contains%23hash&merge_request%5Btarget_branch%5D=master`,
);
});
});

View file

@ -1,11 +1,10 @@
import { GlLink, GlEmptyState } from '@gitlab/ui';
import { GlLink } from '@gitlab/ui';
import { nextTick } from 'vue';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
import SignInPage from '~/jira_connect/subscriptions/pages/sign_in.vue';
import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions.vue';
import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
@ -23,10 +22,8 @@ describe('JiraConnectApp', () => {
const findAlert = () => wrapper.findByTestId('jira-connect-persisted-alert');
const findAlertLink = () => findAlert().findComponent(GlLink);
const findSignInButton = () => wrapper.findComponent(SignInButton);
const findAddNamespaceButton = () => wrapper.findComponent(AddNamespaceButton);
const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findSignInPage = () => wrapper.findComponent(SignInPage);
const findSubscriptionsPage = () => wrapper.findComponent(SubscriptionsPage);
const createComponent = ({ provide, mountFn = shallowMountExtended } = {}) => {
store = createStore();
@ -43,49 +40,35 @@ describe('JiraConnectApp', () => {
describe('template', () => {
describe.each`
scenario | usersPath | subscriptions | expectSignInButton | expectEmptyState | expectNamespaceButton | expectSubscriptionsList
${'user is not signed in with subscriptions'} | ${'/users'} | ${[mockSubscription]} | ${true} | ${false} | ${false} | ${true}
${'user is not signed in without subscriptions'} | ${'/users'} | ${undefined} | ${true} | ${false} | ${false} | ${false}
${'user is signed in with subscriptions'} | ${undefined} | ${[mockSubscription]} | ${false} | ${false} | ${true} | ${true}
${'user is signed in without subscriptions'} | ${undefined} | ${undefined} | ${false} | ${true} | ${false} | ${false}
`(
'when $scenario',
({
usersPath,
expectSignInButton,
subscriptions,
expectEmptyState,
expectNamespaceButton,
expectSubscriptionsList,
}) => {
beforeEach(() => {
createComponent({
provide: {
usersPath,
subscriptions,
},
});
scenario | usersPath | shouldRenderSignInPage | shouldRenderSubscriptionsPage
${'user is not signed in'} | ${'/users'} | ${true} | ${false}
${'user is signed in'} | ${undefined} | ${false} | ${true}
`('when $scenario', ({ usersPath, shouldRenderSignInPage, shouldRenderSubscriptionsPage }) => {
beforeEach(() => {
createComponent({
provide: {
usersPath,
subscriptions: [mockSubscription],
},
});
});
it(`${expectSignInButton ? 'renders' : 'does not render'} sign in button`, () => {
expect(findSignInButton().exists()).toBe(expectSignInButton);
});
it(`${shouldRenderSignInPage ? 'renders' : 'does not render'} sign in page`, () => {
expect(findSignInPage().exists()).toBe(shouldRenderSignInPage);
if (shouldRenderSignInPage) {
expect(findSignInPage().props('hasSubscriptions')).toBe(true);
}
});
it(`${expectEmptyState ? 'renders' : 'does not render'} empty state`, () => {
expect(findEmptyState().exists()).toBe(expectEmptyState);
});
it(`${
expectNamespaceButton ? 'renders' : 'does not render'
} button to add namespace`, () => {
expect(findAddNamespaceButton().exists()).toBe(expectNamespaceButton);
});
it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => {
expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList);
});
},
);
it(`${
shouldRenderSubscriptionsPage ? 'renders' : 'does not render'
} subscriptions page`, () => {
expect(findSubscriptionsPage().exists()).toBe(shouldRenderSubscriptionsPage);
if (shouldRenderSubscriptionsPage) {
expect(findSubscriptionsPage().props('hasSubscriptions')).toBe(true);
}
});
});
it('renders UserLink component', () => {
createComponent({

View file

@ -11,11 +11,12 @@ jest.mock('~/jira_connect/subscriptions/utils');
describe('SignInButton', () => {
let wrapper;
const createComponent = () => {
const createComponent = ({ slots } = {}) => {
wrapper = shallowMount(SignInButton, {
propsData: {
usersPath: MOCK_USERS_PATH,
},
slots,
});
};
@ -29,6 +30,7 @@ describe('SignInButton', () => {
createComponent();
expect(findButton().exists()).toBe(true);
expect(findButton().text()).toBe(SignInButton.i18n.defaultButtonText);
});
describe.each`
@ -45,4 +47,12 @@ describe('SignInButton', () => {
expect(findButton().attributes('href')).toBe(expectedHref);
});
});
describe('with slot', () => {
const mockSlotContent = 'custom button content!';
it('renders slot content in button', () => {
createComponent({ slots: { default: mockSlotContent } });
expect(wrapper.text()).toMatchInterpolatedText(mockSlotContent);
});
});
});

View file

@ -0,0 +1,62 @@
import { mount } from '@vue/test-utils';
import SignInPage from '~/jira_connect/subscriptions/pages/sign_in.vue';
import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
import createStore from '~/jira_connect/subscriptions/store';
jest.mock('~/jira_connect/subscriptions/utils');
describe('SignInPage', () => {
let wrapper;
let store;
const findSignInButton = () => wrapper.findComponent(SignInButton);
const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
const createComponent = ({ provide, props } = {}) => {
store = createStore();
wrapper = mount(SignInPage, {
store,
provide,
propsData: props,
});
};
afterEach(() => {
wrapper.destroy();
});
describe('template', () => {
const mockUsersPath = '/test';
describe.each`
scenario | expectSubscriptionsList | signInButtonText
${'with subscriptions'} | ${true} | ${SignInPage.i18n.signinButtonTextWithSubscriptions}
${'without subscriptions'} | ${false} | ${SignInButton.i18n.defaultButtonText}
`('$scenario', ({ expectSubscriptionsList, signInButtonText }) => {
beforeEach(() => {
createComponent({
provide: {
usersPath: mockUsersPath,
},
props: {
hasSubscriptions: expectSubscriptionsList,
},
});
});
it(`renders sign in button with text ${signInButtonText}`, () => {
expect(findSignInButton().text()).toMatchInterpolatedText(signInButtonText);
});
it('renders sign in button with `usersPath` prop', () => {
expect(findSignInButton().props('usersPath')).toBe(mockUsersPath);
});
it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => {
expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList);
});
});
});
});

View file

@ -0,0 +1,56 @@
import { GlEmptyState } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions.vue';
import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
import createStore from '~/jira_connect/subscriptions/store';
describe('SubscriptionsPage', () => {
let wrapper;
let store;
const findAddNamespaceButton = () => wrapper.findComponent(AddNamespaceButton);
const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const createComponent = ({ props } = {}) => {
store = createStore();
wrapper = shallowMount(SubscriptionsPage, {
store,
propsData: props,
});
};
afterEach(() => {
wrapper.destroy();
});
describe('template', () => {
describe.each`
scenario | expectSubscriptionsList | expectEmptyState
${'with subscriptions'} | ${true} | ${false}
${'without subscriptions'} | ${false} | ${true}
`('$scenario', ({ expectEmptyState, expectSubscriptionsList }) => {
beforeEach(() => {
createComponent({
props: {
hasSubscriptions: expectSubscriptionsList,
},
});
});
it('renders button to add namespace', () => {
expect(findAddNamespaceButton().exists()).toBe(true);
});
it(`${expectEmptyState ? 'renders' : 'does not render'} empty state`, () => {
expect(findEmptyState().exists()).toBe(expectEmptyState);
});
it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => {
expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList);
});
});
});
});

View file

@ -215,6 +215,20 @@ RSpec.describe Blob do
end
end
describe '#symlink?' do
it 'is true for symlinks' do
symlink_blob = fake_blob(path: 'file', mode: '120000')
expect(symlink_blob.symlink?).to eq true
end
it 'is false for non-symlinks' do
non_symlink_blob = fake_blob(path: 'file', mode: '100755')
expect(non_symlink_blob.symlink?).to eq false
end
end
describe '#extension' do
it 'returns the extension' do
blob = fake_blob(path: 'file.md')

View file

@ -265,22 +265,37 @@ RSpec.describe Ci::Runner do
it_behaves_like '.belonging_to_parent_group_of_project'
end
describe '.owned_or_instance_wide' do
it 'returns a globally shared, a project specific and a group specific runner' do
# group specific
group = create(:group)
project = create(:project, group: group)
group_runner = create(:ci_runner, :group, groups: [group])
context 'with existing system wide, group and project runners' do
# group specific
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) }
# project specific
project_runner = create(:ci_runner, :project, projects: [project])
# project specific
let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) }
# globally shared
shared_runner = create(:ci_runner, :instance)
# globally shared
let_it_be(:shared_runner) { create(:ci_runner, :instance) }
expect(described_class.owned_or_instance_wide(project.id)).to contain_exactly(
group_runner, project_runner, shared_runner
)
describe '.owned_or_instance_wide' do
subject { described_class.owned_or_instance_wide(project.id) }
it 'returns a globally shared, a project specific and a group specific runner' do
is_expected.to contain_exactly(group_runner, project_runner, shared_runner)
end
end
describe '.group_or_instance_wide' do
subject { described_class.group_or_instance_wide(group) }
before do
# Ensure the project runner is instantiated
project_runner
end
it 'returns a globally shared and a group specific runner' do
is_expected.to contain_exactly(group_runner, shared_runner)
end
end
end

View file

@ -1026,7 +1026,8 @@ RSpec.describe API::Ci::Runners do
get api("/groups/#{group.id}/runners", user)
expect(json_response).to match_array([
a_hash_including('description' => 'Group runner A', 'active' => true, 'paused' => false)
a_hash_including('description' => 'Group runner A', 'active' => true, 'paused' => false),
a_hash_including('description' => 'Shared runner', 'active' => true, 'paused' => false)
])
end
@ -1039,6 +1040,14 @@ RSpec.describe API::Ci::Runners do
])
end
it 'returns instance runners when instance_type is specified' do
get api("/groups/#{group.id}/runners?type=instance_type", user)
expect(json_response).to match_array([
a_hash_including('description' => 'Shared runner')
])
end
it 'returns empty result when type does not match' do
get api("/groups/#{group.id}/runners?type=project_type", user)

View file

@ -65,7 +65,7 @@ RSpec.describe Branches::CreateService do
allow(project.repository).to receive(:add_branch).and_raise(pre_receive_error)
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
pre_receive_error,
pre_receive_message: raw_message,
branch_name: 'new-feature',

View file

@ -4,13 +4,14 @@ module FakeBlobHelpers
class FakeBlob
include BlobLike
attr_reader :path, :size, :data, :lfs_oid, :lfs_size
attr_reader :path, :size, :data, :lfs_oid, :lfs_size, :mode
def initialize(path: 'file.txt', size: 1.kilobyte, data: 'foo', binary: false, lfs: nil)
def initialize(path: 'file.txt', size: 1.kilobyte, data: 'foo', binary: false, lfs: nil, mode: nil)
@path = path
@size = size
@data = data
@binary = binary
@mode = mode
@lfs_pointer = lfs.present?
if @lfs_pointer

View file

@ -12,7 +12,7 @@ ifdef SOURCE_DATE_EPOCH
else
BUILD_TIME := $(shell date -u "$(DATE_FMT)")
endif
GOBUILD := go build -ldflags "-X main.Version=$(VERSION_STRING) -X main.BuildTime=$(BUILD_TIME)"
GO_BUILD_GENERIC_LDFLAGS := -X main.Version=$(VERSION_STRING) -X main.BuildTime=$(BUILD_TIME)
GITALY := tmp/tests/gitaly/_build/bin/gitaly
GITALY_PID_FILE := gitaly.pid
EXE_ALL := gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse
@ -30,31 +30,35 @@ define message
@echo "### $(1)"
endef
# To compute a unique and deterministic value for GNU build-id, we build the Go binary a second time.
# From the first build, we extract its unique and deterministic Go build-id, and use that to derive
# a comparably unique and deterministic GNU build-id to inject into the final binary.
# If we cannot extract a Go build-id, we punt and fallback to using a random 32-byte hex string.
# This fallback is unique but non-deterministic. Uniqueness is critical, because the GNU build-id
# can be used as a cache key in a build cache. Without the fallback, we risk cache key collisions.
## Skip generation of the GNU build ID if set to speed up builds.
WITHOUT_BUILD_ID ?=
.NOTPARALLEL:
.PHONY: all
all: clean-build $(EXE_ALL)
.PHONY: gitlab-resize-image
gitlab-resize-image:
.PHONY: gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata
gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata:
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
.PHONY: gitlab-zip-cat
gitlab-zip-cat:
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
.PHONY: gitlab-zip-metadata
gitlab-zip-metadata:
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
ifndef WITHOUT_BUILD_ID
go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS) -B 0x$$(_support/make-gnu-build-id.sh $(BUILD_DIR)/$@)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)/cmd/$@
endif
.PHONY: gitlab-workhorse
gitlab-workhorse:
$(call message,Building $@)
$(GOBUILD) -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
ifndef WITHOUT_BUILD_ID
go build -ldflags "$(GO_BUILD_GENERIC_LDFLAGS) -B 0x$$(_support/make-gnu-build-id.sh $(BUILD_DIR)/$@)" -tags "$(BUILD_TAGS)" -o $(BUILD_DIR)/$@ $(PKG)
endif
.PHONY: install
install: $(EXE_ALL)

View file

@ -0,0 +1,30 @@
#!/bin/sh
main()
{
GO_BINARY=$1
if [ $# -ne 1 ] || [ ! -f $GO_BINARY ] ; then
fail "Usage: $0 [path_to_go_binary]"
fi
GO_BUILD_ID=$( go tool buildid "$GO_BINARY" || openssl rand -hex 32 )
if [ -z "$GO_BUILD_ID" ] ; then
fail "ERROR: Could not extract Go build-id or generate a random hex string."
fi
GNU_BUILD_ID=$( echo $GO_BUILD_ID | sha1sum | cut -d' ' -f1 )
if [ -z "$GNU_BUILD_ID" ] ; then
fail "ERROR: Could not generate a GNU build-id"
fi
echo "$GNU_BUILD_ID"
}
fail()
{
echo "$@" 1>&2
exit 1
}
main "$@"

View file

@ -962,15 +962,15 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.2.0.tgz#95cf58d6ae634d535145159f08f5cff6241d4013"
integrity sha512-mCwR3KfNPsxRoojtTjMIZwdd4FFlBh5DlR9AeodP+7+k8rILdWGYxTZbJMPNXoPbZx16R94nG8c5bR7toD4QBw==
"@gitlab/ui@33.1.0":
version "33.1.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-33.1.0.tgz#45ac2e6362546530b5756b1973f97f74a9c920da"
integrity sha512-kSpnGx7UjWxl0s6RBl9njhthD2tSyLHoVd3Q/E3WEE9gdw8VSa4tEeI2srD9eGl2npd/VUvO7tNIXzk5NpjLZg==
"@gitlab/ui@34.0.0":
version "34.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-34.0.0.tgz#0fe9574df2c38aeb63add94e4549ed4e65975ef8"
integrity sha512-BFh3x+GCqWAoWhNJhJUunW3eHQLQkBOTBwZFJWSS+1+9ZtetqU3t0/OoqYjJuyTsqdra7A/e6BZsU0j7CnbY+Q==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.20.1"
copy-to-clipboard "^3.0.8"
dompurify "^2.3.4"
dompurify "^2.3.5"
echarts "^5.2.1"
highlight.js "^10.6.0"
iframe-resizer "^4.3.2"
@ -4890,7 +4890,7 @@ dompurify@2.3.4:
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.4.tgz#1cf5cf0105ccb4debdf6db162525bd41e6ddacc6"
integrity sha512-6BVcgOAVFXjI0JTjEvZy901Rghm+7fDQOrNIcxB4+gdhj6Kwp6T9VBhBY/AbagKHJocRkDYGd6wvI+p4/10xtQ==
dompurify@^2.3.4, dompurify@^2.3.5:
dompurify@^2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.5.tgz#c83ed5a3ae5ce23e52efe654ea052ffb358dd7e3"
integrity sha512-kD+f8qEaa42+mjdOpKeztu9Mfx5bv9gVLO6K9jRx4uGvh6Wv06Srn4jr1wPNY2OOUGGSKHNFN+A8MA3v0E0QAQ==