ruby_raider 3.7.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/generators/infrastructure/templates/azure_pipelines.tt +16 -2
- data/lib/generators/infrastructure/templates/github.tt +21 -2
- data/lib/generators/infrastructure/templates/github_appium.tt +33 -5
- data/lib/generators/templates/common/gemfile.tt +1 -1
- data/lib/generators/templates/common/read_me.tt +28 -0
- data/lib/version +1 -1
- data/spec/integration/content/azure_content_spec.rb +23 -6
- data/spec/integration/content/ci_content_spec.rb +84 -6
- data/spec/integration/content/gemfile_content_spec.rb +2 -2
- data/spec/integration/content/readme_content_spec.rb +22 -0
- data/spec/integration/content/rspec_reporter_content_spec.rb +2 -2
- data/spec/integration/end_to_end_spec.rb +8 -8
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed3634de8115662d6148059e139a55f330a07fe9736ac82efbc439a256dd5747
|
|
4
|
+
data.tar.gz: 2c88f2ecb9c18c6f787ac216ef89de3e2dd626c1d1671c990b313d3df29b0e4d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f534bbb7ae8a9ae5870f905376bf1fc6bdc2189729ccb01fd5d76c8a0886255b1693a716e28cebd87d892ce3646b17dfca9a2b887c35349431bae2d47573fc05
|
|
7
|
+
data.tar.gz: 15eba78213eaee9100e1bc9ec5959fa5a8f89843b65fd77259db1571f74684ac01e665ab36a1ff152fb9ec3b8b96090acea9edf3e5d5c7ccd145f5b88c450b67
|
data/README.md
CHANGED
|
@@ -60,7 +60,7 @@ Every generated project comes with:
|
|
|
60
60
|
|
|
61
61
|
- **Page Object Model** — Base page and component classes with example pages
|
|
62
62
|
- **Test examples** — Working login tests against the [Raider Test Store](https://raider-test-site.onrender.com/)
|
|
63
|
-
- **Raider reporting** — RSpec and Cucumber projects include [raider_reporter](https://github.com/RaiderHQ/raider_reporter), which writes results to `raider-results/` and uploads runs when `RAIDER_TOKEN` and `RAIDER_ENDPOINT` are set
|
|
63
|
+
- **Raider reporting** — RSpec and Cucumber projects include [raider_reporter](https://github.com/RaiderHQ/raider_reporter), which writes results to `raider-results/` and uploads runs when `RAIDER_TOKEN` and `RAIDER_ENDPOINT` are set; generated CI runs the suite through `raider-reporter exec` with `RAIDER_QUARANTINE`, so quarantined tests do not fail the build; an opt-in `raider-gate` job (`RAIDER_GATE=1`) fails CI when the Raider quality gate fails
|
|
64
64
|
- **GitHub Actions CI** — Ready-to-use test pipeline
|
|
65
65
|
- **Rake tasks** — Default, smoke, and regression tasks with tag-based filtering
|
|
66
66
|
- **Retry support** — RSpec retry with configurable retry count via `RETRY_COUNT` env var
|
|
@@ -21,16 +21,17 @@ jobs:
|
|
|
21
21
|
inputs: { versionSpec: '3.4' }
|
|
22
22
|
- script: bundle install
|
|
23
23
|
displayName: Install gems
|
|
24
|
-
- script: <%- if cucumber? -%>bundle exec cucumber features/ --format pretty<%- else -%>bundle exec rspec spec/ --format documentation<%- end %>
|
|
24
|
+
- script: <%- if cucumber? -%>bundle exec raider-reporter exec -- bundle exec cucumber features/ --format pretty<%- else -%>bundle exec raider-reporter exec -- bundle exec rspec spec/ --format documentation<%- end %>
|
|
25
25
|
displayName: Run tests
|
|
26
26
|
env:
|
|
27
27
|
RAIDER_TOKEN: $(RAIDER_TOKEN)
|
|
28
28
|
RAIDER_ENDPOINT: $(RAIDER_ENDPOINT)
|
|
29
|
+
RAIDER_QUARANTINE: 1
|
|
29
30
|
- task: PublishPipelineArtifact@1
|
|
30
31
|
condition: always()
|
|
31
32
|
inputs: { targetPath: raider-results, artifact: raider-results-$(System.JobPositionInPhase)-$(System.JobAttempt) }
|
|
32
33
|
- job: raider_comment
|
|
33
|
-
dependsOn: tests
|
|
34
|
+
dependsOn: [tests, raider_gate]
|
|
34
35
|
condition: and(always(), eq(variables['Build.Reason'], 'PullRequest'))
|
|
35
36
|
steps:
|
|
36
37
|
- task: UseRubyVersion@0
|
|
@@ -42,3 +43,16 @@ jobs:
|
|
|
42
43
|
RAIDER_TOKEN: $(RAIDER_TOKEN)
|
|
43
44
|
RAIDER_ENDPOINT: $(RAIDER_ENDPOINT)
|
|
44
45
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
|
46
|
+
- job: raider_gate
|
|
47
|
+
dependsOn: tests
|
|
48
|
+
condition: and(always(), eq(variables['RAIDER_GATE'], '1'))
|
|
49
|
+
steps:
|
|
50
|
+
- task: UseRubyVersion@0
|
|
51
|
+
inputs: { versionSpec: '3.4' }
|
|
52
|
+
- script: bundle install
|
|
53
|
+
- script: bundle exec raider-reporter gate
|
|
54
|
+
displayName: Wait for the Raider quality gate
|
|
55
|
+
env:
|
|
56
|
+
RAIDER_TOKEN: $(RAIDER_TOKEN)
|
|
57
|
+
RAIDER_ENDPOINT: $(RAIDER_ENDPOINT)
|
|
58
|
+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
|
@@ -34,11 +34,12 @@ jobs:
|
|
|
34
34
|
chrome-version: stable
|
|
35
35
|
|
|
36
36
|
- name: Run tests
|
|
37
|
-
run: <%- if framework == 'cucumber' -%>bundle exec cucumber features --format pretty<%- else -%>bundle exec rspec spec --format documentation<%- end %>
|
|
37
|
+
run: <%- if framework == 'cucumber' -%>bundle exec raider-reporter exec -- bundle exec cucumber features --format pretty<%- else -%>bundle exec raider-reporter exec -- bundle exec rspec spec --format documentation<%- end %>
|
|
38
38
|
env:
|
|
39
39
|
HEADLESS: true
|
|
40
40
|
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
41
41
|
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
42
|
+
RAIDER_QUARANTINE: "1"
|
|
42
43
|
|
|
43
44
|
- name: Upload Raider results
|
|
44
45
|
uses: actions/upload-artifact@v4
|
|
@@ -49,7 +50,7 @@ jobs:
|
|
|
49
50
|
if-no-files-found: ignore
|
|
50
51
|
|
|
51
52
|
raider-comment:
|
|
52
|
-
needs: [build]
|
|
53
|
+
needs: [build, raider-gate]
|
|
53
54
|
if: always() && github.event_name == 'pull_request'
|
|
54
55
|
runs-on: ubuntu-latest
|
|
55
56
|
permissions:
|
|
@@ -66,3 +67,21 @@ jobs:
|
|
|
66
67
|
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
67
68
|
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
68
69
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
70
|
+
|
|
71
|
+
raider-gate:
|
|
72
|
+
needs: [build]
|
|
73
|
+
if: always() && vars.RAIDER_GATE == '1'
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
permissions:
|
|
76
|
+
contents: read
|
|
77
|
+
statuses: write
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v4
|
|
80
|
+
- uses: ruby/setup-ruby@v1
|
|
81
|
+
with: { ruby-version: 3.4.0, bundler-cache: true }
|
|
82
|
+
- name: Wait for the Raider quality gate
|
|
83
|
+
run: bundle exec raider-reporter gate
|
|
84
|
+
env:
|
|
85
|
+
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
86
|
+
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
87
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -46,14 +46,19 @@ jobs:
|
|
|
46
46
|
|
|
47
47
|
- name: Run tests
|
|
48
48
|
<%- if cucumber? -%>
|
|
49
|
-
run: bundle exec cucumber features/ --format pretty
|
|
49
|
+
run: bundle exec raider-reporter exec -- bundle exec cucumber features/ --format pretty
|
|
50
50
|
<%- else -%>
|
|
51
|
-
run: bundle exec rspec spec/ --format documentation
|
|
51
|
+
run: bundle exec raider-reporter exec -- bundle exec rspec spec/ --format documentation
|
|
52
52
|
<%- end -%>
|
|
53
53
|
env:
|
|
54
54
|
APP_PATH: ${{ github.workspace }}/apps/RaiderTestApp.app
|
|
55
55
|
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
56
56
|
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
57
|
+
RAIDER_QUARANTINE: "1"
|
|
58
|
+
<%- if cross_platform? -%>
|
|
59
|
+
RAIDER_SHARD_INDEX: "1"
|
|
60
|
+
RAIDER_SHARD_TOTAL: "2"
|
|
61
|
+
<%- end -%>
|
|
57
62
|
|
|
58
63
|
- name: Upload Raider results
|
|
59
64
|
uses: actions/upload-artifact@v4
|
|
@@ -105,14 +110,19 @@ jobs:
|
|
|
105
110
|
profile: pixel_8
|
|
106
111
|
script: |
|
|
107
112
|
<%- if cucumber? -%>
|
|
108
|
-
bundle exec cucumber features/ --format pretty
|
|
113
|
+
bundle exec raider-reporter exec -- bundle exec cucumber features/ --format pretty
|
|
109
114
|
<%- else -%>
|
|
110
|
-
bundle exec rspec spec/ --format documentation
|
|
115
|
+
bundle exec raider-reporter exec -- bundle exec rspec spec/ --format documentation
|
|
111
116
|
<%- end -%>
|
|
112
117
|
env:
|
|
113
118
|
APP_PATH: ${{ github.workspace }}/apps/app-release.apk
|
|
114
119
|
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
115
120
|
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
121
|
+
RAIDER_QUARANTINE: "1"
|
|
122
|
+
<%- if cross_platform? -%>
|
|
123
|
+
RAIDER_SHARD_INDEX: "2"
|
|
124
|
+
RAIDER_SHARD_TOTAL: "2"
|
|
125
|
+
<%- end -%>
|
|
116
126
|
|
|
117
127
|
- name: Upload Raider results
|
|
118
128
|
uses: actions/upload-artifact@v4
|
|
@@ -124,7 +134,7 @@ jobs:
|
|
|
124
134
|
<%- end -%>
|
|
125
135
|
|
|
126
136
|
raider-comment:
|
|
127
|
-
needs: [<%= [('ios-tests' if ios? || cross_platform?), ('android-tests' if android? || cross_platform?)].compact.join(', ')
|
|
137
|
+
needs: [<%= [('ios-tests' if ios? || cross_platform?), ('android-tests' if android? || cross_platform?)].compact.join(', ') %>, raider-gate]
|
|
128
138
|
if: always() && github.event_name == 'pull_request'
|
|
129
139
|
runs-on: ubuntu-latest
|
|
130
140
|
permissions:
|
|
@@ -141,3 +151,21 @@ jobs:
|
|
|
141
151
|
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
142
152
|
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
143
153
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
154
|
+
|
|
155
|
+
raider-gate:
|
|
156
|
+
needs: [<%= [('ios-tests' if ios? || cross_platform?), ('android-tests' if android? || cross_platform?)].compact.join(', ') %>]
|
|
157
|
+
if: always() && vars.RAIDER_GATE == '1'
|
|
158
|
+
runs-on: ubuntu-latest
|
|
159
|
+
permissions:
|
|
160
|
+
contents: read
|
|
161
|
+
statuses: write
|
|
162
|
+
steps:
|
|
163
|
+
- uses: actions/checkout@v4
|
|
164
|
+
- uses: ruby/setup-ruby@v1
|
|
165
|
+
with: { ruby-version: 3.4.0, bundler-cache: true }
|
|
166
|
+
- name: Wait for the Raider quality gate
|
|
167
|
+
run: bundle exec raider-reporter gate
|
|
168
|
+
env:
|
|
169
|
+
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
170
|
+
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
171
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -108,6 +108,34 @@ Without `RAIDER_TOKEN`, nothing is uploaded and the suite output is unchanged. F
|
|
|
108
108
|
report and to Raider. See the [raider_reporter README](https://github.com/RaiderHQ/raider_reporter) for details.
|
|
109
109
|
<%- end -%>
|
|
110
110
|
|
|
111
|
+
<%- unless azure? && mobile? -%>
|
|
112
|
+
### Quarantine
|
|
113
|
+
|
|
114
|
+
CI runs the suite through `bundle exec raider-reporter exec -- …` with `RAIDER_QUARANTINE` set. Tests quarantined in
|
|
115
|
+
Raider still run and are still reported (as `quarantined`), and a build whose only failures are quarantined stays green.
|
|
116
|
+
Local runs keep quarantine off. To turn it off in CI, remove `RAIDER_QUARANTINE` from the pipeline.
|
|
117
|
+
|
|
118
|
+
<%- end -%>
|
|
119
|
+
<%- unless azure? && mobile? -%>
|
|
120
|
+
### Quality gate
|
|
121
|
+
|
|
122
|
+
The `<%= azure? ? 'raider_gate' : 'raider-gate' %>` CI job runs `bundle exec raider-reporter gate` after the tests and
|
|
123
|
+
fails the pipeline when the Raider quality gate fails. It is off until you turn it on:
|
|
124
|
+
|
|
125
|
+
- set the CI variable `RAIDER_GATE=1` (<%= azure? ? 'a pipeline variable' : 'a repository variable under Settings → Secrets and variables → Actions → Variables' %>);
|
|
126
|
+
- turn on rules under the project's Gate page in Raider: a minimum pass rate, no new failures against the default
|
|
127
|
+
branch, no new flaky tests;
|
|
128
|
+
- optionally require the `raider/gate` check in branch protection.
|
|
129
|
+
|
|
130
|
+
`raider-reporter gate` exits 1 when the gate fails, naming the failed rules, and 2 when it gets no verdict (timeout,
|
|
131
|
+
Raider unreachable, token rejected, build not found). `RAIDER_GATE_TIMEOUT` sets how long it waits, in seconds
|
|
132
|
+
(default 600). The job stays off by default because a project without `RAIDER_TOKEN`, or a pull request from a fork,
|
|
133
|
+
would exit 2 on every run.
|
|
134
|
+
|
|
135
|
+
Parallel test jobs that upload to one build must each set `RAIDER_SHARD_TOTAL` (the number of jobs) and
|
|
136
|
+
`RAIDER_SHARD_INDEX` (1 to that number), so the gate waits for all of them instead of judging the first one to finish.
|
|
137
|
+
|
|
138
|
+
<%- end -%>
|
|
111
139
|
<%- if azure? && mobile? -%>
|
|
112
140
|
## CI
|
|
113
141
|
|
data/lib/version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.9.0
|
|
@@ -27,9 +27,9 @@ describe 'Azure Pipelines content' do
|
|
|
27
27
|
let(:yml) { YAML.safe_load(raw) }
|
|
28
28
|
let(:run_command) do
|
|
29
29
|
if framework == 'cucumber'
|
|
30
|
-
'bundle exec cucumber features/ --format pretty'
|
|
30
|
+
'bundle exec raider-reporter exec -- bundle exec cucumber features/ --format pretty'
|
|
31
31
|
else
|
|
32
|
-
'bundle exec rspec spec/ --format documentation'
|
|
32
|
+
'bundle exec raider-reporter exec -- bundle exec rspec spec/ --format documentation'
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -49,20 +49,37 @@ describe 'Azure Pipelines content' do
|
|
|
49
49
|
|
|
50
50
|
it 'passes exactly the Raider settings to the test step' do
|
|
51
51
|
step = yml['jobs'][0]['steps'].find { |s| s['script'] == run_command }
|
|
52
|
-
expect(step['env']).to eq('RAIDER_TOKEN' => '$(RAIDER_TOKEN)', 'RAIDER_ENDPOINT' => '$(RAIDER_ENDPOINT)'
|
|
52
|
+
expect(step['env']).to eq('RAIDER_TOKEN' => '$(RAIDER_TOKEN)', 'RAIDER_ENDPOINT' => '$(RAIDER_ENDPOINT)',
|
|
53
|
+
'RAIDER_QUARANTINE' => 1)
|
|
53
54
|
expect(yml['variables']['HEADLESS']).to eq('true')
|
|
54
55
|
end
|
|
55
56
|
|
|
56
|
-
it 'has a raider_comment job for pull requests' do
|
|
57
|
+
it 'has a raider_comment job for pull requests that waits for the gate job but runs even when it is skipped' do
|
|
57
58
|
comment = yml['jobs'][1]
|
|
58
59
|
expect(comment['job']).to eq('raider_comment')
|
|
59
|
-
expect(comment['dependsOn']).to eq(
|
|
60
|
+
expect(comment['dependsOn']).to eq(%w[tests raider_gate])
|
|
60
61
|
expect(comment['condition']).to eq("and(always(), eq(variables['Build.Reason'], 'PullRequest'))")
|
|
61
62
|
last = comment['steps'].last
|
|
62
63
|
expect(last['script']).to eq('bundle exec raider-reporter comment')
|
|
63
64
|
expect(last['env']).to include('SYSTEM_ACCESSTOKEN' => '$(System.AccessToken)')
|
|
64
65
|
end
|
|
65
66
|
|
|
67
|
+
it 'has a raider_gate job that runs only when RAIDER_GATE is 1' do
|
|
68
|
+
gate = yml['jobs'][2]
|
|
69
|
+
expect(yml['jobs'].size).to eq(3)
|
|
70
|
+
expect(gate['job']).to eq('raider_gate')
|
|
71
|
+
expect(gate['dependsOn']).to eq('tests')
|
|
72
|
+
expect(gate['condition']).to eq("and(always(), eq(variables['RAIDER_GATE'], '1'))")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'sets up Ruby in the raider_gate job and runs the gate with the token env' do
|
|
76
|
+
gate = yml['jobs'][2]
|
|
77
|
+
expect(gate['steps'].first).to eq('task' => 'UseRubyVersion@0', 'inputs' => { 'versionSpec' => '3.4' })
|
|
78
|
+
expect(gate['steps'].filter_map { |s| s['script'] }).to eq(['bundle install', 'bundle exec raider-reporter gate'])
|
|
79
|
+
expect(gate['steps'].last['env']).to eq('RAIDER_TOKEN' => '$(RAIDER_TOKEN)', 'RAIDER_ENDPOINT' => '$(RAIDER_ENDPOINT)',
|
|
80
|
+
'SYSTEM_ACCESSTOKEN' => '$(System.AccessToken)')
|
|
81
|
+
end
|
|
82
|
+
|
|
66
83
|
it 'has triggers, pool and the self-hosted hint' do
|
|
67
84
|
expect(yml['trigger']['branches']['include']).to include('main', 'master')
|
|
68
85
|
expect(yml['pr']['branches']['include']).to include('*')
|
|
@@ -83,7 +100,7 @@ describe 'Azure Pipelines content' do
|
|
|
83
100
|
readme = read_generated(name, 'Readme.md')
|
|
84
101
|
expect(readme).to include('## Azure Pipelines', 'RAIDER_TOKEN', 'Contribute to pull requests',
|
|
85
102
|
'pool: { name: Default }', 'Build validation branch policy',
|
|
86
|
-
'same stage')
|
|
103
|
+
'same stage', 'raider_gate', 'RAIDER_GATE=1', 'RAIDER_SHARD_TOTAL', 'RAIDER_SHARD_INDEX')
|
|
87
104
|
expect(readme).not_to match(/GitHub Actions/i)
|
|
88
105
|
end
|
|
89
106
|
end
|
|
@@ -75,13 +75,24 @@ describe 'CI pipeline content' do
|
|
|
75
75
|
expect(test_steps).not_to be_empty
|
|
76
76
|
test_steps.each do |step|
|
|
77
77
|
expect(step['env']).to include('RAIDER_TOKEN' => '${{ secrets.RAIDER_TOKEN }}',
|
|
78
|
-
'RAIDER_ENDPOINT' => '${{ vars.RAIDER_ENDPOINT }}'
|
|
78
|
+
'RAIDER_ENDPOINT' => '${{ vars.RAIDER_ENDPOINT }}',
|
|
79
|
+
'RAIDER_QUARANTINE' => '1')
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'runs every test command through raider-reporter exec' do
|
|
84
|
+
expect(test_steps).not_to be_empty
|
|
85
|
+
test_steps.each do |step|
|
|
86
|
+
command = step['run'] || step['with']['script']
|
|
87
|
+
wrapped = command.scan(/raider-reporter exec -- bundle exec #{runner}\b/).size
|
|
88
|
+
expect(wrapped).to be_positive
|
|
89
|
+
expect(command.scan(/bundle exec #{runner}\b/).size).to eq(wrapped)
|
|
79
90
|
end
|
|
80
91
|
end
|
|
81
92
|
|
|
82
93
|
it 'uploads raider-results as an artifact even on failure in every job' do
|
|
83
94
|
uploads = steps.select { |step| step['uses'] == 'actions/upload-artifact@v4' }
|
|
84
|
-
expect(uploads.size).to eq(YAML.safe_load(pipeline)['jobs'].except('raider-comment').size)
|
|
95
|
+
expect(uploads.size).to eq(YAML.safe_load(pipeline)['jobs'].except('raider-comment', 'raider-gate').size)
|
|
85
96
|
uploads.each do |upload|
|
|
86
97
|
expect(upload['with']['path']).to eq('raider-results/')
|
|
87
98
|
expect(upload['if']).to eq('always()')
|
|
@@ -96,15 +107,16 @@ describe 'CI pipeline content' do
|
|
|
96
107
|
let(:job) { jobs['raider-comment'] }
|
|
97
108
|
|
|
98
109
|
it 'is a valid workflow with exactly the expected jobs' do
|
|
99
|
-
expect(jobs.keys).to match_array(test_jobs + [
|
|
110
|
+
expect(jobs.keys).to match_array(test_jobs + %w[raider-comment raider-gate])
|
|
100
111
|
end
|
|
101
112
|
|
|
102
|
-
it 'needs every test job' do
|
|
103
|
-
expect(job['needs']).to match_array(test_jobs)
|
|
113
|
+
it 'needs every test job and the gate job, so the comment carries the final gate line' do
|
|
114
|
+
expect(job['needs']).to match_array(test_jobs + %w[raider-gate])
|
|
104
115
|
end
|
|
105
116
|
|
|
106
|
-
it 'runs always, on pull requests only' do
|
|
117
|
+
it 'runs always, on pull requests only, so a skipped or failed gate job does not skip it' do
|
|
107
118
|
expect(job['if']).to eq("always() && github.event_name == 'pull_request'")
|
|
119
|
+
expect(job['if']).to start_with('always()')
|
|
108
120
|
expect(job['runs-on']).to eq('ubuntu-latest')
|
|
109
121
|
end
|
|
110
122
|
|
|
@@ -140,6 +152,62 @@ describe 'CI pipeline content' do
|
|
|
140
152
|
end
|
|
141
153
|
end
|
|
142
154
|
|
|
155
|
+
shared_examples 'github raider-gate job' do |project_name, file, test_jobs|
|
|
156
|
+
subject(:pipeline) { read_generated(project_name, ".github/workflows/#{file}") }
|
|
157
|
+
|
|
158
|
+
let(:jobs) { YAML.safe_load(pipeline)['jobs'] }
|
|
159
|
+
let(:gate_job) { jobs['raider-gate'] }
|
|
160
|
+
|
|
161
|
+
it 'needs every test job and runs always when RAIDER_GATE is 1, on push and pull requests' do
|
|
162
|
+
expect(gate_job['needs']).to match_array(test_jobs)
|
|
163
|
+
expect(gate_job['if']).to eq("always() && vars.RAIDER_GATE == '1'")
|
|
164
|
+
expect(gate_job['runs-on']).to eq('ubuntu-latest')
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it 'can read the code and write statuses only' do
|
|
168
|
+
expect(gate_job['permissions']).to eq('contents' => 'read', 'statuses' => 'write')
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'checks out, sets up the same Ruby as the test jobs and runs the gate' do
|
|
172
|
+
steps = gate_job['steps']
|
|
173
|
+
expect(steps[0]).to eq('uses' => 'actions/checkout@v4')
|
|
174
|
+
test_ruby = jobs.values_at(*test_jobs).flat_map { |j| j['steps'] }
|
|
175
|
+
.find { |step| step['uses'] == 'ruby/setup-ruby@v1' }['with']['ruby-version']
|
|
176
|
+
expect(steps[1]).to eq('uses' => 'ruby/setup-ruby@v1', 'with' => { 'ruby-version' => test_ruby, 'bundler-cache' => true })
|
|
177
|
+
expect(steps[2]).to eq('name' => 'Wait for the Raider quality gate',
|
|
178
|
+
'run' => 'bundle exec raider-reporter gate',
|
|
179
|
+
'env' => { 'RAIDER_TOKEN' => '${{ secrets.RAIDER_TOKEN }}',
|
|
180
|
+
'RAIDER_ENDPOINT' => '${{ vars.RAIDER_ENDPOINT }}',
|
|
181
|
+
'GITHUB_TOKEN' => '${{ secrets.GITHUB_TOKEN }}' })
|
|
182
|
+
expect(steps.size).to eq(3)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
shared_examples 'github appium shards' do |project_name, runner, shards|
|
|
187
|
+
subject(:pipeline) { read_generated(project_name, '.github/workflows/appium_pipeline.yml') }
|
|
188
|
+
|
|
189
|
+
let(:jobs) { YAML.safe_load(pipeline)['jobs'] }
|
|
190
|
+
|
|
191
|
+
def test_step(job, runner)
|
|
192
|
+
job['steps'].find { |step| step['run'].to_s.include?(runner) || step['with'].to_h['script'].to_s.include?(runner) }
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
if shards
|
|
196
|
+
it 'gives each platform job its own shard of two, so the gate waits for both' do
|
|
197
|
+
shards.each do |job_name, index|
|
|
198
|
+
expect(test_step(jobs[job_name], runner)['env'])
|
|
199
|
+
.to include('RAIDER_SHARD_INDEX' => index, 'RAIDER_SHARD_TOTAL' => '2')
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
else
|
|
203
|
+
it 'sets no shard env for a single platform' do
|
|
204
|
+
jobs.except('raider-comment', 'raider-gate').each_value do |job|
|
|
205
|
+
expect(test_step(job, runner)['env'].keys).not_to include('RAIDER_SHARD_INDEX', 'RAIDER_SHARD_TOTAL')
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
143
211
|
context 'with rspec and selenium' do
|
|
144
212
|
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
145
213
|
include_examples 'valid github pipeline', name
|
|
@@ -147,6 +215,7 @@ describe 'CI pipeline content' do
|
|
|
147
215
|
include_examples 'github triggers', name, 'test_pipeline.yml'
|
|
148
216
|
include_examples 'github raider wiring', name, 'test_pipeline.yml'
|
|
149
217
|
include_examples 'github raider-comment job', name, 'test_pipeline.yml', %w[build]
|
|
218
|
+
include_examples 'github raider-gate job', name, 'test_pipeline.yml', %w[build]
|
|
150
219
|
include_examples 'github without allure steps', name
|
|
151
220
|
end
|
|
152
221
|
|
|
@@ -157,6 +226,7 @@ describe 'CI pipeline content' do
|
|
|
157
226
|
include_examples 'github triggers', name, 'test_pipeline.yml'
|
|
158
227
|
include_examples 'github raider wiring', name, 'test_pipeline.yml', 'cucumber'
|
|
159
228
|
include_examples 'github raider-comment job', name, 'test_pipeline.yml', %w[build]
|
|
229
|
+
include_examples 'github raider-gate job', name, 'test_pipeline.yml', %w[build]
|
|
160
230
|
include_examples 'github without allure steps', name
|
|
161
231
|
end
|
|
162
232
|
|
|
@@ -167,6 +237,7 @@ describe 'CI pipeline content' do
|
|
|
167
237
|
include_examples 'github triggers', name, 'test_pipeline.yml'
|
|
168
238
|
include_examples 'github raider wiring', name, 'test_pipeline.yml'
|
|
169
239
|
include_examples 'github raider-comment job', name, 'test_pipeline.yml', %w[build]
|
|
240
|
+
include_examples 'github raider-gate job', name, 'test_pipeline.yml', %w[build]
|
|
170
241
|
include_examples 'github without allure steps', name
|
|
171
242
|
end
|
|
172
243
|
|
|
@@ -177,25 +248,32 @@ describe 'CI pipeline content' do
|
|
|
177
248
|
include_examples 'github triggers', name, 'test_pipeline.yml'
|
|
178
249
|
include_examples 'github raider wiring', name, 'test_pipeline.yml', 'cucumber'
|
|
179
250
|
include_examples 'github raider-comment job', name, 'test_pipeline.yml', %w[build]
|
|
251
|
+
include_examples 'github raider-gate job', name, 'test_pipeline.yml', %w[build]
|
|
180
252
|
include_examples 'github without allure steps', name
|
|
181
253
|
end
|
|
182
254
|
|
|
183
255
|
appium_jobs = { 'android' => %w[android-tests], 'ios' => %w[ios-tests],
|
|
184
256
|
'cross_platform' => %w[ios-tests android-tests] }
|
|
185
257
|
|
|
258
|
+
appium_shards = { 'cross_platform' => { 'ios-tests' => '1', 'android-tests' => '2' } }
|
|
259
|
+
|
|
186
260
|
appium_jobs.each do |automation, test_jobs|
|
|
187
261
|
context "with rspec and #{automation}" do
|
|
188
262
|
name = "#{FrameworkIndex::RSPEC}_#{automation}"
|
|
263
|
+
include_examples 'github appium shards', name, 'rspec', appium_shards[automation]
|
|
189
264
|
include_examples 'github raider-comment job', name, 'appium_pipeline.yml', test_jobs
|
|
265
|
+
include_examples 'github raider-gate job', name, 'appium_pipeline.yml', test_jobs
|
|
190
266
|
include_examples 'github triggers', name, 'appium_pipeline.yml'
|
|
191
267
|
include_examples 'github raider wiring', name, 'appium_pipeline.yml'
|
|
192
268
|
end
|
|
193
269
|
|
|
194
270
|
context "with cucumber and #{automation}" do
|
|
195
271
|
name = "#{FrameworkIndex::CUCUMBER}_#{automation}"
|
|
272
|
+
include_examples 'github appium shards', name, 'cucumber', appium_shards[automation]
|
|
196
273
|
include_examples 'github triggers', name, 'appium_pipeline.yml'
|
|
197
274
|
include_examples 'github raider wiring', name, 'appium_pipeline.yml', 'cucumber'
|
|
198
275
|
include_examples 'github raider-comment job', name, 'appium_pipeline.yml', test_jobs
|
|
276
|
+
include_examples 'github raider-gate job', name, 'appium_pipeline.yml', test_jobs
|
|
199
277
|
end
|
|
200
278
|
end
|
|
201
279
|
end
|
|
@@ -127,7 +127,7 @@ describe 'Gemfile content' do
|
|
|
127
127
|
let(:gemfile) { read_generated("#{FrameworkIndex::RSPEC}_#{automation}", 'Gemfile') }
|
|
128
128
|
|
|
129
129
|
it 'includes raider_reporter' do
|
|
130
|
-
expect(gemfile).to include("gem 'raider_reporter', '~> 0.
|
|
130
|
+
expect(gemfile).to include("gem 'raider_reporter', '~> 0.9'")
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
it 'has no allure gems' do
|
|
@@ -143,7 +143,7 @@ describe 'Gemfile content' do
|
|
|
143
143
|
let(:gemfile) { read_generated("#{FrameworkIndex::CUCUMBER}_#{automation}", 'Gemfile') }
|
|
144
144
|
|
|
145
145
|
it 'includes raider_reporter' do
|
|
146
|
-
expect(gemfile).to include("gem 'raider_reporter', '~> 0.
|
|
146
|
+
expect(gemfile).to include("gem 'raider_reporter', '~> 0.9'")
|
|
147
147
|
end
|
|
148
148
|
|
|
149
149
|
it 'drops allure-cucumber' do
|
|
@@ -16,6 +16,17 @@ describe 'Generated Readme content' do
|
|
|
16
16
|
'https://github.com/RaiderHQ/raider_reporter')
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
it 'explains quarantine in CI' do
|
|
20
|
+
expect(readme).to include('### Quarantine', 'RAIDER_QUARANTINE', 'raider-reporter exec')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'explains the quality gate' do
|
|
24
|
+
expect(readme).to include('### Quality gate', 'RAIDER_GATE=1', 'Gate page', 'raider/gate',
|
|
25
|
+
'raider-reporter gate', 'raider-gate', 'exits 1 when the gate fails',
|
|
26
|
+
'2 when it gets no verdict', 'RAIDER_GATE_TIMEOUT', 'RAIDER_SHARD_TOTAL',
|
|
27
|
+
'RAIDER_SHARD_INDEX')
|
|
28
|
+
end
|
|
29
|
+
|
|
19
30
|
it 'points to the local HTML report' do
|
|
20
31
|
expect(readme).to include('raider-results/index.html')
|
|
21
32
|
expect(readme).not_to match(/allure/i)
|
|
@@ -34,6 +45,17 @@ describe 'Generated Readme content' do
|
|
|
34
45
|
'https://github.com/RaiderHQ/raider_reporter')
|
|
35
46
|
end
|
|
36
47
|
|
|
48
|
+
it 'explains quarantine in CI' do
|
|
49
|
+
expect(readme).to include('### Quarantine', 'RAIDER_QUARANTINE', 'raider-reporter exec')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'explains the quality gate' do
|
|
53
|
+
expect(readme).to include('### Quality gate', 'RAIDER_GATE=1', 'Gate page', 'raider/gate',
|
|
54
|
+
'raider-reporter gate', 'raider-gate', 'exits 1 when the gate fails',
|
|
55
|
+
'2 when it gets no verdict', 'RAIDER_GATE_TIMEOUT', 'RAIDER_SHARD_TOTAL',
|
|
56
|
+
'RAIDER_SHARD_INDEX')
|
|
57
|
+
end
|
|
58
|
+
|
|
37
59
|
it 'does not mention Allure' do
|
|
38
60
|
expect(readme).not_to match(/allure/i)
|
|
39
61
|
end
|
|
@@ -18,8 +18,8 @@ describe 'RSpec projects without Allure' do
|
|
|
18
18
|
expect(File).not_to exist(File.join(project_name, 'allure-results'))
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
it 'pins raider_reporter 0.
|
|
22
|
-
expect(read_generated(project_name, 'Gemfile')).to include("gem 'raider_reporter', '~> 0.
|
|
21
|
+
it 'pins raider_reporter 0.9' do
|
|
22
|
+
expect(read_generated(project_name, 'Gemfile')).to include("gem 'raider_reporter', '~> 0.9'")
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -104,10 +104,10 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
104
104
|
expect(bundle_install(project)).to be true
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
-
it 'resolves raider_reporter 0.
|
|
107
|
+
it 'resolves raider_reporter 0.9 from RubyGems and ships the raider-reporter executable', :aggregate_failures do
|
|
108
108
|
skip 'Bundle install failed' unless bundle_install(project)
|
|
109
109
|
|
|
110
|
-
expect(File.read(File.join(project, 'Gemfile.lock'))).to match(/^ raider_reporter \(0\.
|
|
110
|
+
expect(File.read(File.join(project, 'Gemfile.lock'))).to match(/^ raider_reporter \(0\.9\.\d+\)$/)
|
|
111
111
|
result = run_in_project(project, 'bundle exec raider-reporter --help', timeout: 60)
|
|
112
112
|
expect(result[:exit_code]).to eq(0), "STDOUT: #{result[:stdout]}\nSTDERR: #{result[:stderr]}"
|
|
113
113
|
expect(result[:stdout] + result[:stderr]).to include('raider-reporter comment')
|
|
@@ -163,11 +163,11 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
163
163
|
"STDERR: #{result[:stderr]}"
|
|
164
164
|
end
|
|
165
165
|
|
|
166
|
-
it 'resolves raider_reporter 0.
|
|
166
|
+
it 'resolves raider_reporter 0.9 from RubyGems and requires its Cucumber plugin', :aggregate_failures do
|
|
167
167
|
skip 'Bundle install failed' unless bundle_install(project)
|
|
168
168
|
|
|
169
169
|
lockfile = File.read(File.join(project, 'Gemfile.lock'))
|
|
170
|
-
expect(lockfile).to match(/^ raider_reporter \(0\.
|
|
170
|
+
expect(lockfile).to match(/^ raider_reporter \(0\.9\.\d+\)$/)
|
|
171
171
|
expect(File.read(File.join(project, 'features/support/env.rb'))).to include("require 'raider_reporter/cucumber'")
|
|
172
172
|
end
|
|
173
173
|
|
|
@@ -310,12 +310,12 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
310
310
|
describe 'Selenium + RSpec' do
|
|
311
311
|
let(:project) { generate_azure_project('rspec') }
|
|
312
312
|
|
|
313
|
-
it 'ships azure-pipelines.yml and resolves raider_reporter 0.
|
|
313
|
+
it 'ships azure-pipelines.yml and resolves raider_reporter 0.9', :aggregate_failures do
|
|
314
314
|
expect(File).to exist(File.join(project, 'azure-pipelines.yml'))
|
|
315
315
|
expect(File).not_to exist(File.join(project, '.github/workflows'))
|
|
316
316
|
skip 'Bundle install failed' unless bundle_install(project)
|
|
317
317
|
|
|
318
|
-
expect(File.read(File.join(project, 'Gemfile.lock'))).to match(/^ raider_reporter \(0\.
|
|
318
|
+
expect(File.read(File.join(project, 'Gemfile.lock'))).to match(/^ raider_reporter \(0\.9\.\d+\)$/)
|
|
319
319
|
end
|
|
320
320
|
|
|
321
321
|
it 'records provider azure_pipelines and an azure_pipelines: build key in run.json', :aggregate_failures, :slow do
|
|
@@ -332,11 +332,11 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
332
332
|
describe 'Selenium + Cucumber' do
|
|
333
333
|
let(:project) { generate_azure_project('cucumber') }
|
|
334
334
|
|
|
335
|
-
it 'ships azure-pipelines.yml and resolves raider_reporter 0.
|
|
335
|
+
it 'ships azure-pipelines.yml and resolves raider_reporter 0.9', :aggregate_failures do
|
|
336
336
|
expect(File).to exist(File.join(project, 'azure-pipelines.yml'))
|
|
337
337
|
skip 'Bundle install failed' unless bundle_install(project)
|
|
338
338
|
|
|
339
|
-
expect(File.read(File.join(project, 'Gemfile.lock'))).to match(/^ raider_reporter \(0\.
|
|
339
|
+
expect(File.read(File.join(project, 'Gemfile.lock'))).to match(/^ raider_reporter \(0\.9\.\d+\)$/)
|
|
340
340
|
end
|
|
341
341
|
|
|
342
342
|
it 'records provider azure_pipelines and an azure_pipelines: build key in run.json', :aggregate_failures, :slow do
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_raider
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Agustin Pequeno
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-10-25 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rake
|
|
@@ -354,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
354
354
|
- !ruby/object:Gem::Version
|
|
355
355
|
version: '0'
|
|
356
356
|
requirements: []
|
|
357
|
-
rubygems_version:
|
|
357
|
+
rubygems_version: 3.6.2
|
|
358
358
|
specification_version: 4
|
|
359
359
|
summary: A gem to make setup and start of UI automation projects easier
|
|
360
360
|
test_files: []
|