Skip to content

Commit 09f35b5

Browse files
authored
Merge pull request #26 from gtt-project/ftr/support-test-and-ci
Support Test and CI
2 parents 194723c + 8bc320d commit 09f35b5

File tree

17 files changed

+851
-40
lines changed

17 files changed

+851
-40
lines changed

.github/workflows/test.yml

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
name: Test
2+
3+
env:
4+
PLUGIN_NAME: ${{ github.event.repository.name }}
5+
6+
on:
7+
push:
8+
branches:
9+
- main
10+
- next
11+
pull_request:
12+
branches:
13+
- main
14+
- next
15+
workflow_dispatch:
16+
17+
jobs:
18+
test:
19+
name: redmine:${{ matrix.redmine_version }} ruby:${{ matrix.ruby_version }} db:${{ matrix.db }}
20+
runs-on: ubuntu-22.04
21+
22+
container:
23+
image: ruby:${{ matrix.ruby_version }}-bullseye
24+
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
redmine_version: [4.2-stable, 5.0-stable, 5.1-stable, master]
29+
ruby_version: ['2.7', '3.0', '3.1', '3.2']
30+
db: [mysql, postgres, sqlite]
31+
# System test takes 2~3 times longer, so limit to specific matrix combinations
32+
# See: https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#expanding-or-adding-matrix-configurations
33+
include:
34+
- system_test: true
35+
redmine_version: 5.1-stable
36+
ruby_version: '3.2'
37+
db: mysql
38+
exclude:
39+
- redmine_version: 4.2-stable
40+
ruby_version: '3.0'
41+
- redmine_version: 4.2-stable
42+
ruby_version: '3.1'
43+
- redmine_version: 4.2-stable
44+
ruby_version: '3.2'
45+
- redmine_version: 5.0-stable
46+
ruby_version: '3.2'
47+
- redmine_version: master
48+
ruby_version: '2.7'
49+
50+
services:
51+
mysql:
52+
image: mysql:5.7 # min
53+
# image: mysql:8.0 # latest
54+
env:
55+
MYSQL_ROOT_PASSWORD: password
56+
ports:
57+
- 3306:3306
58+
options: --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 5
59+
postgres:
60+
image: postgres:10 # min
61+
# image: postgres:15 # latest
62+
env:
63+
POSTGRES_USER: postgres
64+
POSTGRES_PASSWORD: postgres
65+
ports:
66+
- 5432:5432
67+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
68+
69+
steps:
70+
- name: Checkout Redmine
71+
uses: actions/checkout@v4
72+
with:
73+
repository: redmine/redmine
74+
ref: ${{ matrix.redmine_version }}
75+
path: redmine
76+
77+
- name: Checkout Plugin
78+
uses: actions/checkout@v4
79+
with:
80+
path: redmine/plugins/${{ env.PLUGIN_NAME }}
81+
82+
- name: Update package archives
83+
run: apt-get update --yes --quiet
84+
85+
- name: Install package dependencies
86+
run: |
87+
if [ ${{ matrix.db }} = "mysql" ]; then
88+
apt-get install --yes --quiet default-mysql-client-core
89+
fi
90+
if [ ${{ matrix.db }} = "postgres" ]; then
91+
apt-get install --yes --quiet postgresql-client
92+
fi
93+
# For system test
94+
if [ ${{ matrix.system_test }} = "true" ]; then
95+
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
96+
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
97+
apt-get -y update
98+
apt-get install -y google-chrome-stable
99+
fi
100+
101+
- name: Verify MySQL connection from host
102+
if: matrix.db == 'mysql'
103+
run: |
104+
mysql --host mysql --port 3306 -uroot -ppassword -e "SHOW DATABASES"
105+
106+
- name: Prepare Redmine source
107+
working-directory: redmine
108+
run: |
109+
if [ ${{ matrix.db }} = "mysql" ]; then
110+
cat <<EOF > config/database.yml
111+
test:
112+
adapter: mysql2
113+
database: redmine
114+
host: mysql
115+
username: root
116+
password: password
117+
encoding: utf8mb4
118+
EOF
119+
fi
120+
if [ ${{ matrix.db }} = "postgres" ]; then
121+
cat <<EOF > config/database.yml
122+
test:
123+
adapter: postgresql
124+
database: redmine
125+
host: postgres
126+
username: postgres
127+
password: postgres
128+
encoding: utf8
129+
EOF
130+
fi
131+
if [ ${{ matrix.db }} = "sqlite" ]; then
132+
cat <<EOF > config/database.yml
133+
test:
134+
adapter: sqlite3
135+
database: db/redmine.sqlite3
136+
EOF
137+
fi
138+
139+
- name: Install Ruby dependencies
140+
working-directory: redmine
141+
run: |
142+
bundle config set --local without 'development'
143+
bundle install --jobs=4 --retry=3
144+
145+
- name: Run Redmine rake tasks
146+
env:
147+
RAILS_ENV: test
148+
working-directory: redmine
149+
run: |
150+
bundle exec rake generate_secret_token
151+
bundle exec rake db:create db:migrate redmine:plugins:migrate
152+
153+
- name: Zeitwerk check
154+
env:
155+
RAILS_ENV: test
156+
working-directory: redmine
157+
run: |
158+
if grep -q zeitwerk config/application.rb ; then
159+
bundle exec rake zeitwerk:check
160+
fi
161+
shell: bash
162+
163+
- name: Run plugin tests
164+
env:
165+
RAILS_ENV: test
166+
# For system test in plugin
167+
GOOGLE_CHROME_OPTS_ARGS: "headless,disable-gpu,no-sandbox,disable-dev-shm-usage"
168+
working-directory: redmine
169+
run: |
170+
bundle exec rake redmine:plugins:test:units NAME=${{ env.PLUGIN_NAME }} RUBYOPT="-W0"
171+
bundle exec rake redmine:plugins:test:functionals NAME=${{ env.PLUGIN_NAME }} RUBYOPT="-W0"
172+
bundle exec rake redmine:plugins:test:integration NAME=${{ env.PLUGIN_NAME }} RUBYOPT="-W0"
173+
if [ ${{ matrix.system_test }} = "true" ]; then
174+
bundle exec rake redmine:plugins:test:system NAME=${{ env.PLUGIN_NAME }} RUBYOPT="-W0"
175+
fi
176+
177+
# - name: Run core tests
178+
# env:
179+
# RAILS_ENV: test
180+
# PARALLEL_WORKERS: 1
181+
# working-directory: redmine
182+
# run: bundle exec rake test
183+
184+
# - name: Run core system tests
185+
# if: matrix.system_test == true
186+
# env:
187+
# RAILS_ENV: test
188+
# GOOGLE_CHROME_OPTS_ARGS: "headless,disable-gpu,no-sandbox,disable-dev-shm-usage"
189+
# working-directory: redmine
190+
# run: bundle exec rake test:system
191+
192+
- name: Run uninstall test
193+
env:
194+
RAILS_ENV: test
195+
working-directory: redmine
196+
run: bundle exec rake redmine:plugins:migrate NAME=${{ env.PLUGIN_NAME }} VERSION=0

app/controllers/custom_fields_groups_controller.rb

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,68 @@ class CustomFieldsGroupsController < ApplicationController
22
layout 'admin'
33

44
before_action :require_admin
5+
before_action :find_custom_fields_group, only: %i[edit update destroy]
56

67
def index
78
@custom_fields_groups = CustomFieldsGroup.sorted
89
end
910

1011
def new
1112
@custom_fields_group = CustomFieldsGroup.new
12-
# @custom_fields_group.custom_fields_group_fields.build
1313
end
1414

1515
def create
16-
@custom_fields_group = CustomFieldsGroup.new(custom_fields_group_params)
17-
18-
ActiveRecord::Base.transaction do
19-
@custom_fields_group.save!
16+
@custom_fields_group = CustomFieldsGroup.new
17+
@custom_fields_group.safe_attributes = custom_fields_group_params
18+
if @custom_fields_group.save
19+
flash[:notice] = l(:notice_successful_create)
20+
redirect_to custom_fields_groups_path
21+
else
22+
render :action => 'new'
2023
end
21-
redirect_to custom_fields_groups_path
22-
rescue ActiveRecord::RecordInvalid
23-
render 'new'
2424
end
2525

2626
def edit
27-
@custom_fields_group = CustomFieldsGroup.find params[:id]
28-
# unless @custom_fields_group.custom_fields_group_fields.present?
29-
# @custom_fields_group.custom_fields_group_fields.build
30-
# end
3127
end
3228

3329
def update
34-
# TODO: @custom_fields_group becomes nil
35-
custom_fields_group = CustomFieldsGroup.find params[:id]
36-
ActiveRecord::Base.transaction do
37-
custom_fields_group.update!(custom_fields_group_params)
30+
@custom_fields_group.safe_attributes = custom_fields_group_params
31+
if @custom_fields_group.save
32+
respond_to do |format|
33+
format.html do
34+
flash[:notice] = l(:notice_successful_update)
35+
redirect_to custom_fields_groups_path
36+
end
37+
format.js { head 200 }
38+
end
39+
else
40+
respond_to do |format|
41+
format.html { render :action => 'edit' }
42+
format.js { head 422 }
43+
end
3844
end
39-
redirect_to custom_fields_groups_path
40-
rescue ActiveRecord::RecordInvalid
41-
render 'edit'
4245
end
4346

4447
def destroy
45-
custom_fields_group = CustomFieldsGroup.find params[:id]
46-
custom_fields_group.destroy
48+
begin
49+
if @custom_fields_group.destroy
50+
flash[:notice] = l(:notice_successful_delete)
51+
end
52+
rescue
53+
flash[:error] = l(:error_can_not_delete_custom_fields_group)
54+
end
4755
redirect_to custom_fields_groups_path
4856
end
4957

5058
private
5159

5260
def custom_fields_group_params
53-
params.require(:custom_fields_group).permit( :name, :position, custom_field_ids: [] )
61+
params.require(:custom_fields_group).permit(:name, :position, custom_field_ids: [])
5462
end
5563

64+
def find_custom_fields_group
65+
@custom_fields_group = CustomFieldsGroup.find(params[:id])
66+
rescue ActiveRecord::RecordNotFound
67+
render_404
68+
end
5669
end

app/models/custom_fields_group.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
class CustomFieldsGroup < ActiveRecord::Base
1+
class CustomFieldsGroup < (defined?(ApplicationRecord) == 'constant' ? ApplicationRecord : ActiveRecord::Base)
2+
include Redmine::SafeAttributes
3+
24
validates :name, presence: true, uniqueness: true
35

46
has_many :custom_fields_group_fields, :dependent => :delete_all
57
has_many :custom_fields, :through => :custom_fields_group_fields
68

7-
# accepts_nested_attributes_for :custom_fields_group_fields, :allow_destroy => true
8-
99
acts_as_positioned
1010
scope :sorted, ->{ order :position }
11+
12+
safe_attributes(
13+
'name',
14+
'position',
15+
'custom_field_ids'
16+
)
1117
end

app/views/issues/_form_custom_fields.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<% end %>
3636
<% else %>
3737
<% fieldset_class = 'collapsible custom-fields-groups' + (all_collapsed ? ' collapsed' : '') %>
38-
<% legend_class = 'icon ' + (all_collapsed ? 'icon-collapsed' : 'icon-expended') %>
38+
<% legend_class = 'icon icon-' + (all_collapsed ? 'collapsed' : ((Redmine::VERSION.to_s >= '5.0.0') ? 'expanded' : 'expended')) %>
3939
<% div_style = all_collapsed ? 'display: none' : '' %>
4040
<fieldset class="<%= fieldset_class %>">
4141
<%= content_tag('legend', title, :onclick => "toggleFieldset(this);", :class => legend_class) %>

config/locales/en.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ en:
1111
label_fieldset_default_state: Fieldset Default State
1212
label_fieldset_state_all_expended: All expended
1313
label_fieldset_state_all_collapsed: All collapsed
14+
error_can_not_delete_custom_fields_group: Unable to delete custom fields group

config/locales/ja.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ ja:
1111
label_fieldset_default_state: フィールドセットのデフォルト状態
1212
label_fieldset_state_all_expended: 全て展開
1313
label_fieldset_state_all_collapsed: 全て折りたたみ
14+
error_can_not_delete_custom_fields_group: カスタムフィールドグループを削除できません。
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class AddOnDeleteCascadeToForeignKeyCustomField < ActiveRecord::Migration[5.2]
2+
def change
3+
remove_foreign_key :custom_fields_group_fields, :custom_fields
4+
add_foreign_key :custom_fields_group_fields, :custom_fields, on_delete: :cascade
5+
end
6+
end

init.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
require File.expand_path('../lib/redmine_custom_fields_groups/hooks/view_layouts_base_html_head_hook', __FILE__)
2-
require File.expand_path('../lib/redmine_custom_fields_groups/hooks/view_user_preferences_hook', __FILE__)
1+
require_relative 'lib/redmine_custom_fields_groups/hooks/view_layouts_base_html_head_hook'
2+
require_relative 'lib/redmine_custom_fields_groups/hooks/view_user_preferences_hook'
33

44
Redmine::Plugin.register :redmine_custom_fields_groups do
55
name 'Redmine Custom Fields Groups plugin'
@@ -26,7 +26,7 @@
2626
end
2727

2828
if Rails.version > '6.0' && Rails.autoloaders.zeitwerk_enabled?
29-
require File.expand_path('../app/overrides/issues', __FILE__)
29+
require_relative 'app/overrides/issues'
3030
Rails.application.config.after_initialize do
3131
RedmineCustomFieldsGroups.setup
3232
end

lib/redmine_custom_fields_groups/patches/issues_helper_patch.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def render_custom_fields_rows_by_groups(issue)
4646
else
4747
s << content_tag('fieldset', :class => 'collapsible custom-fields-groups') do
4848
concat content_tag('legend', title, :onclick => 'toggleFieldset(this);',
49-
:class => 'icon icon-expended')
49+
:class => 'icon icon-' + ((Redmine::VERSION.to_s >= '5.0.0') ? 'expanded' : 'expended'))
5050
concat render_half_width_custom_fields_rows_by_grouped_values(issue, values)
5151
concat render_full_width_custom_fields_rows_by_grouped_values(issue, values)
5252
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
custom_fields_group_fields_101:
2+
custom_fields_group_id: 1
3+
custom_field_id: 1
4+
custom_fields_group_fields_102:
5+
custom_fields_group_id: 1
6+
custom_field_id: 2
7+
custom_fields_group_fields_206:
8+
custom_fields_group_id: 2
9+
custom_field_id: 6
10+
custom_fields_group_fields_308:
11+
custom_fields_group_id: 3
12+
custom_field_id: 8

0 commit comments

Comments
 (0)