{{ linkExample }}
+ #{markdown(description)}" - - message.join - end - - def create_merge_request_message(data) - user_name = data[:user][:name] - - obj_attr = data[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - merge_request_id = obj_attr[:iid] - state = obj_attr[:state] - description = obj_attr[:description] - title = render_line(obj_attr[:title]) - - merge_request_url = "#{project_url}/-/merge_requests/#{merge_request_id}" - merge_request_link = "merge request !#{merge_request_id}" - message = ["#{user_name} #{state} #{merge_request_link} in " \ - "#{project_link}: #{title}"] - - message << "
#{markdown(description)}" - message.join - end - def format_title(title) "#{render_line(title)}" end - def create_note_message(data) - data = HashWithIndifferentAccess.new(data) - user_name = data[:user][:name] - - obj_attr = HashWithIndifferentAccess.new(data[:object_attributes]) - note = obj_attr[:note] - note_url = obj_attr[:url] - noteable_type = obj_attr[:noteable_type] - commit_id = nil - - case noteable_type - when "Commit" - commit_attr = HashWithIndifferentAccess.new(data[:commit]) - commit_id = commit_attr[:id] - subject_desc = commit_id - subject_desc = Commit.truncate_sha(subject_desc) - subject_type = "commit" - title = format_title(commit_attr[:message]) - when "Issue" - subj_attr = HashWithIndifferentAccess.new(data[:issue]) - subject_id = subj_attr[:iid] - subject_desc = "##{subject_id}" - subject_type = "issue" - title = format_title(subj_attr[:title]) - when "MergeRequest" - subj_attr = HashWithIndifferentAccess.new(data[:merge_request]) - subject_id = subj_attr[:iid] - subject_desc = "!#{subject_id}" - subject_type = "merge request" - title = format_title(subj_attr[:title]) - when "Snippet" - subj_attr = HashWithIndifferentAccess.new(data[:snippet]) - subject_id = subj_attr[:id] - subject_desc = "##{subject_id}" - subject_type = "snippet" - title = format_title(subj_attr[:title]) - end - - subject_html = "#{subject_type} #{subject_desc}" - message = ["#{user_name} commented on #{subject_html} in #{project_link}: "] - message << title - - message << "
#{markdown(note, ref: commit_id)}" - message.join - end - - def create_pipeline_message(data) - pipeline_attributes = data[:object_attributes] - pipeline_id = pipeline_attributes[:id] - ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch' - ref = pipeline_attributes[:ref] - user_name = (data[:user] && data[:user][:name]) || 'API' - status = pipeline_attributes[:status] - duration = pipeline_attributes[:duration] - - branch_link = "#{ref}" - pipeline_url = "##{pipeline_id}" - - "#{project_link}: Pipeline #{pipeline_url} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)" - end - def message_color(data) pipeline_status_color(data) || color || 'yellow' end @@ -309,5 +149,3 @@ class HipchatService < Service end end end - -HipchatService.prepend_if_ee('EE::HipchatService') diff --git a/app/services/post_receive_service.rb b/app/services/post_receive_service.rb index 24b19e75639..3dc8fd8929a 100644 --- a/app/services/post_receive_service.rb +++ b/app/services/post_receive_service.rb @@ -48,7 +48,7 @@ class PostReceiveService end def process_mr_push_options(push_options, changes) - Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab-foss/issues/61359') + Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/28494') return unless repository unless repository.repo_type.project? diff --git a/app/views/shared/wikis/_form.html.haml b/app/views/shared/wikis/_form.html.haml index d91e3c73c49..e121725b9af 100644 --- a/app/views/shared/wikis/_form.html.haml +++ b/app/views/shared/wikis/_form.html.haml @@ -1,79 +1,6 @@ -- form_classes = %w[wiki-form common-note-form gl-mt-3 js-quick-submit] +- page_info = { last_commit_sha: @page.last_commit_sha, persisted: @page.persisted?, title: @page.title, content: @page.content || '', format: @page.format.to_s, uploads_path: uploads_path, path: wiki_page_path(@wiki, @page), wiki_path: wiki_path(@wiki), help_path: help_page_path('user/project/wiki/index'), markdown_help_path: help_page_path('user/markdown'), markdown_preview_path: wiki_page_path(@wiki, @page, action: :preview_markdown), create_path: wiki_path(@wiki, action: :create) } -- if @page.persisted? - - form_action = wiki_page_path(@wiki, @page) - - form_method = :put -- else - - form_action = wiki_path(@wiki, action: :create) - - form_method = :post - - form_classes << 'js-new-wiki-page' - -= form_for @page, url: form_action, method: form_method, - html: { class: form_classes }, - data: { uploads_path: uploads_path } do |f| +.gl-mt-3 = form_errors(@page, truncate: :title) - - if @page.persisted? - = f.hidden_field :last_commit_sha, value: @page.last_commit_sha - - .form-group.row - .col-sm-2.col-form-label= f.label :title, class: 'control-label-full-width' - .col-sm-10 - = f.text_field :title, class: 'form-control qa-wiki-title-textbox', value: @page.title, required: true, autofocus: !@page.persisted?, placeholder: s_('Wiki|Page title') - %span.gl-display-inline-block.gl-max-w-full.gl-mt-2.gl-text-gray-600 - = sprite_icon('bulb', size: 12, css_class: 'gl-mr-n1') - - if @page.persisted? - = s_("WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title.") - = link_to sprite_icon('question-o'), help_page_path('user/project/wiki/index', anchor: 'moving-a-wiki-page'), - target: '_blank', rel: 'noopener noreferrer' - - else - = s_("WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories.") - = succeed '.' do - = link_to _('More information'), help_page_path('user/project/wiki/index', anchor: 'creating-a-new-wiki-page'), - target: '_blank', rel: 'noopener noreferrer' - .form-group.row - .col-sm-2.col-form-label= f.label :format, class: 'control-label-full-width' - .col-sm-10 - .select-wrapper - = f.select :format, options_for_select(Wiki::MARKUPS, {selected: @page.format}), {}, class: 'form-control select-control' - = sprite_icon('chevron-down', css_class: 'gl-absolute gl-top-3 gl-right-3 gl-text-gray-200') - - .form-group.row - .col-sm-2.col-form-label= f.label :content, class: 'control-label-full-width' - .col-sm-10 - = render layout: 'shared/md_preview', locals: { url: wiki_page_path(@wiki, @page, action: :preview_markdown) } do - = render 'shared/zen', f: f, attr: :content, classes: 'note-textarea qa-wiki-content-textarea', placeholder: s_("WikiPage|Write your content or drag files here…"), autofocus: @page.persisted? - = render 'shared/notes/hints' - - .clearfix - .error-alert - - .form-text.gl-text-gray-600 - = succeed '.' do - - case @page.format.to_s - - when 'rdoc' - - link_example = '{Link title}[link:page-slug]' - - when 'asciidoc' - - link_example = 'link:page-slug[Link title]' - - when 'org' - - link_example = '[[page-slug]]' - - else - - link_example = '[Link Title](page-slug)' - = html_escape(s_('WikiMarkdownTip|To link to a (new) page, simply type %{link_example}')) % { link_example: tag.code(link_example, class: 'js-markup-link-example') } - = succeed '.' do - - markdown_link = link_to s_("WikiMarkdownDocs|documentation"), help_page_path('user/markdown', anchor: 'wiki-specific-markdown') - = (s_("WikiMarkdownDocs|More examples are in the %{docs_link}") % { docs_link: markdown_link }).html_safe - - .form-group.row - .col-sm-2.col-form-label= f.label :commit_message, class: 'control-label-full-width' - .col-sm-10= f.text_field :message, class: 'form-control qa-wiki-message-textbox', rows: 18, value: nil - - .form-actions - - if @page && @page.persisted? - = f.submit _("Save changes"), class: 'btn gl-button btn-confirm qa-save-changes-button js-wiki-btn-submit', disabled: 'true' - .float-right - = link_to _("Cancel"), wiki_page_path(@wiki, @page), class: 'btn gl-button btn-cancel btn-default' - - else - = f.submit s_("Wiki|Create page"), class: 'btn-confirm gl-button btn qa-create-page-button rspec-create-page-button js-wiki-btn-submit', disabled: 'true' - .float-right - = link_to _("Cancel"), wiki_path(@wiki), class: 'btn gl-button btn-cancel btn-default' +#js-wiki-form{ data: { page_info: page_info.to_json, format_options: Wiki::MARKUPS.to_json } } diff --git a/changelogs/unreleased/hchouraria-backup-repository-empty-repo-skipped.yml b/changelogs/unreleased/hchouraria-backup-repository-empty-repo-skipped.yml new file mode 100644 index 00000000000..272457a0059 --- /dev/null +++ b/changelogs/unreleased/hchouraria-backup-repository-empty-repo-skipped.yml @@ -0,0 +1,5 @@ +--- +title: Add message for repository backup skip +merge_request: 54285 +author: +type: other diff --git a/changelogs/unreleased/remove_hipchat_gem.yml b/changelogs/unreleased/remove_hipchat_gem.yml new file mode 100644 index 00000000000..21a5db3bb5a --- /dev/null +++ b/changelogs/unreleased/remove_hipchat_gem.yml @@ -0,0 +1,5 @@ +--- +title: Make HipChat project service do nothing +merge_request: 57434 +author: +type: removed diff --git a/changelogs/unreleased/update-contribution-tooltip.yml b/changelogs/unreleased/update-contribution-tooltip.yml new file mode 100644 index 00000000000..d1962a5cac0 --- /dev/null +++ b/changelogs/unreleased/update-contribution-tooltip.yml @@ -0,0 +1,5 @@ +--- +title: Add multi-line styling within contribution tooltip +merge_request: 54765 +author: Yogi (@yo) +type: changed diff --git a/config/initializers/hipchat_client_patch.rb b/config/initializers/hipchat_client_patch.rb deleted file mode 100644 index 51bd48af320..00000000000 --- a/config/initializers/hipchat_client_patch.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true -# This monkey patches the HTTParty used in https://github.com/hipchat/hipchat-rb. -module HipChat - class Client - connection_adapter ::Gitlab::HTTPConnectionAdapter - end - - class Room - connection_adapter ::Gitlab::HTTPConnectionAdapter - end - - class User - connection_adapter ::Gitlab::HTTPConnectionAdapter - end -end diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md index 661fa67220d..7fd457cd07d 100644 --- a/doc/administration/job_artifacts.md +++ b/doc/administration/job_artifacts.md @@ -89,7 +89,7 @@ _The artifacts are stored by default in > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1762) in > [GitLab Premium](https://about.gitlab.com/pricing/) 9.4. -> - Since version 9.5, artifacts are [browsable](../ci/pipelines/job_artifacts.md#browsing-artifacts), +> - Since version 9.5, artifacts are [browsable](../ci/pipelines/job_artifacts.md#download-job-artifacts), > when object storage is enabled. 9.4 lacks this feature. > - Since version 10.6, available in [GitLab Free](https://about.gitlab.com/pricing/). > - Since version 11.0, we support `direct_upload` to S3. @@ -509,7 +509,7 @@ If you need to manually remove job artifacts associated with multiple jobs while NOTE: This step also erases artifacts that users have chosen to - ["keep"](../ci/pipelines/job_artifacts.md#browsing-artifacts). + ["keep"](../ci/pipelines/job_artifacts.md#download-job-artifacts). ```ruby builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.week.ago) @@ -583,3 +583,21 @@ If you need to manually remove **all** job artifacts associated with multiple jo - `7.days.ago` - `3.months.ago` - `1.year.ago` + +### Error `Downloading artifacts from coordinator... not found` + +When a job tries to download artifacts from an earlier job, you might receive an error similar to: + +```plaintext +Downloading artifacts from coordinator... not found id=12345678 responseStatus=404 Not Found +``` + +This might be caused by a `gitlab.rb` file with the following configuration: + +```ruby +gitlab_rails['artifacts_object_store_background_upload'] = false +gitlab_rails['artifacts_object_store_direct_upload'] = true +``` + +To prevent this, comment out or remove those lines, or switch to their [default values](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template), +then run `sudo gitlab-ctl reconfigure`. diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index 6fba192e794..8181c13aca0 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -487,7 +487,7 @@ internet connectivity is gated by a proxy. To use a proxy for GitLab Pages: ### Using a custom Certificate Authority (CA) When using certificates issued by a custom CA, [Access Control](../../user/project/pages/pages_access_control.md#gitlab-pages-access-control) and -the [online view of HTML job artifacts](../../ci/pipelines/job_artifacts.md#browsing-artifacts) +the [online view of HTML job artifacts](../../ci/pipelines/job_artifacts.md#download-job-artifacts) fails to work if the custom CA is not recognized. This usually results in this error: diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md index cf8e4e71534..72266cce3e6 100644 --- a/doc/ci/pipelines/job_artifacts.md +++ b/doc/ci/pipelines/job_artifacts.md @@ -8,25 +8,19 @@ type: reference, howto # Job artifacts -> - Introduced in GitLab 8.2 and GitLab Runner 0.7.0. -> - Starting with GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format changed to `ZIP`, and it's now possible to browse its contents, with the added ability of downloading the files separately. -> - In GitLab 8.17, builds were renamed to jobs. -> - The artifacts browser is available only for new artifacts that are sent to GitLab using GitLab Runner version 1.0 and up. You cannot browse old artifacts already uploaded to GitLab. +> Introduced in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675), artifacts in internal and private projects can be previewed when [GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled. -Job artifacts are a list of files and directories created by a job -once it finishes. This feature is [enabled by default](../../administration/job_artifacts.md) in all -GitLab installations. +Jobs can output an archive of files and directories. This output is known as a job artifact. -Job artifacts created by GitLab Runner are uploaded to GitLab and are downloadable as a single archive using the GitLab UI or the [GitLab API](../../api/job_artifacts.md#get-job-artifacts). +You can download job artifacts by using the GitLab UI or the [API](../../api/job_artifacts.md#get-job-artifacts). For an overview, watch the video [GitLab CI Pipeline, Artifacts, and Environments](https://www.youtube.com/watch?v=PCKDICEe10s). Watch also [GitLab CI pipeline tutorial for beginners](https://www.youtube.com/watch?v=Jav4vbUrqII). -## Defining artifacts in `.gitlab-ci.yml` +## Define artifacts in the `.gitlab-ci.yml` file -A simple example of using the artifacts definition in `.gitlab-ci.yml` would be -the following: +This example shows how to configure your `.gitlab-ci.yml` file to create job artifacts: ```yaml pdf: @@ -38,19 +32,169 @@ pdf: ``` A job named `pdf` calls the `xelatex` command to build a PDF file from the -latex source file `mycv.tex`. We then define the `artifacts` paths which in -turn are defined with the `paths` keyword. All paths to files and directories -are relative to the repository that was cloned during the build. +LaTeX source file, `mycv.tex`. -By default, the artifacts upload when the job succeeds. You can also set artifacts to upload -when the job fails, or always, by using [`artifacts:when`](../yaml/README.md#artifactswhen) -keyword. GitLab keeps these uploaded artifacts for 1 week, as defined -by the `expire_in` definition. You can keep the artifacts from expiring -via the [web interface](#browsing-artifacts). If the expiry time is not defined, it defaults -to the [instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration). +The `paths` keyword determines which files to add to the job artifacts. +All paths to files and directories are relative to the repository where the job was created. -For more examples on artifacts, follow the [artifacts reference in -`.gitlab-ci.yml`](../yaml/README.md#artifacts). +The `expire_in` keyword determines how long GitLab keeps the job artifacts. +You can also [use the UI to keep job artifacts from expiring](#download-job-artifacts). +If `expire_in` is not defined, the +[instance-wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration) +is used. + +For more examples, view the [keyword reference for the `.gitlab-ci.yml` file](../yaml/README.md#artifacts). + +## Download job artifacts + +You can download job artifacts or view the job archive: + +- On the **Pipelines** page, to the right of the pipeline: + + ![Job artifacts in Pipelines page](img/job_artifacts_pipelines_page.png) + +- On the **Jobs** page, to the right of the job: + + ![Job artifacts in Builds page](img/job_artifacts_builds_page.png) + +- On a job's detail page. The **Keep** button indicates an `expire_in` value was set: + + ![Job artifacts browser button](img/job_artifacts_browser_button.png) + +- On a merge request, by the pipeline details: + + ![Job artifacts in Merge Request](img/job_artifacts_merge_request.png) + +- When browsing an archive: + + ![Job artifacts browser](img/job_artifacts_browser.png) + + If [GitLab Pages](../../administration/pages/index.md) is enabled in the project, you can preview + HTML files in the artifacts directly in your browser. If the project is internal or private, you must + enable [GitLab Pages access control](../../administration/pages/index.md#access-control) to preview + HTML files. + +## View failed job artifacts + +If the latest job has failed to upload the artifacts, you can see that +information in the UI. + +![Latest artifacts button](img/job_latest_artifacts_browser.png) + +## Erase job artifacts + +WARNING: +This is a destructive action that leads to data loss. Use with caution. + +You can erase a single job, which also removes the job's +artifacts and log. You must be: + +- The owner of the job. +- A [Maintainer](../../user/permissions.md#gitlab-cicd-permissions) of the project. + +To erase a job: + +1. Go to a job's detail page. +1. At the top right of the job's log, select the trash icon. +1. Confirm the deletion. + +## Use GitLab CI/CD to retrieve job artifacts for private projects + +To retrieve a job artifact from a different project, you might need to use a +private token to [authenticate and download](../../api/job_artifacts.md#get-job-artifacts) +the artifact. + +## The latest job artifacts + +Job artifacts created in the most recent successful pipeline for a specific ref +are considered the latest artifacts. If you run two types of pipelines for the same ref, +timing determines which artifacts are the latest. + +For example, if a merge request creates a branch pipeline at the same time as +a scheduled pipeline, the pipeline that finished most recently creates the latest job artifact. + +In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/201784) and later, artifacts +for [parent and child pipelines](../parent_child_pipelines.md) are searched in hierarchical +order from parent to child. For example, if both parent and child pipelines have a +job with the same name, the job artifact from the parent pipeline is returned. + +## Access the latest job artifacts by URL + +You can download the latest job artifacts by using a URL. + +To download the whole artifacts archive: + +```plaintext +https://example.com/