Skip to content

Commit 3994bf5

Browse files
authored
Merge pull request #72 from gtt-project/phase-0/ci-and-tests
Phase 0: CI and test foundation
2 parents 6b2eaa5 + d40739f commit 3994bf5

4 files changed

Lines changed: 262 additions & 1 deletion

File tree

.github/dependabot.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
# Defer brand-new releases to reduce supply-chain risk from
8+
# freshly published (potentially hijacked) action versions.
9+
cooldown:
10+
default-days: 8
11+
groups:
12+
github-actions:
13+
patterns: ["*"]
14+
update-types: ["minor", "patch"]

.github/workflows/test-postgis.yml

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
name: Test with PostGIS
2+
3+
env:
4+
PLUGIN_NAME: ${{ github.event.repository.name }}
5+
6+
on:
7+
push:
8+
branches:
9+
- main
10+
pull_request:
11+
branches:
12+
- main
13+
workflow_dispatch:
14+
15+
jobs:
16+
test:
17+
name: redmine:${{ matrix.redmine_version }} ruby:${{ matrix.ruby_version }} postgis:${{ matrix.db_version }}
18+
runs-on: ubuntu-latest
19+
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
# Redmine >= 6 only (see init.rb requires_redmine). Each Redmine version
24+
# is tested against the Ruby versions it supports, limited to Rubies
25+
# still in upstream support:
26+
# 6.0-stable -> 3.3
27+
# 6.1-stable -> 3.3, 3.4
28+
redmine_version: [6.0-stable, 6.1-stable]
29+
ruby_version: ['3.3', '3.4']
30+
# postgis/postgis tags spanning PG 15/17/18 and PostGIS 3.4/3.5/3.6
31+
# (floor -> ceiling), matching the redmine_gtt matrix.
32+
db_version: [15-3.4, 17-3.5, 18-3.6]
33+
include:
34+
- system_test: true
35+
redmine_version: 6.1-stable
36+
ruby_version: '3.4'
37+
exclude:
38+
# Redmine 6.0 supports Ruby up to 3.3 only.
39+
- redmine_version: 6.0-stable
40+
ruby_version: '3.4'
41+
42+
services:
43+
postgres:
44+
image: postgis/postgis:${{ matrix.db_version }}
45+
env:
46+
POSTGRES_USER: postgres
47+
POSTGRES_PASSWORD: postgres
48+
ports:
49+
- 5432:5432
50+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
51+
52+
steps:
53+
- name: Checkout Redmine
54+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
55+
with:
56+
repository: redmine/redmine
57+
ref: ${{ matrix.redmine_version }}
58+
path: redmine
59+
60+
# redmine_gtt is a hard dependency: this plugin uses RedmineGtt::Conversions
61+
# for geometry and relies on the `geom` column its migration adds to issues.
62+
# It is checked out from `next` on purpose: that is redmine_gtt's
63+
# integration branch, and this plugin must stay compatible with it.
64+
# A CI break caused by a redmine_gtt change is a signal we want early,
65+
# not noise to be pinned away.
66+
- name: Checkout redmine_gtt (dependency)
67+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
68+
with:
69+
repository: gtt-project/redmine_gtt
70+
ref: next
71+
path: redmine/plugins/redmine_gtt
72+
73+
- name: Checkout Plugin
74+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
75+
with:
76+
path: redmine/plugins/${{ env.PLUGIN_NAME }}
77+
78+
- name: Set up Ruby
79+
uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0
80+
with:
81+
ruby-version: ${{ matrix.ruby_version }}
82+
83+
- name: Install native gem system libraries
84+
# pg and rgeo-geos gems' headers need these.
85+
run: |
86+
sudo apt-get update --yes --quiet
87+
sudo apt-get install --yes --quiet --no-install-recommends libpq-dev libgeos-dev
88+
89+
- name: Prepare Redmine source
90+
working-directory: redmine
91+
run: |
92+
cat <<EOF > config/database.yml
93+
test:
94+
adapter: postgis
95+
database: redmine
96+
host: 127.0.0.1
97+
username: postgres
98+
password: postgres
99+
encoding: utf8
100+
EOF
101+
102+
- name: Install Ruby dependencies
103+
working-directory: redmine
104+
run: |
105+
bundle config set --local without 'development'
106+
bundle install --jobs=4 --retry=3
107+
108+
- name: Run Redmine rake tasks
109+
env:
110+
RAILS_ENV: test
111+
working-directory: redmine
112+
run: |
113+
bundle exec rake generate_secret_token
114+
bundle exec rake db:create db:migrate redmine:plugins:migrate
115+
116+
- name: Zeitwerk check
117+
env:
118+
RAILS_ENV: test
119+
working-directory: redmine
120+
run: |
121+
if grep -q zeitwerk config/application.rb ; then
122+
bundle exec rake zeitwerk:check
123+
fi
124+
shell: bash
125+
126+
- name: Run tests
127+
env:
128+
RAILS_ENV: test
129+
# For system tests in the plugin
130+
GOOGLE_CHROME_OPTS_ARGS: "headless,disable-gpu,no-sandbox,disable-dev-shm-usage"
131+
working-directory: redmine
132+
# Only run suites that exist; `rails test` raises LoadError on a
133+
# missing directory (functional/integration/system get added as the
134+
# revival progresses). System tests only run on the designated matrix
135+
# cell, like in redmine_gtt.
136+
run: |
137+
suites="unit functional integration"
138+
if [ "${{ matrix.system_test }}" = "true" ]; then
139+
suites="$suites system"
140+
fi
141+
for suite in $suites; do
142+
dir="plugins/${{ env.PLUGIN_NAME }}/test/$suite"
143+
if [ -d "$dir" ]; then
144+
bundle exec rails test "$dir"
145+
else
146+
echo "Skipping $suite tests ($dir does not exist yet)"
147+
fi
148+
done
149+
150+
- name: Run uninstall test
151+
env:
152+
RAILS_ENV: test
153+
working-directory: redmine
154+
run: bundle exec rake redmine:plugins:migrate NAME=${{ env.PLUGIN_NAME }} VERSION=0

app/models/subscription_template.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def set_default_alteration_types
7171
end
7272

7373
def set_default_notify_on_metadata_change
74-
self.notify_on_metadata_change = true
74+
self.notify_on_metadata_change = true if notify_on_metadata_change.nil?
7575
end
7676

7777
def take_json_entities
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
require File.expand_path('../../test_helper', __FILE__)
2+
3+
class SubscriptionTemplateTest < ActiveSupport::TestCase
4+
fixtures :projects, :trackers, :issue_statuses, :users, :members,
5+
:member_roles, :roles, :enumerations
6+
7+
def valid_attributes(overrides = {})
8+
{
9+
standard: 'NGSIv2',
10+
status: 'active',
11+
name: 'Temperature alerts',
12+
broker_url: 'https://broker.example.com',
13+
subject: 'Sensor ${id}',
14+
description: 'A monitored value changed',
15+
entities_string: '[{"idPattern": ".*", "type": "TemperatureSensor"}]',
16+
project_id: 1,
17+
tracker_id: 1,
18+
issue_status_id: 1,
19+
member_id: 1,
20+
}.merge(overrides)
21+
end
22+
23+
def test_valid_template_saves
24+
template = SubscriptionTemplate.new(valid_attributes)
25+
assert template.valid?, template.errors.full_messages.join(', ')
26+
assert template.save
27+
end
28+
29+
def test_default_alteration_types
30+
template = SubscriptionTemplate.new
31+
assert_equal ['entityCreate', 'entityChange'], template.alteration_types
32+
end
33+
34+
def test_default_notify_on_metadata_change
35+
template = SubscriptionTemplate.new
36+
assert_equal true, template.notify_on_metadata_change
37+
end
38+
39+
def test_explicit_false_notify_on_metadata_change_is_respected
40+
template = SubscriptionTemplate.new(valid_attributes(notify_on_metadata_change: false))
41+
assert_equal false, template.notify_on_metadata_change
42+
end
43+
44+
def test_name_is_required
45+
template = SubscriptionTemplate.new(valid_attributes(name: nil))
46+
assert_not template.valid?
47+
assert template.errors.added?(:name, :blank)
48+
end
49+
50+
def test_broker_url_is_required
51+
template = SubscriptionTemplate.new(valid_attributes(broker_url: nil))
52+
assert_not template.valid?
53+
assert template.errors.added?(:broker_url, :blank)
54+
end
55+
56+
def test_standard_must_be_supported
57+
template = SubscriptionTemplate.new(valid_attributes(standard: 'bogus'))
58+
assert_not template.valid?
59+
assert template.errors[:standard].present?
60+
end
61+
62+
def test_status_must_be_valid
63+
template = SubscriptionTemplate.new(valid_attributes(status: 'paused'))
64+
assert_not template.valid?
65+
assert template.errors[:status].present?
66+
end
67+
68+
def test_entities_string_must_be_valid_json
69+
template = SubscriptionTemplate.new(valid_attributes(entities_string: 'not json'))
70+
assert_not template.valid?
71+
assert template.errors[:entities_string].present?
72+
end
73+
74+
def test_name_is_unique_within_project
75+
SubscriptionTemplate.create!(valid_attributes)
76+
duplicate = SubscriptionTemplate.new(valid_attributes)
77+
assert_not duplicate.valid?
78+
assert duplicate.errors[:name].present?
79+
end
80+
81+
def test_threshold_create_hours_converts_to_seconds
82+
template = SubscriptionTemplate.new(valid_attributes)
83+
template.threshold_create_hours = 2
84+
assert_equal 7200, template.threshold_create
85+
assert_equal 2, template.threshold_create_hours
86+
end
87+
88+
def test_geo_query_fields_must_be_all_or_none
89+
template = SubscriptionTemplate.new(valid_attributes(expression_georel: 'near;maxDistance:1000'))
90+
assert_not template.valid?
91+
assert template.errors[:base].present?
92+
end
93+
end

0 commit comments

Comments
 (0)