Коммит 07a5db4d создал по автору Ben Bodenmiller's avatar Ben Bodenmiller Зафиксировано автором Ben Bodenmiller
Просмотр файлов

Jenkins for all

владелец 0800baa1
......@@ -164,6 +164,7 @@ class Project < ApplicationRecord
has_one :bamboo_service
has_one :teamcity_service
has_one :pushover_service
has_one :jenkins_service
has_one :jira_service
has_one :redmine_service
has_one :youtrack_service
......
......@@ -17,6 +17,10 @@ class Service < ApplicationRecord
pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack
].freeze
PROJECT_SPECIFIC_SERVICE_NAMES = %w[
jenkins
].freeze
# Fake services to help with local development.
DEV_SERVICE_NAMES = %w[
mock_ci mock_deployment mock_monitoring
......@@ -212,7 +216,7 @@ def self.dev_services_names
end
def self.project_specific_services_names
[]
PROJECT_SPECIFIC_SERVICE_NAMES
end
def self.available_services_types(include_project_specific: true, include_dev: true)
......
---
title: Move Jenkins to Core
merge_request: 37797
author: Ben Bodenmiller (@bbodenmiller)
type: changed
......@@ -23,23 +23,12 @@ alternative authentication methods to your users.
### Remove Service Integration entries from the database
The `JenkinsService` and `GithubService` classes are only available in the Enterprise Edition codebase,
The `GithubService` class is only available in the Enterprise Edition codebase,
so if you downgrade to the Community Edition, the following error displays:
```plaintext
Completed 500 Internal Server Error in 497ms (ActiveRecord: 32.2ms)
ActionView::Template::Error (The single-table inheritance mechanism failed to locate the subclass: 'JenkinsService'. This
error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this
column if you didn't intend it to be used for storing the inheritance class or overwrite Service.inheritance_column to
use another column for that information.)
```
or
```plaintext
Completed 500 Internal Server Error in 497ms (ActiveRecord: 32.2ms)
ActionView::Template::Error (The single-table inheritance mechanism failed to locate the subclass: 'GithubService'. This
error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this
column if you didn't intend it to be used for storing the inheritance class or overwrite Service.inheritance_column to
......@@ -48,22 +37,23 @@ use another column for that information.)
All services are created automatically for every project you have, so in order
to avoid getting this error, you need to remove all instances of the
`JenkinsService` and `GithubService` from your database:
`GithubService` from your database:
**Omnibus Installation**
```shell
sudo gitlab-rails runner "Service.where(type: ['JenkinsService', 'GithubService']).delete_all"
sudo gitlab-rails runner "Service.where(type: ['GithubService']).delete_all"
```
**Source Installation**
```shell
bundle exec rails runner "Service.where(type: ['JenkinsService', 'GithubService']).delete_all" production
bundle exec rails runner "Service.where(type: ['GithubService']).delete_all" production
```
NOTE: **Note:**
If you are running `GitLab =< v13.0` you need to also remove `JenkinsDeprecatedService` records.
If you are running `GitLab =< v13.0` you need to also remove `JenkinsDeprecatedService` records
and if you are running `GitLab =< v13.6` you need to also remove `JenkinsService` records.
### Variables environment scopes
......
......@@ -43,7 +43,7 @@ GitLab also provides features to improve the security of your own application. F
GitLab can be integrated with the following external service for continuous integration:
- [Jenkins](jenkins.md) CI. **(STARTER)**
- [Jenkins](jenkins.md) CI.
## Feature enhancements
......
......@@ -4,7 +4,7 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Jenkins CI service **(STARTER)**
# Jenkins CI service
NOTE: **Note:**
This documentation focuses only on how to **configure** a Jenkins *integration* with
......@@ -73,11 +73,11 @@ Create a personal access token to authorize Jenkins' access to GitLab.
1. Click **Access Tokens** in the sidebar.
1. Create a personal access token with the **API** scope checkbox checked. For more details, see
[Personal access tokens](../user/profile/personal_access_tokens.md).
1. Record the personal access token's value, because it's required in [Configure the Jenkins server](#configure-the-jenkins-server).
1. Record the personal access token's value, because it's required in [Configure the Jenkins server](#configure-the-jenkins-server) section.
## Configure the Jenkins server
Install and configure the Jenkins plugins. Both plugins must be installed and configured to
Install and configure the Jenkins plugin. The plugin must be installed and configured to
authorize the connection to GitLab.
1. On the Jenkins server, go to **Manage Jenkins > Manage Plugins**.
......@@ -137,6 +137,8 @@ Set up the Jenkins project you intend to run your build on.
Configure the GitLab integration with Jenkins.
### Option 1: Jenkins integration (recommended)
1. Create a new GitLab project or choose an existing one.
1. Go to **Settings > Integrations**, then select **Jenkins CI**.
1. Turn on the **Active** toggle.
......@@ -154,6 +156,14 @@ Configure the GitLab integration with Jenkins.
authentication.
1. Click **Test settings and save changes**. GitLab tests the connection to Jenkins.
### Option 2: Webhook
1. In the configuration of your Jenkins job, in the GitLab configuration section, click **Advanced**.
1. Click the **Generate** button under the **Secret Token** field.
1. Copy the resulting token, and save the job configuration.
1. In GitLab, create a webhook for your project, enter the trigger URL (e.g. `https://JENKINS_URL/project/YOUR_JOB`) and paste the token in the **Secret Token** field.
1. After you add the webhook, click the **Test** button, and it should succeed.
## Troubleshooting
### Error in merge requests - "Could not connect to the CI server"
......
......@@ -38,7 +38,6 @@ module Project
has_one :push_rule, ->(project) { project&.feature_available?(:push_rules) ? all : none }
has_one :index_status
has_one :jenkins_service
has_one :github_service
has_one :gitlab_slack_application_service
......@@ -581,7 +580,6 @@ def merge_requests_ff_only_enabled
def disabled_services
strong_memoize(:disabled_services) do
super.tap do |services|
services.push('jenkins') unless feature_available?(:jenkins_integration)
services.push('github') unless feature_available?(:github_project_service_integration)
::Gitlab::CurrentSettings.slack_app_enabled ? services.push('slack_slash_commands') : services.push('gitlab_slack_application')
end
......
......@@ -10,7 +10,6 @@ module Service
EE_PROJECT_SPECIFIC_SERVICE_NAMES = %w[
github
jenkins
].freeze
class_methods do
......
......@@ -26,7 +26,6 @@ class License < ApplicationRecord
issuable_default_templates
issue_weights
iterations
jenkins_integration
ldap_group_sync
member_lock
merge_request_approvers
......
......@@ -31,32 +31,6 @@ def services
type: ::API::Services::Boolean,
desc: 'Append instance name instead of branch to status check name'
}
],
'jenkins' => [
{
required: true,
name: :jenkins_url,
type: String,
desc: 'Jenkins root URL like https://jenkins.example.com'
},
{
required: true,
name: :project_name,
type: String,
desc: 'The URL-friendly project name. Example: my_project_name'
},
{
required: false,
name: :username,
type: String,
desc: 'A user with access to the Jenkins server, if applicable'
},
{
required: false,
name: :password,
type: String,
desc: 'The password of the user'
}
]
)
end
......@@ -65,7 +39,6 @@ def services
def service_classes
[
::GithubService,
::JenkinsService,
*super
]
end
......
......@@ -29,7 +29,7 @@
context 'Sets correct services list' do
let(:active_services) { assigns(:services).map(&:type) }
let(:disabled_services) { %w(JenkinsService) }
let(:disabled_services) { %w[GithubService] }
it 'enables SlackSlashCommandsService and disables GitlabSlackApplication' do
get :show, params: { namespace_id: project.namespace, project_id: project }
......@@ -60,26 +60,21 @@
let(:namespace) { create(:group, :private) }
let(:project) { create(:project, :private, namespace: namespace) }
context 'when checking of namespace plan is enabled' do
before do
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:should_check_namespace_plan?) { true }
end
before do
create(:license, plan: ::License::PREMIUM_PLAN)
end
context 'and namespace does not have a plan' do
it_behaves_like 'endpoint with some disabled services'
context 'when checking if namespace plan is enabled' do
before do
stub_application_setting(check_namespace_plan: true)
end
context 'and namespace has a plan' do
let(:namespace) { create(:group, :private) }
let!(:gitlab_subscription) { create(:gitlab_subscription, :bronze, namespace: namespace) }
it_behaves_like 'endpoint without disabled services'
end
it_behaves_like 'endpoint with some disabled services'
end
context 'when checking of namespace plan is not enabled' do
context 'when checking if namespace plan is not enabled' do
before do
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:should_check_namespace_plan?) { false }
stub_application_setting(check_namespace_plan: false)
end
it_behaves_like 'endpoint without disabled services'
......
......@@ -37,7 +37,6 @@
create(:prometheus_alert, project: projects[0])
create(:prometheus_alert, project: projects[1])
create(:service, project: projects[1], type: 'JenkinsService', active: true)
create(:jira_service, project: projects[0], issues_enabled: true, project_key: 'GL')
create(:operations_feature_flag, project: projects[0])
......@@ -104,7 +103,6 @@
operations_dashboard_default_dashboard
operations_dashboard_users_with_projects_added
pod_logs_usages_total
projects_jenkins_active
projects_jira_issuelist_active
projects_mirrored_with_pipelines_enabled
projects_reporting_ci_cd_back_to_github
......@@ -122,7 +120,6 @@
network_policy_drops
))
expect(count_data[:projects_jenkins_active]).to eq(1)
expect(count_data[:projects_with_prometheus_alerts]).to eq(2)
expect(count_data[:feature_flags]).to eq(1)
expect(count_data[:status_page_projects]).to eq(1)
......
......@@ -1312,7 +1312,6 @@
subject { project.disabled_services }
where(:license_feature, :disabled_services) do
:jenkins_integration | %w(jenkins)
:github_project_service_integration | %w(github)
end
......
......@@ -3,15 +3,8 @@
require 'spec_helper'
RSpec.describe Service do
let(:ee_project_services) do
%w[
github
jenkins
]
end
describe '.available_services_names' do
it { expect(described_class.available_services_names).to include(*ee_project_services) }
it { expect(described_class.available_services_names).to include('github') }
end
describe '.project_specific_services_names' do
......@@ -22,13 +15,13 @@
context 'when not on gitlab.com' do
let(:com) { false }
it { expect(described_class.project_specific_services_names).to match_array(ee_project_services) }
it { expect(described_class.project_specific_services_names).to include('github') }
end
context 'when on gitlab.com' do
let(:com) { true }
it { expect(described_class.project_specific_services_names).to match_array(ee_project_services + ['gitlab_slack_application']) }
it { expect(described_class.project_specific_services_names).to include('github', 'gitlab_slack_application') }
end
end
end
......@@ -459,6 +459,32 @@ def self.services
desc: 'Colorize messages'
}
],
'jenkins' => [
{
required: true,
name: :jenkins_url,
type: String,
desc: 'Jenkins root URL like https://jenkins.example.com'
},
{
required: true,
name: :project_name,
type: String,
desc: 'The URL-friendly project name. Example: my_project_name'
},
{
required: false,
name: :username,
type: String,
desc: 'A user with access to the Jenkins server, if applicable'
},
{
required: false,
name: :password,
type: String,
desc: 'The password of the user'
}
],
'jira' => [
{
required: true,
......@@ -767,6 +793,7 @@ def self.service_classes
::HangoutsChatService,
::HipchatService,
::IrkerService,
::JenkinsService,
::JiraService,
::MattermostSlashCommandsService,
::SlackSlashCommandsService,
......
......@@ -307,14 +307,12 @@ module Settings
module Services
autoload :Jira, 'qa/page/project/settings/services/jira'
autoload :Jenkins, 'qa/page/project/settings/services/jenkins'
autoload :Prometheus, 'qa/page/project/settings/services/prometheus'
end
autoload :Operations, 'qa/page/project/settings/operations'
autoload :Incidents, 'qa/page/project/settings/incidents'
autoload :Integrations, 'qa/page/project/settings/integrations'
module Services
autoload :Prometheus, 'qa/page/project/settings/services/prometheus'
end
end
module SubMenus
......
......@@ -142,10 +142,6 @@ module Settings
autoload :Repository, 'qa/ee/page/project/settings/repository'
autoload :PushRules, 'qa/ee/page/project/settings/push_rules'
autoload :LicenseCompliance, 'qa/ee/page/project/settings/license_compliance'
module Services
autoload :Jenkins, 'qa/ee/page/project/settings/services/jenkins'
end
end
module Operations
......
# frozen_string_literal: true
module QA
module EE
module Page
module Project
module Settings
module Services
class Jenkins < QA::Page::Base
view 'app/assets/javascripts/integrations/edit/components/dynamic_field.vue' do
element :jenkins_url_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :project_name_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :username_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :password_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do
element :save_changes_button
end
def setup_service_with(jenkins_url:, project_name:)
set_jenkins_url(jenkins_url)
set_project_name(project_name)
set_username('admin')
set_password('password')
click_save_changes_button
end
private
def set_jenkins_url(jenkins_url)
fill_element(:jenkins_url_field, jenkins_url)
end
def set_project_name(project_name)
fill_element(:project_name_field, project_name)
end
def set_username(username)
fill_element(:username_field, username)
end
def set_password(password)
fill_element(:password_field, password)
end
def click_save_changes_button
click_element :save_changes_button
end
end
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module Page
module Project
module Settings
module Services
class Jenkins < QA::Page::Base
view 'app/assets/javascripts/integrations/edit/components/dynamic_field.vue' do
element :jenkins_url_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :project_name_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :username_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :password_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do
element :save_changes_button
end
def setup_service_with(jenkins_url:, project_name:)
set_jenkins_url(jenkins_url)
set_project_name(project_name)
set_username('admin')
set_password('password')
click_save_changes_button
end
private
def set_jenkins_url(jenkins_url)
fill_element(:jenkins_url_field, jenkins_url)
end
def set_project_name(project_name)
fill_element(:project_name_field, project_name)
end
def set_username(username)
fill_element(:username_field, username)
end
def set_password(password)
fill_element(:password_field, password)
end
def click_save_changes_button
click_element :save_changes_button
end
end
end
end
end
end
end
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать