// eslint-disable-next-line import/prefer-default-export
export const decodeAndParse = param => JSON.parse(window.atob(param));
......@@ -61,7 +61,7 @@ export default {
eventHub.$emit('EnablePolling');
},
updateTimer() {
this.timer = this.timer - 1;
this.timer -= 1;
if (this.timer === 0) {
this.refresh();
......
......
......@@ -192,7 +192,7 @@
.stage-events {
width: 60%;
overflow: scroll;
height: 467px;
min-height: 467px;
}
.stage-event-list {
......
......
# frozen_string_literal: true
module Mutations
module Issues
class Update < Base
graphql_name 'UpdateIssue'
# Add arguments here instead of creating separate mutations
def resolve(project_path:, iid:, **args)
issue = authorized_find!(project_path: project_path, iid: iid)
project = issue.project
::Issues::UpdateService.new(project, current_user, args).execute(issue)
{
issue: issue,
errors: issue.errors.full_messages
}
end
end
end
end
Mutations::Issues::Update.prepend_if_ee('::EE::Mutations::Issues::Update')
......@@ -11,6 +11,7 @@ module Types
mount_mutation Mutations::AwardEmojis::Toggle
mount_mutation Mutations::Issues::SetConfidential
mount_mutation Mutations::Issues::SetDueDate
mount_mutation Mutations::Issues::Update
mount_mutation Mutations::MergeRequests::SetLabels
mount_mutation Mutations::MergeRequests::SetLocked
mount_mutation Mutations::MergeRequests::SetMilestone
......
......
......@@ -2,6 +2,7 @@
- current_text ||= nil
- supports_autocomplete = local_assigns.fetch(:supports_autocomplete, true)
- supports_quick_actions = local_assigns.fetch(:supports_quick_actions, false)
- qa_selector = local_assigns.fetch(:qa_selector, '')
.zen-backdrop
- classes << ' js-gfm-input js-autosize markdown-area'
- if defined?(f) && f
......@@ -10,7 +11,8 @@
placeholder: placeholder,
dir: 'auto',
data: { supports_quick_actions: supports_quick_actions,
supports_autocomplete: supports_autocomplete }
supports_autocomplete: supports_autocomplete,
qa_selector: qa_selector }
- else
= text_area_tag attr, current_text, class: classes, placeholder: placeholder
%a.zen-control.zen-control-leave.js-zen-leave{ href: "#" }
......
......
......@@ -16,10 +16,10 @@
= f.label :description, s_("Snippets|Description (optional)"), class: 'label-bold'
.js-collapsible-input
.js-collapsed{ class: ('d-none' if is_expanded) }
= text_field_tag nil, nil, class: 'form-control', placeholder: description_placeholder
= text_field_tag nil, nil, class: 'form-control', placeholder: description_placeholder, data: { qa_selector: 'description_placeholder' }
.js-expanded{ class: ('d-none' if !is_expanded) }
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: description_placeholder
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: description_placeholder, qa_selector: 'description_field'
= render 'shared/notes/hints'
.form-group.file-editor
......
......
---
title: Time series extends axis options correctly
merge_request: 25399
author:
type: fixed
......@@ -1877,6 +1877,11 @@ type Epic implements Noteable {
"""
hasIssues: Boolean!
"""
Current health status. Available only when feature flag save_issuable_health_status is enabled.
"""
healthStatus: HealthStatus
"""
ID of the epic
"""
......@@ -2252,6 +2257,11 @@ type EpicIssue implements Noteable {
"""
epicIssueId: ID!
"""
Current health status. Available only when feature flag save_issuable_health_status is enabled.
"""
healthStatus: HealthStatus
"""
Global ID of the epic-issue relation
"""
......@@ -3059,6 +3069,15 @@ type GroupPermissions {
readGroup: Boolean!
}
"""
Health status of an issue or epic
"""
enum HealthStatus {
atRisk
needsAttention
onTrack
}
"""
State of a GitLab issue or merge request
"""
......@@ -3179,6 +3198,11 @@ type Issue implements Noteable {
"""
epic: Epic
"""
Current health status. Available only when feature flag save_issuable_health_status is enabled.
"""
healthStatus: HealthStatus
"""
Internal ID of the issue
"""
......@@ -4667,6 +4691,7 @@ type Mutation {
be destroyed during the update, and no Note will be returned
"""
updateImageDiffNote(input: UpdateImageDiffNoteInput!): UpdateImageDiffNotePayload
updateIssue(input: UpdateIssueInput!): UpdateIssuePayload
"""
Updates a Note. If the body of the Note contains only quick actions, the Note
......@@ -7601,6 +7626,11 @@ input UpdateEpicInput {
"""
groupPath: ID!
"""
The desired health status
"""
healthStatus: HealthStatus
"""
The iid of the epic to mutate
"""
......@@ -7697,6 +7727,51 @@ type UpdateImageDiffNotePayload {
note: Note
}
"""
Autogenerated input type of UpdateIssue
"""
input UpdateIssueInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
The desired health status
"""
healthStatus: HealthStatus
"""
The iid of the issue to mutate
"""
iid: String!
"""
The project the issue to mutate is in
"""
projectPath: ID!
}
"""
Autogenerated return type of UpdateIssue
"""
type UpdateIssuePayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Reasons why the mutation failed.
"""
errors: [String!]!
"""
The issue after mutation
"""
issue: Issue
}
"""
Autogenerated input type of UpdateNote
"""
......
......
......@@ -11162,6 +11162,35 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "HealthStatus",
"description": "Health status of an issue or epic",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "onTrack",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "needsAttention",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "atRisk",
"description": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DesignConnection",
......@@ -19453,6 +19482,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "updateIssue",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "UpdateIssueInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "UpdateIssuePayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "updateNote",
"description": "Updates a Note. If the body of the Note contains only quick actions, the Note will be destroyed during the update, and no Note will be returned",
......@@ -20262,6 +20318,132 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "UpdateIssuePayload",
"description": "Autogenerated return type of UpdateIssue",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Reasons why the mutation failed.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issue",
"description": "The issue after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Issue",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "UpdateIssueInput",
"description": "Autogenerated input type of UpdateIssue",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "The project the issue to mutate is in",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "iid",
"description": "The iid of the issue to mutate",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "healthStatus",
"description": "The desired health status",
"type": {
"kind": "ENUM",
"name": "HealthStatus",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "MergeRequestSetLabelsPayload",
......@@ -23906,6 +24088,16 @@
},
"defaultValue": null
},
{
"name": "healthStatus",
"description": "The desired health status",
"type": {
"kind": "ENUM",
"name": "HealthStatus",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
......
......
......@@ -293,6 +293,7 @@ Represents an epic.
| `group` | Group! | Group to which the epic belongs |
| `hasChildren` | Boolean! | Indicates if the epic has children |
| `hasIssues` | Boolean! | Indicates if the epic has direct issues |
| `healthStatus` | HealthStatus | Current health status. Available only when feature flag save_issuable_health_status is enabled. |
| `id` | ID! | ID of the epic |
| `iid` | ID! | Internal ID of the epic |
| `parent` | Epic | Parent epic of the epic |
......@@ -342,6 +343,7 @@ Relationship between an epic and an issue
| `dueDate` | Time | Due date of the issue |
| `epic` | Epic | Epic to which this issue belongs |
| `epicIssueId` | ID! | ID of the epic-issue relation |
| `healthStatus` | HealthStatus | Current health status. Available only when feature flag save_issuable_health_status is enabled. |
| `id` | ID | Global ID of the epic-issue relation |
| `iid` | ID! | Internal ID of the issue |
| `milestone` | Milestone | Milestone of the issue |
......@@ -461,6 +463,7 @@ Autogenerated return type of EpicTreeReorder
| `downvotes` | Int! | Number of downvotes the issue has received |
| `dueDate` | Time | Due date of the issue |
| `epic` | Epic | Epic to which this issue belongs |
| `healthStatus` | HealthStatus | Current health status. Available only when feature flag save_issuable_health_status is enabled. |
| `iid` | ID! | Internal ID of the issue |
| `milestone` | Milestone | Milestone of the issue |
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
......@@ -1240,6 +1243,16 @@ Autogenerated return type of UpdateImageDiffNote
| `errors` | String! => Array | Reasons why the mutation failed. |
| `note` | Note | The note after mutation |
## UpdateIssuePayload
Autogenerated return type of UpdateIssue
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Reasons why the mutation failed. |
| `issue` | Issue | The issue after mutation |
## UpdateNotePayload
Autogenerated return type of UpdateNote
......
......
......@@ -166,6 +166,43 @@ In the following example:
![Collapsible sections](img/collapsible_log_v12_6.png)
#### Custom collapsible sections
You can create collapsible sections in job logs by manually outputting special codes
that GitLab will use to determine what sections to collapse:
- Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER`
- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
You must add these codes to the script section of the CI configuration. For example,
using `echo`:
```yaml
job1:
script:
- echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section"
- echo 'this line should be hidden when collapsed'
- echo -e "section_end:`date +%s`:my_first_section\r\e[0K"
```
In the example above:
- `date +%s`: The Unix timestamp (for example `1560896352`).
- `my_first_section`: The name given to the section.
- `\r\e[0K`: Prevents the section markers from displaying in the rendered (colored)
job log, but they are displayed in the raw job log. To see them, in the top right
of the job log, click **{doc-text}** (**Show complete raw**).
- `\r`: carriage return.
- `\e[0K`: clear line ANSI escape code.
Sample raw job log:
```plaintext
section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section
this line should be hidden when collapsed
section_end:1560896353:my_first_section\r\e[0K
```
## Configuring pipelines
Pipelines, and their component jobs and stages, are defined in the [`.gitlab-ci.yml`](yaml/README.md) file for each project.
......
......
......@@ -23,6 +23,7 @@ There are two places defined variables can be used. On the:
|:-------------------------------------------|:-----------------|:-----------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `environment:url` | yes | GitLab | The variable expansion is made by GitLab's [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism).<br/><br/>Supported are all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules).<br/><br/>Not supported are variables defined in Runner's `config.toml` and variables created in job's `script`. |
| `environment:name` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
| `resource_group` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
| `variables` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `image` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `services:[]` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
......
......
......@@ -52,6 +52,30 @@ bundle exec rails db RAILS_ENV=development
- `SELECT * FROM schema_migrations WHERE version = '20170926203418';`: Check if a migration was run
- `DELETE FROM schema_migrations WHERE version = '20170926203418';`: Manually remove a migration
## Access the GDK database with Visual Studio Code
Use these instructions for exploring the GitLab database while developing with the GDK:
1. Install or open [Visual Studio Code](https://code.visualstudio.com/download).
1. Install the [PostgreSQL VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres) by Chris Kolkman.
1. In Visual Studio Code click on the PostgreSQL Explorer button in the left toolbar.
1. In the top bar of the new window, click on the `+` to **Add Database Connection**, and follow the prompts to fill in the details:
1. **Hostname**: the path to the PostgreSQL folder in your GDK directory (for example `/dev/gitlab-development-kit/postgresql`).
1. **PostgreSQL user to authenticate as**: usually your local username, unless otherwise specified during PostgreSQL installation.
1. **Password of the PostgreSQL user**: the password you set when installing PostgreSQL.
1. **Port number to connect to**: `5432` (default).
1. **Use an ssl connection?** This depends on your installation. Options are:
- **Use Secure Connection**
- **Standard Connection** (default)
1. **(Optional) The database to connect to**: `gitlabhq_development`.
1. **The display name for the database connection**: `gitlabhq_development`.
Your database connection should now be displayed in the PostgreSQL Explorer pane and
you can explore the `gitlabhq_development` database. If you cannot connect, ensure
that GDK is running. For further instructions on how to use the PostgreSQL Explorer
Extension for Visual Studio Code, read the [usage section](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres#usage)
of the extension documentation.
## FAQ
### `ActiveRecord::PendingMigrationError` with Spring
......
......
# Event tracking
# Product Analytics
At GitLab, we encourage event tracking so we can iterate on and improve the project and user experience.
......@@ -44,6 +44,8 @@ From the backend, the events that are tracked will likely consist of things like
See [Backend tracking guide](backend.md).
Also, see [Application performance metrics](../instrumentation.md) if you are after instrumenting application performance metrics.
## Enabling tracking
Tracking can be enabled at:
......
......
# Instrumenting Ruby Code
# Application Performance Metrics for Ruby Code
[GitLab Performance Monitoring](../administration/monitoring/performance/index.md) allows instrumenting of both methods and custom
blocks of Ruby code. Method instrumentation is the primary form of
instrumentation with block-based instrumentation only being used when we want to
drill down to specific regions of code within a method.
Please refer to [Product analytics](event_tracking/index.md) if you are after tracking product usage patterns.
## Instrumenting Methods
Instrumenting methods is done by using the `Gitlab::Metrics::Instrumentation`
......
......
......@@ -5,6 +5,7 @@ module Gitlab
class Blob
include Gitlab::BlobHelper
include Gitlab::EncodingHelper
include Gitlab::Metrics::Methods
extend Gitlab::Git::WrapsGitalyErrors
# This number is the maximum amount of data that we want to display to
......@@ -26,6 +27,14 @@ module Gitlab
attr_accessor :name, :path, :size, :data, :mode, :id, :commit_id, :loaded_size, :binary
define_counter :gitlab_blob_truncated_true do
docstring 'blob.truncated? == true'
end
define_counter :gitlab_blob_truncated_false do
docstring 'blob.truncated? == false'
end
class << self
def find(repository, sha, path, limit: MAX_DATA_DISPLAY_SIZE)
tree_entry(repository, sha, path, limit)
......
......
......@@ -1538,6 +1538,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
msgid "All default stages are currently visible"
msgstr ""
msgid "All email addresses will be used to identify your commits."
msgstr ""
......@@ -6110,6 +6113,9 @@ msgstr ""
msgid "Default projects limit"
msgstr ""
msgid "Default stages"
msgstr ""
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
......@@ -15727,6 +15733,9 @@ msgstr ""
msgid "Recipe"
msgstr ""
msgid "Recover hidden stage"
msgstr ""
msgid "Recovery Codes"
msgstr ""
......@@ -21561,6 +21570,30 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
msgid "VulnerabilityManagement|Change status"
msgstr ""
msgid "VulnerabilityManagement|Confirm"
msgstr ""
msgid "VulnerabilityManagement|Dismiss"
msgstr ""
msgid "VulnerabilityManagement|Resolved"
msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
msgid "Vulnerability|Class"
msgstr ""
......
......
......@@ -10,17 +10,25 @@ module QA
end
view 'app/views/shared/snippets/_form.html.haml' do
element :description_field
element :description_placeholder
element :snippet_title
element :snippet_file_name
element :create_snippet_button
end
view 'app/views/projects/_zen.html.haml' do
# This 'element' is here only to ensure the changes in the view source aren't mistakenly changed
element :_, "qa_selector = local_assigns.fetch(:qa_selector, '')" # rubocop:disable QA/ElementWithPattern
end
def fill_title(title)
fill_element :snippet_title, title
end
def fill_description(description)
fill_element :issuable_form_description, description
click_element :description_placeholder
fill_element :description_field, description
end
def set_visibility(visibility)
......
......