Merge branch 'master' into matbaj/gitlab-ce-add-inherit-command
This commit is contained in:
commit
6a88ffb412
|
@ -75,7 +75,7 @@ stages:
|
|||
|
||||
.use-mysql: &use-mysql
|
||||
services:
|
||||
- mysql:latest
|
||||
- mysql:5.7
|
||||
- redis:alpine
|
||||
|
||||
.rails5-variables: &rails5-variables
|
||||
|
|
|
@ -143,7 +143,7 @@ Lint/MissingCopEnableDirective:
|
|||
Lint/NestedPercentLiteral:
|
||||
Exclude:
|
||||
- 'lib/gitlab/git/repository.rb'
|
||||
- 'spec/support/email_format_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/email_format_shared_examples.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/ReturnInVoidContext:
|
||||
|
@ -195,8 +195,8 @@ Naming/HeredocDelimiterCase:
|
|||
- 'spec/lib/gitlab/diff/parser_spec.rb'
|
||||
- 'spec/lib/json_web_token/rsa_token_spec.rb'
|
||||
- 'spec/models/commit_spec.rb'
|
||||
- 'spec/support/repo_helpers.rb'
|
||||
- 'spec/support/seed_repo.rb'
|
||||
- 'spec/support/helpers/repo_helpers.rb'
|
||||
- 'spec/support/helpers/seed_repo.rb'
|
||||
|
||||
# Offense count: 112
|
||||
# Configuration parameters: Blacklist.
|
||||
|
@ -496,7 +496,7 @@ Style/EmptyLiteral:
|
|||
- 'spec/lib/gitlab/request_context_spec.rb'
|
||||
- 'spec/lib/gitlab/workhorse_spec.rb'
|
||||
- 'spec/requests/api/jobs_spec.rb'
|
||||
- 'spec/support/chat_slash_commands_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/chat_slash_commands_shared_examples.rb'
|
||||
|
||||
# Offense count: 102
|
||||
# Cop supports --auto-correct.
|
||||
|
|
235
CHANGELOG.md
235
CHANGELOG.md
|
@ -2,6 +2,241 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 10.7.1 (2018-04-23)
|
||||
|
||||
### Fixed (11 changes)
|
||||
|
||||
- [API] Fix URLs in the `Link` header for `GET /projects/:id/repository/contributors` when no value is passed for `order_by` or `sort`. !18393
|
||||
- Fix a case with secret variables being empty sometimes. !18400
|
||||
- Fix `Trace::HttpIO` can not render multi-byte chars. !18417
|
||||
- Fix specifying a non-default ref when requesting an archive using the legacy URL. !18468
|
||||
- Respect visibility options and description when importing project from template. !18473
|
||||
- Removes 'No Job log' message from build trace. !18523
|
||||
- Align action icons in pipeline graph.
|
||||
- Fix direct_upload when records with null file_store are used.
|
||||
- Removed alert box in IDE when redirecting to new merge request.
|
||||
- Fixed IDE not loading for sub groups.
|
||||
- Fixed IDE not showing loading state when tree is loading.
|
||||
|
||||
### Performance (4 changes)
|
||||
|
||||
- Validate project path prior to hitting the database. !18322
|
||||
- Add index to file_store on ci_job_artifacts. !18444
|
||||
- Fix N+1 queries when loading participants for a commit note.
|
||||
- Support Markdown rendering using multiple projects.
|
||||
|
||||
### Added (1 change)
|
||||
|
||||
- Add an API endpoint to download git repository snapshots. !18173
|
||||
|
||||
|
||||
## 10.7.0 (2018-04-22)
|
||||
|
||||
### Security (6 changes, 2 of them are from the community)
|
||||
|
||||
- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
|
||||
- Update ruby-saml to 1.7.2 and omniauth-saml to 1.10.0. !17734 (Takuya Noguchi)
|
||||
- Update rack-protection to 2.0.1. !17835 (Takuya Noguchi)
|
||||
- Adds confidential notes channel for Slack/Mattermost.
|
||||
- Fix XSS on diff view stored on filenames.
|
||||
- Fix GitLab Auth0 integration signing in the wrong user.
|
||||
|
||||
### Fixed (65 changes, 20 of them are from the community)
|
||||
|
||||
- File uploads in remote storage now support project renaming. !4597
|
||||
- Fixed bug in dropdown selector when selecting the same selection again. !14631 (bitsapien)
|
||||
- Fixed group deletion linked to Mattermost. !16209 (Julien Millau)
|
||||
- Create commit API and Web IDE obey LFS filters. !16718
|
||||
- Set breadcrumb for admin/runners/show. !17431 (Takuya Noguchi)
|
||||
- Enable restore rake task to handle nested storage directories. !17516 (Balasankar C)
|
||||
- Fix hover style of dropdown items in the right sidebar. !17519
|
||||
- Improve empty state for canceled job. !17646
|
||||
- Fix generated URL when listing repoitories for import. !17692
|
||||
- Use singular in the diff stats if only one line has been changed. !17697 (Jan Beckmann)
|
||||
- Long instance urls do not overflow anymore during project creation. !17717
|
||||
- Fix importing multiple assignees from GitLab export. !17718
|
||||
- Correct copy text for the promote milestone and label modals. !17726
|
||||
- Fix search results stripping last endline when parsing the results. !17777 (Jasper Maes)
|
||||
- Add read-only banner to all pages. !17798
|
||||
- Fix viewing diffs on old merge requests. !17805
|
||||
- Fix forking to subgroup via API when namespace is given by name. !17815 (Jan Beckmann)
|
||||
- Fix UI breakdown for Create merge request button. !17821 (Takuya Noguchi)
|
||||
- Unify format for nested non-task lists. !17823 (Takuya Noguchi)
|
||||
- UX re-design branch items with flexbox. !17832 (Takuya Noguchi)
|
||||
- Use porcelain commit lookup method on CI::CreatePipelineService. !17911
|
||||
- Update dashboard milestones breadcrumb link. !17933 (George Tsiolis)
|
||||
- Deleting a MR you are assigned to should decrements counter. !17951 (m b)
|
||||
- Update no repository placeholder. !17964 (George Tsiolis)
|
||||
- Drop JSON response in Project Milestone along with avoiding error. !17977 (Takuya Noguchi)
|
||||
- Fix personal access token clipboard button style. !17978 (Fabian Schneider)
|
||||
- Avoid validation errors when running the Pages domain verification service. !17992
|
||||
- Project creation will now raise an error if a service template is invalid. !18013
|
||||
- Add better LDAP connection handling. !18039
|
||||
- Fix autolinking URLs containing ampersands. !18045
|
||||
- Fix exceptions raised when migrating pipeline stages in the background. !18076
|
||||
- Always display Labels section in issuable sidebar, even when the project has no labels. !18081 (Branka Martinovic)
|
||||
- Fixed gitlab:uploads:migrate task ignoring some uploads. !18082
|
||||
- Fixed gitlab:uploads:migrate task failing for Groups' avatar. !18088
|
||||
- Increase dropdown width in pipeline graph & center action icon. !18089
|
||||
- Fix `JobsController#raw` endpoint can not read traces in database. !18101
|
||||
- Fix `gitlab-rake gitlab:two_factor:disable_for_all_users`. !18154
|
||||
- Adjust 404's for LegacyDiffNote discussion rendering. !18201
|
||||
- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert)
|
||||
- Prioritize weight over title when sorting charts. !18233
|
||||
- Verify that deploy token has valid access when pulling container registry image. !18260
|
||||
- Stop redirecting the page in pipeline main actions.
|
||||
- Fixed IDE button opening the wrong URL in tree list.
|
||||
- Ensure hooks run when a deploy key without a user pushes.
|
||||
- Fix 404 in group boards when moving issue between lists.
|
||||
- Display state indicator for issuable references in non-project scope (e.g. when referencing issuables from group scope).
|
||||
- Add missing port to artifact links.
|
||||
- Fix data race between ObjectStorage background_upload and Pages publishing.
|
||||
- Fixes unresolved discussions rendering the error state instead of the diff.
|
||||
- Don't show Jump to Discussion button on Issues.
|
||||
- Fix bug rendering group icons when forking.
|
||||
- Automatically cleanup stale worktrees and lock files upon a push.
|
||||
- Use the GitLab version as part of the appearances cache key.
|
||||
- Fix Firefox stealing formatting characters on issue notes.
|
||||
- Include matching branches and tags in protected branches / tags count. (Jan Beckmann)
|
||||
- Fix 500 error when a merge request from a fork has conflicts and has not yet been updated.
|
||||
- Test if remote repository exists when importing wikis.
|
||||
- Hide emoji popup after multiple spaces. (Jan Beckmann)
|
||||
- Fix relative uri when "#" is in branch name. (Jan)
|
||||
- Escape Markdown characters properly when using autocomplete.
|
||||
- Ignore project internal references in group context.
|
||||
- Fix finding wiki file when Gitaly is enabled.
|
||||
- Fix listing commit branch/tags that contain special characters.
|
||||
- Ensure internal users (ghost, support bot) get assigned a namespace.
|
||||
- Fix links to subdirectories of a directory with a plus character in its path.
|
||||
|
||||
### Deprecated (1 change)
|
||||
|
||||
- Remove support for legacy tar.gz pages artifacts. !18090
|
||||
|
||||
### Changed (22 changes, 2 of them are from the community)
|
||||
|
||||
- Add yellow favicon when `CANARY=true` to differientate canary environment. !12477
|
||||
- Use human readable value build_timeout in Project. !17386
|
||||
- Improved visual styles and consistency for commit hash and possible actions across commit lists. !17406
|
||||
- Don't create permanent redirect routes. !17521
|
||||
- Add empty repo check before running AutoDevOps pipeline. !17605
|
||||
- Update wording to specify create/manage project vs group labels in labels dropdown. !17640
|
||||
- Add tooltips to icons in lists of issues and merge requests. !17700
|
||||
- Change avatar error message to include allowed file formats. !17747 (Fabian Schneider)
|
||||
- Polish design for verifying domains. !17767
|
||||
- Move email footer info to a single line. !17916
|
||||
- Add average and maximum summary statistics to the prometheus dashboard. !17921
|
||||
- Add additional cluster usage metrics to usage ping. !17922
|
||||
- Move 'Registry' after 'CI/CD' in project navigation sidebar. !18018 (Elias Werberich)
|
||||
- Redesign application settings to match project settings. !18019
|
||||
- Allow HTTP(s) when git request is made by GitLab CI. !18021
|
||||
- Added hover background color to IDE file list rows.
|
||||
- Make project avatar in IDE consistent with the rest of GitLab.
|
||||
- Show issues of subgroups in group-level issue board.
|
||||
- Repository checksum calculation is handled by Gitaly when feature is enabled.
|
||||
- Allow viewing timings for AJAX requests in the performance bar.
|
||||
- Fixes remove source branch checkbox being visible when user cannot remove the branch.
|
||||
- Make /-/ delimiter optional for search endpoints.
|
||||
|
||||
### Performance (24 changes, 11 of them are from the community)
|
||||
|
||||
- Move AssigneeTitle vue component. !17397 (George Tsiolis)
|
||||
- Move TimeTrackingCollapsedState vue component. !17399 (George Tsiolis)
|
||||
- Move MemoryGraph and MemoryUsage vue components. !17533 (George Tsiolis)
|
||||
- Move UnresolvedDiscussions vue component. !17538 (George Tsiolis)
|
||||
- Move NothingToMerge vue component. !17544 (George Tsiolis)
|
||||
- Move ShaMismatch vue component. !17546 (George Tsiolis)
|
||||
- Stop caching highlighted diffs in Redis unnecessarily. !17746
|
||||
- Add i18n and update specs for ShaMismatch vue component. !17870 (George Tsiolis)
|
||||
- Update spec import path for vue mount component helper. !17880 (George Tsiolis)
|
||||
- Move TimeTrackingComparisonPane vue component. !17931 (George Tsiolis)
|
||||
- Improves the performance of projects list page. !17934
|
||||
- Remove N+1 query for Noteable association. !17956
|
||||
- Improve performance of loading issues with lots of references to merge requests. !17986
|
||||
- Reuse root_ref_hash for performance on Branches. !17998 (Takuya Noguchi)
|
||||
- Update asciidoctor-plantuml to 0.0.8. !18022 (Takuya Noguchi)
|
||||
- Cache personal projects count. !18197
|
||||
- Reduce complexity of issuable finder query. !18219
|
||||
- Reduce number of queries when viewing a merge request.
|
||||
- Free open file descriptors and libgit2 buffers in UpdatePagesService.
|
||||
- Memoize Git::Repository#has_visible_content?.
|
||||
- Require at least one filter when listing issues or merge requests on dashboard page.
|
||||
- lazy load diffs on merge request discussions.
|
||||
- Bulk deleting refs is handled by Gitaly by default.
|
||||
- ListCommitsByOid is executed by Gitaly by default.
|
||||
|
||||
### Added (38 changes, 7 of them are from the community)
|
||||
|
||||
- Add HTTPS-only pages. !16273 (rfwatson)
|
||||
- adds closed by informations in issue api. !17042 (haseebeqx)
|
||||
- Projects and groups badges settings UI. !17114
|
||||
- Add per-runner configured job timeout. !17221
|
||||
- Add alternate archive route for simplified packaging. !17225
|
||||
- Add support for pipeline variables expressions in only/except. !17316
|
||||
- Add object storage support for LFS objects, CI artifacts, and uploads. !17358
|
||||
- Added confirmation modal for changing username. !17405
|
||||
- Implement foreground verification of CI artifacts. !17578
|
||||
- Extend API for exporting a project with direct upload URL. !17686
|
||||
- Move ci/lint under project's namespace. !17729
|
||||
- Add Total CPU/Memory consumption metrics for Kubernetes. !17731
|
||||
- Adds the option to the project export API to override the project description and display GitLab export description once imported. !17744
|
||||
- Port direct upload of LFS artifacts from EE. !17752
|
||||
- Adds support for OmniAuth JWT provider. !17774
|
||||
- Display error message on job's tooltip if this one fails. !17782
|
||||
- Add 'Assigned Issues' and 'Assigned Merge Requests' as dashboard view choices for users. !17860 (Elias Werberich)
|
||||
- Extend API for importing a project export with overwrite support. !17883
|
||||
- Create Deploy Tokens to allow permanent access to repository and registry. !17894
|
||||
- Detect commit message trailers and link users properly to their accounts on Gitlab. !17919 (cousine)
|
||||
- Adds cancel btn to new pages domain page. !18026 (Jacopo Beschi @jacopo-beschi)
|
||||
- API: Add parameter merge_method to projects. !18031 (Jan Beckmann)
|
||||
- Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436. !18036
|
||||
- Allow overriding params on project import through API. !18086
|
||||
- Support LFS objects when importing/exporting GitLab project archives. !18115
|
||||
- Store sha256 checksum of artifact metadata. !18149
|
||||
- Limit the number of failed logins when using LDAP for authentication. !43525
|
||||
- Allow assigning and filtering issuables by ancestor group labels.
|
||||
- Include subgroup issues when searching for group issues using the API.
|
||||
- Allow to store uploads by default on Object Storage.
|
||||
- Add slash command for moving issues. (Adam Pahlevi)
|
||||
- Render MR commit SHA instead "diffs" when viable.
|
||||
- Send @mention notifications even if a user has explicitly unsubscribed from item.
|
||||
- Add support for Sidekiq JSON logging.
|
||||
- Add Gitaly call details to performance bar.
|
||||
- Add support for patch link extension for commit links on GitLab Flavored Markdown.
|
||||
- Allow feature gates to be removed through the API.
|
||||
- Allow merge requests related to a commit to be found via API.
|
||||
|
||||
### Other (27 changes, 11 of them are from the community)
|
||||
|
||||
- Send notification emails when push to a merge request. !7610 (YarNayar)
|
||||
- Rename modal.vue to deprecated_modal.vue. !17438
|
||||
- Atomic generation of internal ids for issues. !17580
|
||||
- Use object ID to prevent duplicate keys Vue warning on Issue Boards page during development. !17682
|
||||
- Update foreman from 0.78.0 to 0.84.0. !17690 (Takuya Noguchi)
|
||||
- Add realtime pipeline status for adding/viewing files. !17705
|
||||
- Update documentation to reflect current minimum required versions of node and yarn. !17706
|
||||
- Update knapsack to 1.16.0. !17735 (Takuya Noguchi)
|
||||
- Update CI services documnetation. !17749
|
||||
- Added i18n support for the prometheus memory widget. !17753
|
||||
- Use specific names for filtered CI variable controller parameters. !17796
|
||||
- Apply NestingDepth (level 5) (framework/dropdowns.scss). !17820 (Takuya Noguchi)
|
||||
- Clean up selectors in framework/header.scss. !17822 (Takuya Noguchi)
|
||||
- Bump `state_machines-activerecord` to 0.5.1. !17924 (blackst0ne)
|
||||
- Increase the memory limits used in the unicorn killer. !17948
|
||||
- Replace the spinach test with an rspec analog. !17950 (blackst0ne)
|
||||
- Remove unused index from events table. !18014
|
||||
- Make all workhorse gitaly calls opt-out, take 2. !18043
|
||||
- Update brakeman 3.6.1 to 4.2.1. !18122 (Takuya Noguchi)
|
||||
- Replace the `project/issues/labels.feature` spinach test with an rspec analog. !18126 (blackst0ne)
|
||||
- Bump html-pipeline to 2.7.1. !18132 (@blackst0ne)
|
||||
- Remove test_ci rake task. !18139 (Takuya Noguchi)
|
||||
- Add documentation for Pipelines failure reasons. !18352
|
||||
- Improve JIRA event descriptions.
|
||||
- Add query counts to profiler output.
|
||||
- Move Sidekiq exporter logs to log/sidekiq_exporter.log.
|
||||
- Upgrade Gitaly to upgrade its charlock_holmes.
|
||||
|
||||
|
||||
## 10.6.4 (2018-04-09)
|
||||
|
||||
### Fixed (8 changes, 1 of them is from the community)
|
||||
|
|
|
@ -26,7 +26,9 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
|
|||
- [Type labels (~"feature proposal", ~bug, ~customer, etc.)](#type-labels-feature-proposal-bug-customer-etc)
|
||||
- [Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.)](#subject-labels-wiki-container-registry-ldap-api-etc)
|
||||
- [Team labels (~"CI/CD", ~Discussion, ~Edge, ~Platform, etc.)](#team-labels-cicd-discussion-edge-platform-etc)
|
||||
- [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#priority-labels-deliverable-stretch-next-patch-release)
|
||||
- [Milestone labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#milestone-labels-deliverable-stretch-next-patch-release)
|
||||
- [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-priority-labels-p1-p2-p3-etc)
|
||||
- [Severity labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-severity-labels-s1-s2-s3-etc)
|
||||
- [Label for community contributors (~"Accepting Merge Requests")](#label-for-community-contributors-accepting-merge-requests)
|
||||
- [Implement design & UI elements](#implement-design-ui-elements)
|
||||
- [Issue tracker](#issue-tracker)
|
||||
|
@ -127,6 +129,8 @@ Most issues will have labels for at least one of the following:
|
|||
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
|
||||
- Team: ~"CI/CD", ~Discussion, ~Edge, ~Platform, etc.
|
||||
- Milestone: ~Deliverable, ~Stretch, ~"Next Patch Release"
|
||||
- Priority: ~P1, ~P2, ~P3, ~P4
|
||||
- Severity: ~S1, ~S2, ~S3, ~S4
|
||||
|
||||
All labels, their meaning and priority are defined on the
|
||||
[labels page][labels-page].
|
||||
|
@ -210,7 +214,7 @@ This label documents the planned timeline & urgency which is used to measure aga
|
|||
|
||||
| Label | Meaning | Estimate time to fix | Guidance |
|
||||
|-------|-----------------|------------------------------------------------------------------|----------|
|
||||
| ~P1 | Urgent Priority | The current release | |
|
||||
| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com | |
|
||||
| ~P2 | High Priority | The next release | |
|
||||
| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) | |
|
||||
| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) | The issue is prominent but does not impact user workflow and a workaround is documented |
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.95.0
|
||||
0.96.1
|
||||
|
|
|
@ -178,7 +178,7 @@ GEM
|
|||
docile (1.1.5)
|
||||
domain_name (0.5.20170404)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
doorkeeper (4.3.1)
|
||||
doorkeeper (4.3.2)
|
||||
railties (>= 4.2)
|
||||
doorkeeper-openid_connect (1.3.0)
|
||||
doorkeeper (~> 4.3)
|
||||
|
|
|
@ -113,6 +113,8 @@ class List {
|
|||
issue.id = data.id;
|
||||
issue.iid = data.iid;
|
||||
issue.project = data.project;
|
||||
issue.path = data.real_path;
|
||||
issue.referencePath = data.reference_path;
|
||||
|
||||
if (this.issuesSize > 1) {
|
||||
const moveBeforeId = this.issues[1].id;
|
||||
|
|
|
@ -84,20 +84,21 @@ export default class CreateMergeRequestDropdown {
|
|||
if (data.can_create_branch) {
|
||||
this.available();
|
||||
this.enable();
|
||||
this.updateBranchName(data.suggested_branch_name);
|
||||
|
||||
if (!this.droplabInitialized) {
|
||||
this.droplabInitialized = true;
|
||||
this.initDroplab();
|
||||
this.bindEvents();
|
||||
}
|
||||
} else if (data.has_related_branch) {
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.unavailable();
|
||||
this.disable();
|
||||
Flash('Failed to check if a new branch can be created.');
|
||||
Flash(__('Failed to check related branches.'));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -409,13 +410,16 @@ export default class CreateMergeRequestDropdown {
|
|||
this.unavailableButton.classList.remove('hide');
|
||||
}
|
||||
|
||||
updateBranchName(suggestedBranchName) {
|
||||
this.branchInput.value = suggestedBranchName;
|
||||
this.updateCreatePaths('branch', suggestedBranchName);
|
||||
}
|
||||
|
||||
updateInputState(target, ref, result) {
|
||||
// target - 'branch' or 'ref' - which the input field we are searching a ref for.
|
||||
// ref - string - what a user typed.
|
||||
// result - string - what has been found on backend.
|
||||
|
||||
const pathReplacement = `$1${ref}`;
|
||||
|
||||
// If a found branch equals exact the same text a user typed,
|
||||
// that means a new branch cannot be created as it already exists.
|
||||
if (ref === result) {
|
||||
|
@ -426,18 +430,12 @@ export default class CreateMergeRequestDropdown {
|
|||
this.refIsValid = true;
|
||||
this.refInput.dataset.value = ref;
|
||||
this.showAvailableMessage('ref');
|
||||
this.createBranchPath = this.createBranchPath.replace(this.regexps.ref.createBranchPath,
|
||||
pathReplacement);
|
||||
this.createMrPath = this.createMrPath.replace(this.regexps.ref.createMrPath,
|
||||
pathReplacement);
|
||||
this.updateCreatePaths(target, ref);
|
||||
}
|
||||
} else if (target === 'branch') {
|
||||
this.branchIsValid = true;
|
||||
this.showAvailableMessage('branch');
|
||||
this.createBranchPath = this.createBranchPath.replace(this.regexps.branch.createBranchPath,
|
||||
pathReplacement);
|
||||
this.createMrPath = this.createMrPath.replace(this.regexps.branch.createMrPath,
|
||||
pathReplacement);
|
||||
this.updateCreatePaths(target, ref);
|
||||
} else {
|
||||
this.refIsValid = false;
|
||||
this.refInput.dataset.value = ref;
|
||||
|
@ -457,4 +455,15 @@ export default class CreateMergeRequestDropdown {
|
|||
this.disableCreateAction();
|
||||
}
|
||||
}
|
||||
|
||||
// target - 'branch' or 'ref'
|
||||
// ref - string - the new value to use as branch or ref
|
||||
updateCreatePaths(target, ref) {
|
||||
const pathReplacement = `$1${ref}`;
|
||||
|
||||
this.createBranchPath = this.createBranchPath.replace(this.regexps[target].createBranchPath,
|
||||
pathReplacement);
|
||||
this.createMrPath = this.createMrPath.replace(this.regexps[target].createMrPath,
|
||||
pathReplacement);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1427,7 +1427,7 @@ export default class Notes {
|
|||
const { discussion_html } = data;
|
||||
const lines = $(discussion_html).find('.line_holder');
|
||||
lines.addClass('fade-in');
|
||||
$container.find('tbody').prepend(lines);
|
||||
$container.find('.diff-content > table > tbody').prepend(lines);
|
||||
const fileHolder = $container.find('.file-holder');
|
||||
$container.find('.line-holder-placeholder').remove();
|
||||
syntaxHighlight(fileHolder);
|
||||
|
|
|
@ -19,7 +19,7 @@ function getSystemDate(systemUtcOffsetSeconds) {
|
|||
const date = new Date();
|
||||
const localUtcOffsetMinutes = 0 - date.getTimezoneOffset();
|
||||
const systemUtcOffsetMinutes = systemUtcOffsetSeconds / 60;
|
||||
date.setMinutes((date.getMinutes() - localUtcOffsetMinutes) + systemUtcOffsetMinutes);
|
||||
date.setMinutes(date.getMinutes() - localUtcOffsetMinutes + systemUtcOffsetMinutes);
|
||||
return date;
|
||||
}
|
||||
|
||||
|
@ -35,18 +35,36 @@ function formatTooltipText({ date, count }) {
|
|||
return `${contribText}<br />${dateDayName} ${dateText}`;
|
||||
}
|
||||
|
||||
const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]);
|
||||
const initColorKey = () =>
|
||||
d3
|
||||
.scaleLinear()
|
||||
.range(['#acd5f2', '#254e77'])
|
||||
.domain([0, 3]);
|
||||
|
||||
export default class ActivityCalendar {
|
||||
constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0) {
|
||||
constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0, firstDayOfWeek = 0) {
|
||||
this.calendarActivitiesPath = calendarActivitiesPath;
|
||||
this.clickDay = this.clickDay.bind(this);
|
||||
this.currentSelectedDate = '';
|
||||
this.daySpace = 1;
|
||||
this.daySize = 15;
|
||||
this.daySizeWithSpace = this.daySize + (this.daySpace * 2);
|
||||
this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
this.daySizeWithSpace = this.daySize + this.daySpace * 2;
|
||||
this.monthNames = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec',
|
||||
];
|
||||
this.months = [];
|
||||
this.firstDayOfWeek = firstDayOfWeek;
|
||||
|
||||
// Loop through the timestamps to create a group of objects
|
||||
// The group of objects will be grouped based on the day of the week they are
|
||||
|
@ -70,7 +88,7 @@ export default class ActivityCalendar {
|
|||
|
||||
// Create a new group array if this is the first day of the week
|
||||
// or if is first object
|
||||
if ((day === 0 && i !== 0) || i === 0) {
|
||||
if ((day === this.firstDayOfWeek && i !== 0) || i === 0) {
|
||||
this.timestampsTmp.push([]);
|
||||
group += 1;
|
||||
}
|
||||
|
@ -109,21 +127,30 @@ export default class ActivityCalendar {
|
|||
}
|
||||
|
||||
renderSvg(container, group) {
|
||||
const width = ((group + 1) * this.daySizeWithSpace) + this.getExtraWidthPadding(group);
|
||||
return d3.select(container)
|
||||
const width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group);
|
||||
return d3
|
||||
.select(container)
|
||||
.append('svg')
|
||||
.attr('width', width)
|
||||
.attr('height', 167)
|
||||
.attr('class', 'contrib-calendar');
|
||||
.attr('width', width)
|
||||
.attr('height', 167)
|
||||
.attr('class', 'contrib-calendar');
|
||||
}
|
||||
|
||||
dayYPos(day) {
|
||||
return this.daySizeWithSpace * ((day + 7 - this.firstDayOfWeek) % 7);
|
||||
}
|
||||
|
||||
renderDays() {
|
||||
this.svg.selectAll('g').data(this.timestampsTmp).enter().append('g')
|
||||
this.svg
|
||||
.selectAll('g')
|
||||
.data(this.timestampsTmp)
|
||||
.enter()
|
||||
.append('g')
|
||||
.attr('transform', (group, i) => {
|
||||
_.each(group, (stamp, a) => {
|
||||
if (a === 0 && stamp.day === 0) {
|
||||
const month = stamp.date.getMonth();
|
||||
const x = (this.daySizeWithSpace * i) + 1 + this.daySizeWithSpace;
|
||||
const x = this.daySizeWithSpace * i + 1 + this.daySizeWithSpace;
|
||||
const lastMonth = _.last(this.months);
|
||||
if (
|
||||
lastMonth == null ||
|
||||
|
@ -133,86 +160,113 @@ export default class ActivityCalendar {
|
|||
}
|
||||
}
|
||||
});
|
||||
return `translate(${(this.daySizeWithSpace * i) + 1 + this.daySizeWithSpace}, 18)`;
|
||||
return `translate(${this.daySizeWithSpace * i + 1 + this.daySizeWithSpace}, 18)`;
|
||||
})
|
||||
.selectAll('rect')
|
||||
.data(stamp => stamp)
|
||||
.enter()
|
||||
.append('rect')
|
||||
.attr('x', '0')
|
||||
.attr('y', stamp => this.daySizeWithSpace * stamp.day)
|
||||
.attr('width', this.daySize)
|
||||
.attr('height', this.daySize)
|
||||
.attr('fill', stamp => (
|
||||
stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed'
|
||||
))
|
||||
.attr('title', stamp => formatTooltipText(stamp))
|
||||
.attr('class', 'user-contrib-cell js-tooltip')
|
||||
.attr('data-container', 'body')
|
||||
.on('click', this.clickDay);
|
||||
.data(stamp => stamp)
|
||||
.enter()
|
||||
.append('rect')
|
||||
.attr('x', '0')
|
||||
.attr('y', stamp => this.dayYPos(stamp.day))
|
||||
.attr('width', this.daySize)
|
||||
.attr('height', this.daySize)
|
||||
.attr(
|
||||
'fill',
|
||||
stamp => (stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed'),
|
||||
)
|
||||
.attr('title', stamp => formatTooltipText(stamp))
|
||||
.attr('class', 'user-contrib-cell js-tooltip')
|
||||
.attr('data-container', 'body')
|
||||
.on('click', this.clickDay);
|
||||
}
|
||||
|
||||
renderDayTitles() {
|
||||
const days = [
|
||||
{
|
||||
text: 'M',
|
||||
y: 29 + (this.daySizeWithSpace * 1),
|
||||
}, {
|
||||
y: 29 + this.dayYPos(1),
|
||||
},
|
||||
{
|
||||
text: 'W',
|
||||
y: 29 + (this.daySizeWithSpace * 3),
|
||||
}, {
|
||||
y: 29 + this.dayYPos(2),
|
||||
},
|
||||
{
|
||||
text: 'F',
|
||||
y: 29 + (this.daySizeWithSpace * 5),
|
||||
y: 29 + this.dayYPos(3),
|
||||
},
|
||||
];
|
||||
this.svg.append('g')
|
||||
this.svg
|
||||
.append('g')
|
||||
.selectAll('text')
|
||||
.data(days)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('x', 8)
|
||||
.attr('y', day => day.y)
|
||||
.text(day => day.text)
|
||||
.attr('class', 'user-contrib-text');
|
||||
.data(days)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('x', 8)
|
||||
.attr('y', day => day.y)
|
||||
.text(day => day.text)
|
||||
.attr('class', 'user-contrib-text');
|
||||
}
|
||||
|
||||
renderMonths() {
|
||||
this.svg.append('g')
|
||||
this.svg
|
||||
.append('g')
|
||||
.attr('direction', 'ltr')
|
||||
.selectAll('text')
|
||||
.data(this.months)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('x', date => date.x)
|
||||
.attr('y', 10)
|
||||
.attr('class', 'user-contrib-text')
|
||||
.text(date => this.monthNames[date.month]);
|
||||
.data(this.months)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('x', date => date.x)
|
||||
.attr('y', 10)
|
||||
.attr('class', 'user-contrib-text')
|
||||
.text(date => this.monthNames[date.month]);
|
||||
}
|
||||
|
||||
renderKey() {
|
||||
const keyValues = ['no contributions', '1-9 contributions', '10-19 contributions', '20-29 contributions', '30+ contributions'];
|
||||
const keyColors = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
|
||||
const keyValues = [
|
||||
'no contributions',
|
||||
'1-9 contributions',
|
||||
'10-19 contributions',
|
||||
'20-29 contributions',
|
||||
'30+ contributions',
|
||||
];
|
||||
const keyColors = [
|
||||
'#ededed',
|
||||
this.colorKey(0),
|
||||
this.colorKey(1),
|
||||
this.colorKey(2),
|
||||
this.colorKey(3),
|
||||
];
|
||||
|
||||
this.svg.append('g')
|
||||
.attr('transform', `translate(18, ${(this.daySizeWithSpace * 8) + 16})`)
|
||||
this.svg
|
||||
.append('g')
|
||||
.attr('transform', `translate(18, ${this.daySizeWithSpace * 8 + 16})`)
|
||||
.selectAll('rect')
|
||||
.data(keyColors)
|
||||
.enter()
|
||||
.append('rect')
|
||||
.attr('width', this.daySize)
|
||||
.attr('height', this.daySize)
|
||||
.attr('x', (color, i) => this.daySizeWithSpace * i)
|
||||
.attr('y', 0)
|
||||
.attr('fill', color => color)
|
||||
.attr('class', 'js-tooltip')
|
||||
.attr('title', (color, i) => keyValues[i])
|
||||
.attr('data-container', 'body');
|
||||
.data(keyColors)
|
||||
.enter()
|
||||
.append('rect')
|
||||
.attr('width', this.daySize)
|
||||
.attr('height', this.daySize)
|
||||
.attr('x', (color, i) => this.daySizeWithSpace * i)
|
||||
.attr('y', 0)
|
||||
.attr('fill', color => color)
|
||||
.attr('class', 'js-tooltip')
|
||||
.attr('title', (color, i) => keyValues[i])
|
||||
.attr('data-container', 'body');
|
||||
}
|
||||
|
||||
initColor() {
|
||||
const colorRange = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
|
||||
return d3.scaleThreshold().domain([0, 10, 20, 30]).range(colorRange);
|
||||
const colorRange = [
|
||||
'#ededed',
|
||||
this.colorKey(0),
|
||||
this.colorKey(1),
|
||||
this.colorKey(2),
|
||||
this.colorKey(3),
|
||||
];
|
||||
return d3
|
||||
.scaleThreshold()
|
||||
.domain([0, 10, 20, 30])
|
||||
.range(colorRange);
|
||||
}
|
||||
|
||||
clickDay(stamp) {
|
||||
|
@ -227,14 +281,15 @@ export default class ActivityCalendar {
|
|||
|
||||
$('.user-calendar-activities').html(LOADING_HTML);
|
||||
|
||||
axios.get(this.calendarActivitiesPath, {
|
||||
params: {
|
||||
date,
|
||||
},
|
||||
responseType: 'text',
|
||||
})
|
||||
.then(({ data }) => $('.user-calendar-activities').html(data))
|
||||
.catch(() => flash(__('An error occurred while retrieving calendar activity')));
|
||||
axios
|
||||
.get(this.calendarActivitiesPath, {
|
||||
params: {
|
||||
date,
|
||||
},
|
||||
responseType: 'text',
|
||||
})
|
||||
.then(({ data }) => $('.user-calendar-activities').html(data))
|
||||
.catch(() => flash(__('An error occurred while retrieving calendar activity')));
|
||||
} else {
|
||||
this.currentSelectedDate = '';
|
||||
$('.user-calendar-activities').html('');
|
||||
|
|
|
@ -32,26 +32,38 @@ export default {
|
|||
required: true,
|
||||
},
|
||||
|
||||
buttonDisabled: {
|
||||
requestFinishedFor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isDisabled: false,
|
||||
linkRequested: '',
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
cssClass() {
|
||||
const actionIconDash = dasherize(this.actionIcon);
|
||||
return `${actionIconDash} js-icon-${actionIconDash}`;
|
||||
},
|
||||
isDisabled() {
|
||||
return this.buttonDisabled === this.link;
|
||||
},
|
||||
watch: {
|
||||
requestFinishedFor() {
|
||||
if (this.requestFinishedFor === this.linkRequested) {
|
||||
this.isDisabled = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClickAction() {
|
||||
$(this.$el).tooltip('hide');
|
||||
eventHub.$emit('graphAction', this.link);
|
||||
this.linkRequested = this.link;
|
||||
this.isDisabled = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -62,7 +74,8 @@ export default {
|
|||
@click="onClickAction"
|
||||
v-tooltip
|
||||
:title="tooltipText"
|
||||
class="btn btn-blank btn-transparent ci-action-icon-container ci-action-icon-wrapper"
|
||||
class="js-ci-action btn btn-blank
|
||||
btn-transparent ci-action-icon-container ci-action-icon-wrapper"
|
||||
:class="cssClass"
|
||||
data-container="body"
|
||||
:disabled="isDisabled"
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
<script>
|
||||
import icon from '../../../vue_shared/components/icon.vue';
|
||||
import tooltip from '../../../vue_shared/directives/tooltip';
|
||||
|
||||
/**
|
||||
* Renders either a cancel, retry or play icon pointing to the given path.
|
||||
* TODO: Remove UJS from here and use an async request instead.
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
tooltipText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
link: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
actionMethod: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
actionIcon: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<a
|
||||
v-tooltip
|
||||
:data-method="actionMethod"
|
||||
:title="tooltipText"
|
||||
:href="link"
|
||||
rel="nofollow"
|
||||
class="ci-action-icon-wrapper js-ci-status-icon"
|
||||
data-container="body"
|
||||
aria-label="Job's action"
|
||||
>
|
||||
<icon :name="actionIcon" />
|
||||
</a>
|
||||
</template>
|
|
@ -1,77 +1,83 @@
|
|||
<script>
|
||||
import $ from 'jquery';
|
||||
import jobNameComponent from './job_name_component.vue';
|
||||
import jobComponent from './job_component.vue';
|
||||
import tooltip from '../../../vue_shared/directives/tooltip';
|
||||
import $ from 'jquery';
|
||||
import JobNameComponent from './job_name_component.vue';
|
||||
import JobComponent from './job_component.vue';
|
||||
import tooltip from '../../../vue_shared/directives/tooltip';
|
||||
|
||||
/**
|
||||
* Renders the dropdown for the pipeline graph.
|
||||
*
|
||||
* The following object should be provided as `job`:
|
||||
*
|
||||
* {
|
||||
* "id": 4256,
|
||||
* "name": "test",
|
||||
* "status": {
|
||||
* "icon": "icon_status_success",
|
||||
* "text": "passed",
|
||||
* "label": "passed",
|
||||
* "group": "success",
|
||||
* "details_path": "/root/ci-mock/builds/4256",
|
||||
* "action": {
|
||||
* "icon": "retry",
|
||||
* "title": "Retry",
|
||||
* "path": "/root/ci-mock/builds/4256/retry",
|
||||
* "method": "post"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
/**
|
||||
* Renders the dropdown for the pipeline graph.
|
||||
*
|
||||
* The following object should be provided as `job`:
|
||||
*
|
||||
* {
|
||||
* "id": 4256,
|
||||
* "name": "test",
|
||||
* "status": {
|
||||
* "icon": "icon_status_success",
|
||||
* "text": "passed",
|
||||
* "label": "passed",
|
||||
* "group": "success",
|
||||
* "details_path": "/root/ci-mock/builds/4256",
|
||||
* "action": {
|
||||
* "icon": "retry",
|
||||
* "title": "Retry",
|
||||
* "path": "/root/ci-mock/builds/4256/retry",
|
||||
* "method": "post"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
|
||||
components: {
|
||||
JobComponent,
|
||||
JobNameComponent,
|
||||
},
|
||||
|
||||
props: {
|
||||
job: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
|
||||
components: {
|
||||
jobComponent,
|
||||
jobNameComponent,
|
||||
requestFinishedFor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
props: {
|
||||
job: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
tooltipText() {
|
||||
return `${this.job.name} - ${this.job.status.label}`;
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
tooltipText() {
|
||||
return `${this.job.name} - ${this.job.status.label}`;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.stopDropdownClickPropagation();
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.stopDropdownClickPropagation();
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* When the user right clicks or cmd/ctrl + click in the job name
|
||||
* the dropdown should not be closed and the link should open in another tab,
|
||||
* so we stop propagation of the click event inside the dropdown.
|
||||
methods: {
|
||||
/**
|
||||
* When the user right clicks or cmd/ctrl + click in the job name or the action icon
|
||||
* the dropdown should not be closed so we stop propagation
|
||||
* of the click event inside the dropdown.
|
||||
*
|
||||
* Since this component is rendered multiple times per page we need to guarantee we only
|
||||
* target the click event of this component.
|
||||
*/
|
||||
stopDropdownClickPropagation() {
|
||||
$(this.$el
|
||||
.querySelectorAll('.js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item'))
|
||||
.on('click', (e) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
},
|
||||
stopDropdownClickPropagation() {
|
||||
$(
|
||||
'.js-grouped-pipeline-dropdown button, .js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item',
|
||||
this.$el,
|
||||
).on('click', e => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="ci-job-dropdown-container">
|
||||
|
@ -101,8 +107,8 @@
|
|||
:key="i">
|
||||
<job-component
|
||||
:job="item"
|
||||
:is-dropdown="true"
|
||||
css-class-job-name="mini-pipeline-graph-dropdown-item"
|
||||
:request-finished-for="requestFinishedFor"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -7,7 +7,6 @@ export default {
|
|||
StageColumnComponent,
|
||||
LoadingIcon,
|
||||
},
|
||||
|
||||
props: {
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
|
@ -17,10 +16,10 @@ export default {
|
|||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
actionDisabled: {
|
||||
requestFinishedFor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -75,7 +74,7 @@ export default {
|
|||
:key="stage.name"
|
||||
:stage-connector-class="stageConnectorClass(index, stage)"
|
||||
:is-first-column="isFirstColumn(index)"
|
||||
:action-disabled="actionDisabled"
|
||||
:request-finished-for="requestFinishedFor"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
import ActionComponent from './action_component.vue';
|
||||
import DropdownActionComponent from './dropdown_action_component.vue';
|
||||
import JobNameComponent from './job_name_component.vue';
|
||||
import tooltip from '../../../vue_shared/directives/tooltip';
|
||||
|
||||
|
@ -32,10 +31,8 @@ import tooltip from '../../../vue_shared/directives/tooltip';
|
|||
export default {
|
||||
components: {
|
||||
ActionComponent,
|
||||
DropdownActionComponent,
|
||||
JobNameComponent,
|
||||
},
|
||||
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
|
@ -44,26 +41,17 @@ export default {
|
|||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
|
||||
cssClassJobName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
|
||||
isDropdown: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
|
||||
actionDisabled: {
|
||||
requestFinishedFor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
status() {
|
||||
return this.job && this.job.status ? this.job.status : {};
|
||||
|
@ -134,19 +122,11 @@ export default {
|
|||
</div>
|
||||
|
||||
<action-component
|
||||
v-if="hasAction && !isDropdown"
|
||||
v-if="hasAction"
|
||||
:tooltip-text="status.action.title"
|
||||
:link="status.action.path"
|
||||
:action-icon="status.action.icon"
|
||||
:button-disabled="actionDisabled"
|
||||
/>
|
||||
|
||||
<dropdown-action-component
|
||||
v-if="hasAction && isDropdown"
|
||||
:tooltip-text="status.action.title"
|
||||
:link="status.action.path"
|
||||
:action-icon="status.action.icon"
|
||||
:action-method="status.action.method"
|
||||
:request-finished-for="requestFinishedFor"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -29,10 +29,11 @@ export default {
|
|||
required: false,
|
||||
default: '',
|
||||
},
|
||||
actionDisabled: {
|
||||
|
||||
requestFinishedFor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -74,12 +75,12 @@ export default {
|
|||
v-if="job.size === 1"
|
||||
:job="job"
|
||||
css-class-job-name="build-content"
|
||||
:action-disabled="actionDisabled"
|
||||
/>
|
||||
|
||||
<dropdown-job-component
|
||||
v-if="job.size > 1"
|
||||
:job="job"
|
||||
:request-finished-for="requestFinishedFor"
|
||||
/>
|
||||
|
||||
</li>
|
||||
|
|
|
@ -25,7 +25,7 @@ export default () => {
|
|||
data() {
|
||||
return {
|
||||
mediator,
|
||||
actionDisabled: null,
|
||||
requestFinishedFor: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
@ -36,15 +36,17 @@ export default () => {
|
|||
},
|
||||
methods: {
|
||||
postAction(action) {
|
||||
this.actionDisabled = action;
|
||||
// Click was made, reset this variable
|
||||
this.requestFinishedFor = null;
|
||||
|
||||
this.mediator.service.postAction(action)
|
||||
this.mediator.service
|
||||
.postAction(action)
|
||||
.then(() => {
|
||||
this.mediator.refreshPipeline();
|
||||
this.actionDisabled = null;
|
||||
this.requestFinishedFor = action;
|
||||
})
|
||||
.catch(() => {
|
||||
this.actionDisabled = null;
|
||||
this.requestFinishedFor = action;
|
||||
Flash(__('An error occurred while making the request.'));
|
||||
});
|
||||
},
|
||||
|
@ -54,7 +56,7 @@ export default () => {
|
|||
props: {
|
||||
isLoading: this.mediator.state.isLoading,
|
||||
pipeline: this.mediator.store.state.pipeline,
|
||||
actionDisabled: this.actionDisabled,
|
||||
requestFinishedFor: this.requestFinishedFor,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
@ -79,7 +81,8 @@ export default () => {
|
|||
},
|
||||
methods: {
|
||||
postAction(action) {
|
||||
this.mediator.service.postAction(action.path)
|
||||
this.mediator.service
|
||||
.postAction(action.path)
|
||||
.then(() => this.mediator.refreshPipeline())
|
||||
.catch(() => Flash(__('An error occurred while making the request.')));
|
||||
},
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
<script>
|
||||
import ciIcon from './ci_icon.vue';
|
||||
import tooltip from '../directives/tooltip';
|
||||
/**
|
||||
* Renders CI Badge link with CI icon and status text based on
|
||||
* API response shared between all places where it is used.
|
||||
*
|
||||
* Receives status object containing:
|
||||
* status: {
|
||||
* details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
|
||||
* group:"running" // used for CSS class
|
||||
* icon: "icon_status_running" // used to render the icon
|
||||
* label:"running" // used for potential tooltip
|
||||
* text:"running" // text rendered
|
||||
* }
|
||||
*
|
||||
* Used in:
|
||||
* - Pipelines table - first column
|
||||
* - Jobs table - first column
|
||||
* - Pipeline show view - header
|
||||
* - Job show view - header
|
||||
* - MR widget
|
||||
*/
|
||||
import CiIcon from './ci_icon.vue';
|
||||
import tooltip from '../directives/tooltip';
|
||||
/**
|
||||
* Renders CI Badge link with CI icon and status text based on
|
||||
* API response shared between all places where it is used.
|
||||
*
|
||||
* Receives status object containing:
|
||||
* status: {
|
||||
* details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
|
||||
* group:"running" // used for CSS class
|
||||
* icon: "icon_status_running" // used to render the icon
|
||||
* label:"running" // used for potential tooltip
|
||||
* text:"running" // text rendered
|
||||
* }
|
||||
*
|
||||
* Used in:
|
||||
* - Pipelines table - first column
|
||||
* - Jobs table - first column
|
||||
* - Pipeline show view - header
|
||||
* - Job show view - header
|
||||
* - MR widget
|
||||
*/
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ciIcon,
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
status: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
showText: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
props: {
|
||||
status: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
showText: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
cssClass() {
|
||||
const className = this.status.group;
|
||||
return className ? `ci-status ci-${className}` : 'ci-status';
|
||||
},
|
||||
computed: {
|
||||
cssClass() {
|
||||
const className = this.status.group;
|
||||
return className ? `ci-status ci-${className}` : 'ci-status';
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<a
|
||||
|
|
|
@ -1,45 +1,44 @@
|
|||
<script>
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
import Icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
/**
|
||||
* Renders CI icon based on API response shared between all places where it is used.
|
||||
*
|
||||
* Receives status object containing:
|
||||
* status: {
|
||||
* details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
|
||||
* group:"running" // used for CSS class
|
||||
* icon: "icon_status_running" // used to render the icon
|
||||
* label:"running" // used for potential tooltip
|
||||
* text:"running" // text rendered
|
||||
* }
|
||||
*
|
||||
* Used in:
|
||||
* - Pipelines table Badge
|
||||
* - Pipelines table mini graph
|
||||
* - Pipeline graph
|
||||
* - Pipeline show view badge
|
||||
* - Jobs table
|
||||
* - Jobs show view header
|
||||
* - Jobs show view sidebar
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
/**
|
||||
* Renders CI icon based on API response shared between all places where it is used.
|
||||
*
|
||||
* Receives status object containing:
|
||||
* status: {
|
||||
* details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
|
||||
* group:"running" // used for CSS class
|
||||
* icon: "icon_status_running" // used to render the icon
|
||||
* label:"running" // used for potential tooltip
|
||||
* text:"running" // text rendered
|
||||
* }
|
||||
*
|
||||
* Used in:
|
||||
* - Pipelines table Badge
|
||||
* - Pipelines table mini graph
|
||||
* - Pipeline graph
|
||||
* - Pipeline show view badge
|
||||
* - Jobs table
|
||||
* - Jobs show view header
|
||||
* - Jobs show view sidebar
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
status: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
status: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
cssClass() {
|
||||
const status = this.status.group;
|
||||
return `ci-status-icon ci-status-icon-${status} js-ci-status-icon-${status}`;
|
||||
},
|
||||
|
||||
computed: {
|
||||
cssClass() {
|
||||
const status = this.status.group;
|
||||
return `ci-status-icon ci-status-icon-${status} js-ci-status-icon-${status}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span :class="cssClass">
|
||||
|
|
|
@ -1,40 +1,50 @@
|
|||
<script>
|
||||
/**
|
||||
* Falls back to the code used in `copy_to_clipboard.js`
|
||||
*/
|
||||
import tooltip from '../directives/tooltip';
|
||||
/**
|
||||
* Falls back to the code used in `copy_to_clipboard.js`
|
||||
*
|
||||
* Renders a button with a clipboard icon that copies the content of `data-clipboard-text`
|
||||
* when clicked.
|
||||
*
|
||||
* @example
|
||||
* <clipboard-button
|
||||
* title="Copy to clipbard"
|
||||
* text="Content to be copied"
|
||||
* css-class="btn-transparent"
|
||||
* />
|
||||
*/
|
||||
import tooltip from '../directives/tooltip';
|
||||
|
||||
export default {
|
||||
name: 'ClipboardButton',
|
||||
directives: {
|
||||
tooltip,
|
||||
export default {
|
||||
name: 'ClipboardButton',
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
tooltipPlacement: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'top',
|
||||
},
|
||||
tooltipContainer: {
|
||||
type: [String, Boolean],
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
cssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'btn-default',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
tooltipPlacement: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'top',
|
||||
},
|
||||
tooltipContainer: {
|
||||
type: [String, Boolean],
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
cssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'btn-default',
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,119 +1,111 @@
|
|||
<script>
|
||||
import commitIconSvg from 'icons/_icon_commit.svg';
|
||||
import userAvatarLink from './user_avatar/user_avatar_link.vue';
|
||||
import tooltip from '../directives/tooltip';
|
||||
import icon from '../../vue_shared/components/icon.vue';
|
||||
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
|
||||
import tooltip from '../directives/tooltip';
|
||||
import Icon from '../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
components: {
|
||||
UserAvatarLink,
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
/**
|
||||
* Indicates the existance of a tag.
|
||||
* Used to render the correct icon, if true will render `fa-tag` icon,
|
||||
* if false will render a svg sprite fork icon
|
||||
*/
|
||||
tag: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
components: {
|
||||
userAvatarLink,
|
||||
icon,
|
||||
/**
|
||||
* If provided is used to render the branch name and url.
|
||||
* Should contain the following properties:
|
||||
* name
|
||||
* ref_url
|
||||
*/
|
||||
commitRef: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
/**
|
||||
* Used to link to the commit sha.
|
||||
*/
|
||||
commitUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
props: {
|
||||
/**
|
||||
* Indicates the existance of a tag.
|
||||
* Used to render the correct icon, if true will render `fa-tag` icon,
|
||||
* if false will render a svg sprite fork icon
|
||||
*/
|
||||
tag: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* If provided is used to render the branch name and url.
|
||||
* Should contain the following properties:
|
||||
* name
|
||||
* ref_url
|
||||
*/
|
||||
commitRef: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
/**
|
||||
* Used to link to the commit sha.
|
||||
*/
|
||||
commitUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
|
||||
/**
|
||||
* Used to show the commit short sha that links to the commit url.
|
||||
*/
|
||||
shortSha: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
/**
|
||||
* If provided shows the commit tile.
|
||||
*/
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
/**
|
||||
* If provided renders information about the author of the commit.
|
||||
* When provided should include:
|
||||
* `avatar_url` to render the avatar icon
|
||||
* `web_url` to link to user profile
|
||||
* `username` to render alt and title tags
|
||||
*/
|
||||
author: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
showBranch: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
* Used to show the commit short sha that links to the commit url.
|
||||
*/
|
||||
shortSha: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* Used to verify if all the properties needed to render the commit
|
||||
* ref section were provided.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
hasCommitRef() {
|
||||
return this.commitRef && this.commitRef.name && this.commitRef.ref_url;
|
||||
},
|
||||
/**
|
||||
* Used to verify if all the properties needed to render the commit
|
||||
* author section were provided.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
hasAuthor() {
|
||||
return this.author &&
|
||||
this.author.avatar_url &&
|
||||
this.author.path &&
|
||||
this.author.username;
|
||||
},
|
||||
/**
|
||||
* If information about the author is provided will return a string
|
||||
* to be rendered as the alt attribute of the img tag.
|
||||
*
|
||||
* @returns {String}
|
||||
*/
|
||||
userImageAltDescription() {
|
||||
return this.author &&
|
||||
this.author.username ? `${this.author.username}'s avatar` : null;
|
||||
},
|
||||
/**
|
||||
* If provided shows the commit tile.
|
||||
*/
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
created() {
|
||||
this.commitIconSvg = commitIconSvg;
|
||||
/**
|
||||
* If provided renders information about the author of the commit.
|
||||
* When provided should include:
|
||||
* `avatar_url` to render the avatar icon
|
||||
* `web_url` to link to user profile
|
||||
* `username` to render alt and title tags
|
||||
*/
|
||||
author: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
};
|
||||
showBranch: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* Used to verify if all the properties needed to render the commit
|
||||
* ref section were provided.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
hasCommitRef() {
|
||||
return this.commitRef && this.commitRef.name && this.commitRef.ref_url;
|
||||
},
|
||||
/**
|
||||
* Used to verify if all the properties needed to render the commit
|
||||
* author section were provided.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
hasAuthor() {
|
||||
return this.author && this.author.avatar_url && this.author.path && this.author.username;
|
||||
},
|
||||
/**
|
||||
* If information about the author is provided will return a string
|
||||
* to be rendered as the alt attribute of the img tag.
|
||||
*
|
||||
* @returns {String}
|
||||
*/
|
||||
userImageAltDescription() {
|
||||
return this.author && this.author.username ? `${this.author.username}'s avatar` : null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="branch-commit">
|
||||
|
@ -141,11 +133,10 @@
|
|||
{{ commitRef.name }}
|
||||
</a>
|
||||
</template>
|
||||
<div
|
||||
v-html="commitIconSvg"
|
||||
<icon
|
||||
name="commit"
|
||||
class="commit-icon js-commit-icon"
|
||||
>
|
||||
</div>
|
||||
/>
|
||||
|
||||
<a
|
||||
class="commit-sha"
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
<script>
|
||||
import { __ } from '~/locale';
|
||||
/**
|
||||
* Port of detail_behavior expand button.
|
||||
*
|
||||
* @example
|
||||
* <expand-button>
|
||||
* <template slot="expanded">
|
||||
* Text goes here.
|
||||
* </template>
|
||||
* </expand-button>
|
||||
*/
|
||||
export default {
|
||||
name: 'ExpandButton',
|
||||
data() {
|
||||
return {
|
||||
isCollapsed: true,
|
||||
};
|
||||
import { __ } from '~/locale';
|
||||
/**
|
||||
* Port of detail_behavior expand button.
|
||||
*
|
||||
* @example
|
||||
* <expand-button>
|
||||
* <template slot="expanded">
|
||||
* Text goes here.
|
||||
* </template>
|
||||
* </expand-button>
|
||||
*/
|
||||
export default {
|
||||
name: 'ExpandButton',
|
||||
data() {
|
||||
return {
|
||||
isCollapsed: true,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
ariaLabel() {
|
||||
return __('Click to expand text');
|
||||
},
|
||||
computed: {
|
||||
ariaLabel() {
|
||||
return __('Click to expand text');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span>
|
||||
|
|
|
@ -1,78 +1,78 @@
|
|||
<script>
|
||||
import ciIconBadge from './ci_badge_link.vue';
|
||||
import loadingIcon from './loading_icon.vue';
|
||||
import timeagoTooltip from './time_ago_tooltip.vue';
|
||||
import tooltip from '../directives/tooltip';
|
||||
import userAvatarImage from './user_avatar/user_avatar_image.vue';
|
||||
import CiIconBadge from './ci_badge_link.vue';
|
||||
import LoadingIcon from './loading_icon.vue';
|
||||
import TimeagoTooltip from './time_ago_tooltip.vue';
|
||||
import tooltip from '../directives/tooltip';
|
||||
import UserAvatarImage from './user_avatar/user_avatar_image.vue';
|
||||
|
||||
/**
|
||||
* Renders header component for job and pipeline page based on UI mockups
|
||||
*
|
||||
* Used in:
|
||||
* - job show page
|
||||
* - pipeline show page
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
ciIconBadge,
|
||||
loadingIcon,
|
||||
timeagoTooltip,
|
||||
userAvatarImage,
|
||||
/**
|
||||
* Renders header component for job and pipeline page based on UI mockups
|
||||
*
|
||||
* Used in:
|
||||
* - job show page
|
||||
* - pipeline show page
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
CiIconBadge,
|
||||
LoadingIcon,
|
||||
TimeagoTooltip,
|
||||
UserAvatarImage,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
status: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
itemName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
status: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
itemName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
itemId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
time: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
user: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
actions: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
hasSidebarButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
shouldRenderTriggeredLabel: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
itemId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
time: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
user: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
actions: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
hasSidebarButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
shouldRenderTriggeredLabel: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
userAvatarAltText() {
|
||||
return `${this.user.name}'s avatar`;
|
||||
},
|
||||
computed: {
|
||||
userAvatarAltText() {
|
||||
return `${this.user.name}'s avatar`;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClickAction(action) {
|
||||
this.$emit('actionClicked', action);
|
||||
},
|
||||
methods: {
|
||||
onClickAction(action) {
|
||||
this.$emit('actionClicked', action);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,76 +1,75 @@
|
|||
<script>
|
||||
/* This is a re-usable vue component for rendering a svg sprite
|
||||
icon
|
||||
|
||||
/* This is a re-usable vue component for rendering a svg sprite
|
||||
icon
|
||||
Sample configuration:
|
||||
|
||||
Sample configuration:
|
||||
<icon
|
||||
name="retry"
|
||||
:size="32"
|
||||
css-classes="top"
|
||||
/>
|
||||
|
||||
<icon
|
||||
name="retry"
|
||||
:size="32"
|
||||
css-classes="top"
|
||||
/>
|
||||
*/
|
||||
// only allow classes in images.scss e.g. s12
|
||||
const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
|
||||
|
||||
*/
|
||||
// only allow classes in images.scss e.g. s12
|
||||
const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
size: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 16,
|
||||
validator(value) {
|
||||
return validSizes.includes(value);
|
||||
},
|
||||
},
|
||||
|
||||
cssClasses: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
|
||||
width: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
|
||||
height: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
|
||||
y: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
|
||||
x: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
size: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 16,
|
||||
validator(value) {
|
||||
return validSizes.includes(value);
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
spriteHref() {
|
||||
return `${gon.sprite_icons}#${this.name}`;
|
||||
},
|
||||
iconSizeClass() {
|
||||
return this.size ? `s${this.size}` : '';
|
||||
},
|
||||
cssClasses: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
};
|
||||
|
||||
width: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
|
||||
height: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
|
||||
y: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
|
||||
x: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
spriteHref() {
|
||||
return `${gon.sprite_icons}#${this.name}`;
|
||||
},
|
||||
iconSizeClass() {
|
||||
return this.size ? `s${this.size}` : '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -79,7 +78,8 @@
|
|||
:width="width"
|
||||
:height="height"
|
||||
:x="x"
|
||||
:y="y">
|
||||
:y="y"
|
||||
>
|
||||
<use v-bind="{ 'xlink:href':spriteHref }" />
|
||||
</svg>
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script>
|
||||
import $ from 'jquery';
|
||||
import { __ } from '~/locale';
|
||||
import LabelsSelect from '~/labels_select';
|
||||
import LoadingIcon from '../../loading_icon.vue';
|
||||
|
@ -98,11 +99,18 @@ export default {
|
|||
this.labelsDropdown = new LabelsSelect(this.$refs.dropdownButton, {
|
||||
handleClick: this.handleClick,
|
||||
});
|
||||
$(this.$refs.dropdown).on('hidden.gl.dropdown', this.handleDropdownHidden);
|
||||
},
|
||||
methods: {
|
||||
handleClick(label) {
|
||||
this.$emit('onLabelClick', label);
|
||||
},
|
||||
handleCollapsedValueClick() {
|
||||
this.$emit('toggleCollapse');
|
||||
},
|
||||
handleDropdownHidden() {
|
||||
this.$emit('onDropdownClose');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -112,6 +120,7 @@ export default {
|
|||
<dropdown-value-collapsed
|
||||
v-if="showCreate"
|
||||
:labels="context.labels"
|
||||
@onValueClick="handleCollapsedValueClick"
|
||||
/>
|
||||
<dropdown-title
|
||||
:can-edit="canEdit"
|
||||
|
@ -133,7 +142,10 @@ export default {
|
|||
:name="hiddenInputName"
|
||||
:label="label"
|
||||
/>
|
||||
<div class="dropdown">
|
||||
<div
|
||||
class="dropdown"
|
||||
ref="dropdown"
|
||||
>
|
||||
<dropdown-button
|
||||
:ability-name="abilityName"
|
||||
:field-name="hiddenInputName"
|
||||
|
|
|
@ -26,6 +26,11 @@ export default {
|
|||
return labelsString;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleClick() {
|
||||
this.$emit('onValueClick');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -36,6 +41,7 @@ export default {
|
|||
data-placement="left"
|
||||
data-container="body"
|
||||
:title="labelsList"
|
||||
@click="handleClick"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
|
|
|
@ -468,6 +468,14 @@
|
|||
margin-bottom: 10px;
|
||||
white-space: normal;
|
||||
|
||||
.ci-job-dropdown-container {
|
||||
// override dropdown.scss
|
||||
.dropdown-menu li button {
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure .build-content has hover style when action-icon is hovered
|
||||
.ci-job-dropdown-container:hover .build-content {
|
||||
@extend .build-content:hover;
|
||||
|
|
|
@ -134,11 +134,11 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
def can_create_branch
|
||||
can_create = current_user &&
|
||||
can?(current_user, :push_code, @project) &&
|
||||
@issue.can_be_worked_on?(current_user)
|
||||
@issue.can_be_worked_on?
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: { can_create_branch: can_create, has_related_branch: @issue.has_related_branch? }
|
||||
render json: { can_create_branch: can_create, suggested_branch_name: @issue.suggested_branch_name }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -177,7 +177,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def authorize_create_merge_request!
|
||||
render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user)
|
||||
render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?
|
||||
end
|
||||
|
||||
def render_issue_json
|
||||
|
|
|
@ -78,8 +78,6 @@ class Projects::JobsController < Projects::ApplicationController
|
|||
result.merge!(trace.to_h)
|
||||
end
|
||||
|
||||
result[:html] = result[:html].presence || 'No job log'
|
||||
|
||||
render json: result
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,7 @@ class UsersFinder
|
|||
users = by_active(users)
|
||||
users = by_external_identity(users)
|
||||
users = by_external(users)
|
||||
users = by_2fa(users)
|
||||
users = by_created_at(users)
|
||||
users = by_custom_attributes(users)
|
||||
|
||||
|
@ -76,4 +77,15 @@ class UsersFinder
|
|||
|
||||
users.external
|
||||
end
|
||||
|
||||
def by_2fa(users)
|
||||
case params[:two_factor]
|
||||
when 'enabled'
|
||||
users.with_two_factor
|
||||
when 'disabled'
|
||||
users.without_two_factor
|
||||
else
|
||||
users
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,6 +81,14 @@ module GitlabRoutingHelper
|
|||
end
|
||||
end
|
||||
|
||||
def edit_milestone_path(entity, *args)
|
||||
if entity.parent.is_a?(Group)
|
||||
edit_group_milestone_path(entity.parent, entity, *args)
|
||||
else
|
||||
edit_project_milestone_path(entity.parent, entity, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def toggle_subscription_path(entity, *args)
|
||||
if entity.is_a?(Issue)
|
||||
toggle_subscription_project_issue_path(entity.project, entity)
|
||||
|
|
|
@ -27,6 +27,7 @@ module Ci
|
|||
|
||||
has_one :metadata, class_name: 'Ci::BuildMetadata'
|
||||
delegate :timeout, to: :metadata, prefix: true, allow_nil: true
|
||||
delegate :gitlab_deploy_token, to: :project
|
||||
|
||||
##
|
||||
# The "environment" field for builds is a String, and is the unexpanded name!
|
||||
|
@ -604,6 +605,7 @@ module Ci
|
|||
.append(key: 'CI_REGISTRY_USER', value: CI_REGISTRY_USER)
|
||||
.append(key: 'CI_REGISTRY_PASSWORD', value: token, public: false)
|
||||
.append(key: 'CI_REPOSITORY_URL', value: repo_url, public: false)
|
||||
.concat(deploy_token_variables)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -654,6 +656,15 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def deploy_token_variables
|
||||
Gitlab::Ci::Variables::Collection.new.tap do |variables|
|
||||
break variables unless gitlab_deploy_token
|
||||
|
||||
variables.append(key: 'CI_DEPLOY_USER', value: gitlab_deploy_token.name)
|
||||
variables.append(key: 'CI_DEPLOY_PASSWORD', value: gitlab_deploy_token.token, public: false)
|
||||
end
|
||||
end
|
||||
|
||||
def environment_url
|
||||
options&.dig(:environment, :url) || persisted_environment&.external_url
|
||||
end
|
||||
|
|
|
@ -27,8 +27,9 @@ module AtomicInternalId
|
|||
module ClassMethods
|
||||
def has_internal_id(column, scope:, init:) # rubocop:disable Naming/PredicateName
|
||||
before_validation(on: :create) do
|
||||
if read_attribute(column).blank?
|
||||
scope_attrs = { scope => association(scope).reader }
|
||||
scope_value = association(scope).reader
|
||||
if read_attribute(column).blank? && scope_value
|
||||
scope_attrs = { scope_value.class.table_name.singularize.to_sym => scope_value }
|
||||
usage = self.class.table_name.to_sym
|
||||
|
||||
new_iid = InternalId.generate_next(self, scope_attrs, usage, init)
|
||||
|
|
|
@ -31,12 +31,13 @@ module Avatarable
|
|||
|
||||
asset_host = ActionController::Base.asset_host
|
||||
use_asset_host = asset_host.present?
|
||||
use_authentication = respond_to?(:public?) && !public?
|
||||
|
||||
# Avatars for private and internal groups and projects require authentication to be viewed,
|
||||
# which means they can only be served by Rails, on the regular GitLab host.
|
||||
# If an asset host is configured, we need to return the fully qualified URL
|
||||
# instead of only the avatar path, so that Rails doesn't prefix it with the asset host.
|
||||
if use_asset_host && respond_to?(:public?) && !public?
|
||||
if use_asset_host && use_authentication
|
||||
use_asset_host = false
|
||||
only_path = false
|
||||
end
|
||||
|
@ -49,6 +50,6 @@ module Avatarable
|
|||
url_base << gitlab_config.relative_url_root
|
||||
end
|
||||
|
||||
url_base + avatar.url
|
||||
url_base + avatar.local_url
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
module NonatomicInternalId
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
validate :set_iid, on: :create
|
||||
validates :iid, presence: true, numericality: true
|
||||
end
|
||||
|
||||
def set_iid
|
||||
if iid.blank?
|
||||
parent = project || group
|
||||
records = parent.public_send(self.class.name.tableize) # rubocop:disable GitlabSecurity/PublicSend
|
||||
max_iid = records.maximum(:iid)
|
||||
|
||||
self.iid = max_iid.to_i + 1
|
||||
end
|
||||
end
|
||||
|
||||
def to_param
|
||||
iid.to_s
|
||||
end
|
||||
end
|
|
@ -102,7 +102,7 @@ module Routable
|
|||
# the route. Caching this per request ensures that even if we have multiple instances,
|
||||
# we will not have to duplicate work, avoiding N+1 queries in some cases.
|
||||
def full_path
|
||||
return uncached_full_path unless RequestStore.active?
|
||||
return uncached_full_path unless RequestStore.active? && persisted?
|
||||
|
||||
RequestStore[full_path_key] ||= uncached_full_path
|
||||
end
|
||||
|
@ -124,6 +124,11 @@ module Routable
|
|||
end
|
||||
end
|
||||
|
||||
# Group would override this to check from association
|
||||
def owned_by?(user)
|
||||
owner == user
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_path_errors
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
# Uniquify
|
||||
#
|
||||
# Return a version of the given 'base' string that is unique
|
||||
# by appending a counter to it. Uniqueness is determined by
|
||||
# repeated calls to the passed block.
|
||||
#
|
||||
# You can pass an initial value for the counter, if not given
|
||||
# counting starts from 1.
|
||||
#
|
||||
# If `base` is a function/proc, we expect that calling it with a
|
||||
# candidate counter returns a string to test/return.
|
||||
class Uniquify
|
||||
# Return a version of the given 'base' string that is unique
|
||||
# by appending a counter to it. Uniqueness is determined by
|
||||
# repeated calls to the passed block.
|
||||
#
|
||||
# If `base` is a function/proc, we expect that calling it with a
|
||||
# candidate counter returns a string to test/return.
|
||||
def initialize(counter = nil)
|
||||
@counter = counter
|
||||
end
|
||||
|
||||
def string(base)
|
||||
@base = base
|
||||
@counter = nil
|
||||
|
||||
increment_counter! while yield(base_string)
|
||||
base_string
|
||||
|
|
|
@ -4,6 +4,7 @@ class DeployToken < ActiveRecord::Base
|
|||
add_authentication_token_field :token
|
||||
|
||||
AVAILABLE_SCOPES = %i(read_repository read_registry).freeze
|
||||
GITLAB_DEPLOY_TOKEN_NAME = 'gitlab-deploy-token'.freeze
|
||||
|
||||
default_value_for(:expires_at) { Forever.date }
|
||||
|
||||
|
@ -17,6 +18,10 @@ class DeployToken < ActiveRecord::Base
|
|||
|
||||
scope :active, -> { where("revoked = false AND expires_at >= NOW()") }
|
||||
|
||||
def self.gitlab_deploy_token
|
||||
active.find_by(name: GITLAB_DEPLOY_TOKEN_NAME)
|
||||
end
|
||||
|
||||
def revoke!
|
||||
update!(revoked: true)
|
||||
end
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
class Deployment < ActiveRecord::Base
|
||||
include NonatomicInternalId
|
||||
include AtomicInternalId
|
||||
|
||||
belongs_to :project, required: true
|
||||
belongs_to :environment, required: true
|
||||
belongs_to :user
|
||||
belongs_to :deployable, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
|
||||
|
||||
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.deployments&.maximum(:iid) }
|
||||
|
||||
validates :sha, presence: true
|
||||
validates :ref, presence: true
|
||||
|
||||
|
|
|
@ -125,6 +125,10 @@ class Group < Namespace
|
|||
self[:lfs_enabled]
|
||||
end
|
||||
|
||||
def owned_by?(user)
|
||||
owners.include?(user)
|
||||
end
|
||||
|
||||
def add_users(users, access_level, current_user: nil, expires_at: nil)
|
||||
GroupMember.add_users(
|
||||
self,
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
# * (Optionally) add columns to `internal_ids` if needed for scope.
|
||||
class InternalId < ActiveRecord::Base
|
||||
belongs_to :project
|
||||
belongs_to :namespace
|
||||
|
||||
enum usage: { issues: 0 }
|
||||
enum usage: { issues: 0, merge_requests: 1, deployments: 2, milestones: 3, epics: 4 }
|
||||
|
||||
validates :usage, presence: true
|
||||
|
||||
|
|
|
@ -194,6 +194,15 @@ class Issue < ActiveRecord::Base
|
|||
branches_with_iid - branches_with_merge_request
|
||||
end
|
||||
|
||||
def suggested_branch_name
|
||||
return to_branch_name unless project.repository.branch_exists?(to_branch_name)
|
||||
|
||||
start_counting_from = 2
|
||||
Uniquify.new(start_counting_from).string(-> (counter) { "#{to_branch_name}-#{counter}" }) do |suggested_branch_name|
|
||||
project.repository.branch_exists?(suggested_branch_name)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns boolean if a related branch exists for the current issue
|
||||
# ignores merge requests branchs
|
||||
def has_related_branch?
|
||||
|
@ -248,11 +257,8 @@ class Issue < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def can_be_worked_on?(current_user)
|
||||
!self.closed? &&
|
||||
!self.project.forked? &&
|
||||
self.related_branches(current_user).empty? &&
|
||||
self.closed_by_merge_requests(current_user).empty?
|
||||
def can_be_worked_on?
|
||||
!self.closed? && !self.project.forked?
|
||||
end
|
||||
|
||||
# Returns `true` if the current issue can be viewed by either a logged in User
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class MergeRequest < ActiveRecord::Base
|
||||
include NonatomicInternalId
|
||||
include AtomicInternalId
|
||||
include Issuable
|
||||
include Noteable
|
||||
include Referable
|
||||
|
@ -18,6 +18,8 @@ class MergeRequest < ActiveRecord::Base
|
|||
belongs_to :source_project, class_name: "Project"
|
||||
belongs_to :merge_user, class_name: "User"
|
||||
|
||||
has_internal_id :iid, scope: :target_project, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) }
|
||||
|
||||
has_many :merge_request_diffs
|
||||
|
||||
has_one :merge_request_diff,
|
||||
|
|
|
@ -8,7 +8,7 @@ class Milestone < ActiveRecord::Base
|
|||
Started = MilestoneStruct.new('Started', '#started', -3)
|
||||
|
||||
include CacheMarkdownField
|
||||
include NonatomicInternalId
|
||||
include AtomicInternalId
|
||||
include Sortable
|
||||
include Referable
|
||||
include StripAttribute
|
||||
|
@ -21,6 +21,9 @@ class Milestone < ActiveRecord::Base
|
|||
belongs_to :project
|
||||
belongs_to :group
|
||||
|
||||
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.milestones&.maximum(:iid) }
|
||||
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
|
||||
|
||||
has_many :issues
|
||||
has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues
|
||||
has_many :merge_requests
|
||||
|
|
|
@ -1879,6 +1879,10 @@ class Project < ActiveRecord::Base
|
|||
[]
|
||||
end
|
||||
|
||||
def gitlab_deploy_token
|
||||
@gitlab_deploy_token ||= deploy_tokens.gitlab_deploy_token
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def storage
|
||||
|
|
|
@ -1,5 +1,51 @@
|
|||
require "flowdock-git-hook"
|
||||
|
||||
# Flow dock depends on Grit to compute the number of commits between two given
|
||||
# commits. To make this depend on Gitaly, a monkey patch is applied
|
||||
module Flowdock
|
||||
class Git
|
||||
# pass down a Repository all the way down
|
||||
def repo
|
||||
@options[:repo]
|
||||
end
|
||||
|
||||
def config
|
||||
{}
|
||||
end
|
||||
|
||||
def messages
|
||||
Git::Builder.new(repo: repo,
|
||||
ref: @ref,
|
||||
before: @from,
|
||||
after: @to,
|
||||
commit_url: @commit_url,
|
||||
branch_url: @branch_url,
|
||||
diff_url: @diff_url,
|
||||
repo_url: @repo_url,
|
||||
repo_name: @repo_name,
|
||||
permanent_refs: @permanent_refs,
|
||||
tags: tags
|
||||
).to_hashes
|
||||
end
|
||||
|
||||
class Builder
|
||||
def commits
|
||||
@repo.commits_between(@before, @after).map do |commit|
|
||||
{
|
||||
url: @opts[:commit_url] ? @opts[:commit_url] % [commit.sha] : nil,
|
||||
id: commit.sha,
|
||||
message: commit.message,
|
||||
author: {
|
||||
name: commit.author_name,
|
||||
email: commit.author_email
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class FlowdockService < Service
|
||||
prop_accessor :token
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
@ -34,7 +80,7 @@ class FlowdockService < Service
|
|||
data[:before],
|
||||
data[:after],
|
||||
token: token,
|
||||
repo: project.repository.path_to_repo,
|
||||
repo: project.repository,
|
||||
repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
|
||||
commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/commit/%s",
|
||||
diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
|
||||
|
|
|
@ -22,7 +22,7 @@ class GroupPolicy < BasePolicy
|
|||
condition(:can_change_parent_share_with_group_lock) { can?(:change_share_with_group_lock, @subject.parent) }
|
||||
|
||||
condition(:has_projects) do
|
||||
GroupProjectsFinder.new(group: @subject, current_user: @user).execute.any?
|
||||
GroupProjectsFinder.new(group: @subject, current_user: @user, options: { include_subgroups: true }).execute.any?
|
||||
end
|
||||
|
||||
with_options scope: :subject, score: 0
|
||||
|
@ -43,7 +43,11 @@ class GroupPolicy < BasePolicy
|
|||
end
|
||||
|
||||
rule { admin } .enable :read_group
|
||||
rule { has_projects } .enable :read_group
|
||||
|
||||
rule { has_projects }.policy do
|
||||
enable :read_group
|
||||
enable :read_label
|
||||
end
|
||||
|
||||
rule { has_access }.enable :read_namespace
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
|
|||
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
|
||||
OpenStruct.new(enabled: auto_devops_enabled?,
|
||||
label: auto_devops_enabled? ? _('Auto DevOps enabled') : _('Enable Auto DevOps'),
|
||||
link: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
|
||||
link: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
|
||||
elsif auto_devops_enabled?
|
||||
OpenStruct.new(enabled: true,
|
||||
label: _('Auto DevOps enabled'),
|
||||
|
|
|
@ -65,6 +65,10 @@ class GitlabUploader < CarrierWave::Uploader::Base
|
|||
!!model
|
||||
end
|
||||
|
||||
def local_url
|
||||
File.join('/', self.class.base_dir, dynamic_segment, filename)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Designed to be overridden by child uploaders that have a dynamic path
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
.help-block
|
||||
Manage repository storage paths. Learn more in the
|
||||
= succeed "." do
|
||||
= link_to "repository storages documentation", help_page_path("administration/repository_storages")
|
||||
= link_to "repository storages documentation", help_page_path("administration/repository_storage_paths")
|
||||
.sub-section
|
||||
%h4 Circuit breaker
|
||||
.form-group
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
%hr
|
||||
%p
|
||||
- link_to_auto_devops_settings = link_to(s_('AutoDevOps|enable Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'))
|
||||
- link_to_auto_devops_settings = link_to(s_('AutoDevOps|enable Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'))
|
||||
- link_to_add_kubernetes_cluster = link_to(s_('AutoDevOps|add a Kubernetes cluster'), new_project_cluster_path(@project))
|
||||
= s_('AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}.').html_safe % { link_to_auto_devops_settings: link_to_auto_devops_settings, link_to_add_kubernetes_cluster: link_to_add_kubernetes_cluster }
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
- unless @repository.gitlab_ci_yml
|
||||
= link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
|
||||
|
||||
= link_to ci_lint_path, class: 'btn btn-default' do
|
||||
= link_to project_ci_lint_path(@project), class: 'btn btn-default' do
|
||||
%span CI lint
|
||||
|
||||
.content-list.builds-content-list
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
%ul
|
||||
- pipeline.yaml_errors.split(",").each do |error|
|
||||
%li= error
|
||||
You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path}
|
||||
You can also test your .gitlab-ci.yml in the #{link_to "Lint", project_ci_lint_path(@project)}
|
||||
|
||||
- if pipeline.project.builds_enabled? && !pipeline.ci_yaml_file
|
||||
.bs-callout.bs-callout-warning
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
.row.prepend-top-default
|
||||
.col-lg-12
|
||||
= form_for @project, url: project_settings_ci_cd_path(@project) do |f|
|
||||
= form_errors(@project)
|
||||
%fieldset.builds-feature
|
||||
.form-group
|
||||
- message = auto_devops_warning_message(@project)
|
||||
- ci_file_formatted = '<code>.gitlab-ci.yml</code>'.html_safe
|
||||
- if message
|
||||
%p.settings-message.text-center
|
||||
= message.html_safe
|
||||
= f.fields_for :auto_devops_attributes, @auto_devops do |form|
|
||||
.radio
|
||||
= form.label :enabled_true do
|
||||
= form.radio_button :enabled, 'true'
|
||||
%strong= s_('CICD|Enable Auto DevOps')
|
||||
%br
|
||||
= s_('CICD|The Auto DevOps pipeline configuration will be used when there is no %{ci_file} in the project.').html_safe % { ci_file: ci_file_formatted }
|
||||
|
||||
.radio
|
||||
= form.label :enabled_false do
|
||||
= form.radio_button :enabled, 'false'
|
||||
%strong= s_('CICD|Disable Auto DevOps')
|
||||
%br
|
||||
= s_('CICD|An explicit %{ci_file} needs to be specified before you can begin using Continuous Integration and Delivery.').html_safe % { ci_file: ci_file_formatted }
|
||||
|
||||
.radio
|
||||
= form.label :enabled_ do
|
||||
= form.radio_button :enabled, ''
|
||||
%strong= s_('CICD|Instance default (%{state})') % { state: "#{Gitlab::CurrentSettings.auto_devops_enabled? ? _('enabled') : _('disabled')}" }
|
||||
%br
|
||||
= s_('CICD|Follow the instance default to either have Auto DevOps enabled or disabled when there is no project specific %{ci_file}.').html_safe % { ci_file: ci_file_formatted }
|
||||
|
||||
= form.label :domain, class:"prepend-top-10" do
|
||||
= _('Domain')
|
||||
= form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
|
||||
.help-block
|
||||
= s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.')
|
||||
|
||||
= f.submit 'Save changes', class: "btn btn-success prepend-top-15"
|
|
@ -3,44 +3,6 @@
|
|||
= form_for @project, url: project_settings_ci_cd_path(@project) do |f|
|
||||
= form_errors(@project)
|
||||
%fieldset.builds-feature
|
||||
.form-group
|
||||
%h5 Auto DevOps (Beta)
|
||||
%p
|
||||
Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration.
|
||||
= link_to 'Learn more about Auto DevOps', help_page_path('topics/autodevops/index.md')
|
||||
- message = auto_devops_warning_message(@project)
|
||||
- if message
|
||||
%p.settings-message.text-center
|
||||
= message.html_safe
|
||||
= f.fields_for :auto_devops_attributes, @auto_devops do |form|
|
||||
.radio
|
||||
= form.label :enabled_true do
|
||||
= form.radio_button :enabled, 'true'
|
||||
%strong Enable Auto DevOps
|
||||
%br
|
||||
%span.descr
|
||||
The Auto DevOps pipeline configuration will be used when there is no <code>.gitlab-ci.yml</code> in the project.
|
||||
|
||||
.radio
|
||||
= form.label :enabled_false do
|
||||
= form.radio_button :enabled, 'false'
|
||||
%strong Disable Auto DevOps
|
||||
%br
|
||||
%span.descr
|
||||
An explicit <code>.gitlab-ci.yml</code> needs to be specified before you can begin using Continuous Integration and Delivery.
|
||||
|
||||
.radio
|
||||
= form.label :enabled_ do
|
||||
= form.radio_button :enabled, ''
|
||||
%strong Instance default (#{Gitlab::CurrentSettings.auto_devops_enabled? ? 'enabled' : 'disabled'})
|
||||
%br
|
||||
%span.descr
|
||||
Follow the instance default to either have Auto DevOps enabled or disabled when there is no project specific <code>.gitlab-ci.yml</code>.
|
||||
%p
|
||||
You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.
|
||||
= form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
|
||||
|
||||
%hr
|
||||
.form-group.append-bottom-default.js-secret-runner-token
|
||||
= f.label :runners_token, "Runner token", class: 'label-light'
|
||||
.form-control.js-secret-value-placeholder
|
||||
|
|
|
@ -12,10 +12,22 @@
|
|||
%button.btn.js-settings-toggle{ type: 'button' }
|
||||
= expanded ? 'Collapse' : 'Expand'
|
||||
%p
|
||||
Update your CI/CD configuration, like job timeout or Auto DevOps.
|
||||
Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report.
|
||||
.settings-content
|
||||
= render 'form'
|
||||
|
||||
%section.settings#autodevops-settings.no-animate{ class: ('expanded' if expanded) }
|
||||
.settings-header
|
||||
%h4
|
||||
= s_('CICD|Auto DevOps (Beta)')
|
||||
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
|
||||
= expanded ? _('Collapse') : _('Expand')
|
||||
%p
|
||||
= s_('CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration.')
|
||||
= link_to s_('CICD|Learn more about Auto DevOps'), help_page_path('topics/autodevops/index.md')
|
||||
.settings-content
|
||||
= render 'autodevops_form'
|
||||
|
||||
%section.settings.no-animate{ class: ('expanded' if expanded) }
|
||||
.settings-header
|
||||
%h4
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
- link = link_to(s_('AutoDevOps|Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer')
|
||||
= s_('AutoDevOps|Learn more in the %{link_to_documentation}').html_safe % { link_to_documentation: link }
|
||||
.banner-buttons
|
||||
= link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'), class: 'btn js-close-callout'
|
||||
= link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'), class: 'btn js-close-callout'
|
||||
|
||||
%button.btn-transparent.banner-close.close.js-close-callout{ type: 'button',
|
||||
'aria-label' => 'Dismiss Auto DevOps box' }
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Enable restore rake task to handle nested storage directories
|
||||
merge_request: 17516
|
||||
author: Balasankar C
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Add support for patch link extension for commit links on GitLab Flavored Markdown
|
||||
merge_request:
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Include matching branches and tags in protected branches / tags count
|
||||
merge_request:
|
||||
author: Jan Beckmann
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Send notification emails when push to a merge request
|
||||
merge_request: 7610
|
||||
author: YarNayar
|
||||
type: feature
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Adds cancel btn to new pages domain page
|
||||
merge_request: 18026
|
||||
author: Jacopo Beschi @jacopo-beschi
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Atomic generation of internal ids for issues.
|
||||
merge_request: 17580
|
||||
author:
|
||||
type: other
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Create Deploy Tokens to allow permanent access to repository and registry
|
||||
merge_request: 17894
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Prevent pipeline actions in dropdown to redirct to a new page
|
||||
merge_request:
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Drop JSON response in Project Milestone along with avoiding error
|
||||
merge_request: 17977
|
||||
author: Takuya Noguchi
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix generated URL when listing repoitories for import
|
||||
merge_request: 17692
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: lazy load diffs on merge request discussions
|
||||
merge_request:
|
||||
author:
|
||||
type: performance
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fixed bug in dropdown selector when selecting the same selection again
|
||||
merge_request: 14631
|
||||
author: bitsapien
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Apply NestingDepth (level 5) (framework/dropdowns.scss)
|
||||
merge_request: 17820
|
||||
author: Takuya Noguchi
|
||||
type: other
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: 'API: Add parameter merge_method to projects'
|
||||
merge_request: 18031
|
||||
author: Jan Beckmann
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Add object storage support for LFS objects, CI artifacts, and uploads.
|
||||
merge_request: 17358
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Increase dropdown width in pipeline graph & center action icon
|
||||
merge_request: 18089
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: 'Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436'
|
||||
merge_request: 18036
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Added confirmation modal for changing username
|
||||
merge_request: 17405
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Adds the option to the project export API to override the project description and display GitLab export description once imported
|
||||
merge_request: 17744
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: adds closed by informations in issue api
|
||||
merge_request: 17042
|
||||
author: haseebeqx
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix XSS on diff view stored on filenames
|
||||
merge_request:
|
||||
author:
|
||||
type: security
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Long instance urls do not overflow anymore during project creation
|
||||
merge_request: 17717
|
||||
author:
|
||||
type: fixed
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
title: Improved visual styles and consistency for commit hash and possible actions
|
||||
across commit lists
|
||||
merge_request: 17406
|
||||
author:
|
||||
type: changed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Improve empty state for canceled job
|
||||
merge_request: 17646
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix hover style of dropdown items in the right sidebar
|
||||
merge_request: 17519
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Show new branch/mr button even when branch exists
|
||||
merge_request: 17712
|
||||
author: Jacopo Beschi @jacopo-beschi
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix Firefox stealing formatting characters on issue notes
|
||||
merge_request:
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Fix discussions API setting created_at for notable in a group or notable in
|
||||
a project in a group with owners
|
||||
merge_request: 18464
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Improve performance of loading issues with lots of references to merge requests
|
||||
merge_request: 17986
|
||||
author:
|
||||
type: performance
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Polish design for verifying domains
|
||||
merge_request: 17767
|
||||
author:
|
||||
type: changed
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
title: Require at least one filter when listing issues or merge requests on dashboard
|
||||
page
|
||||
merge_request:
|
||||
author:
|
||||
type: performance
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Use specific names for filtered CI variable controller parameters
|
||||
merge_request: 17796
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Create settings section for autodevops
|
||||
merge_request: 18321
|
||||
author:
|
||||
type: changed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Add empty repo check before running AutoDevOps pipeline
|
||||
merge_request: 17605
|
||||
author:
|
||||
type: changed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Adds support for OmniAuth JWT provider
|
||||
merge_request: 17774
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Limit the number of failed logins when using LDAP for authentication
|
||||
merge_request: 43525
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Improves the performance of projects list page
|
||||
merge_request: 17934
|
||||
author:
|
||||
type: performance
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Move ci/lint under project's namespace
|
||||
merge_request: 17729
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Update wording to specify create/manage project vs group labels in labels dropdown
|
||||
merge_request: 17640
|
||||
author:
|
||||
type: changed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Set breadcrumb for admin/runners/show
|
||||
merge_request: 17431
|
||||
author: Takuya Noguchi
|
||||
type: fixed
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
title: Update documentation to reflect current minimum required versions of node and
|
||||
yarn
|
||||
merge_request: 17706
|
||||
author:
|
||||
type: other
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Store sha256 checksum of artifact metadata
|
||||
merge_request: 18149
|
||||
author:
|
||||
type: added
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue