specwrk 0.1.4 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40f4d401d702b91aeb83be0c46ce7ca36cef7c672adf2d5d3b1cdba036121067
4
- data.tar.gz: cb7e0992a6003a88a0468f9d08ba90a2922866a36cb53a844740c9409fc9254e
3
+ metadata.gz: 0f9b53c4d462665fee20cfd4f6599770bcbe11b226f9617977a43678d3b6f511
4
+ data.tar.gz: ecd33a1c676d898160493fe5fc49c21dc4ef20c038aa2d551b01f21fcb18ddce
5
5
  SHA512:
6
- metadata.gz: bfa583f503773db843aba2e962878a00f7cc8c38cfe2cd2c56ab5165394c4a586345347afcb1efef626e920f05fe95afe949f89e1c97a5000d3477ebb0e2bea5
7
- data.tar.gz: 53bb263d94bd76886d1800f80a3a9fd8270938c7e794ad983f9c843020e0da9abaeec5c2bb664ba3642b02f2fa2b2c8f8cd537216e5af96b38d302d8cd90538e
6
+ metadata.gz: d8819747f5affeb51ea228a030856ea3659b50347ba30c177921cba4d7b966cf79bc7df69b391d2ad16607a7b4273360f82fff105e8d3f624ad3e45b6a07ff35
7
+ data.tar.gz: d225da51ec8eb8d165fb82a07cacfcc706a34cff6c7398a36b5202e8212bfd3e7656394fc56b28ca4e9a8e1ae4418eba4d083609da3c8c251981abebcb0e763f
data/README.md CHANGED
@@ -1,4 +1,165 @@
1
1
  # Specwrk
2
+ Run your [RSpec](https://github.com/rspec/rspec) examples across many processors and many nodes for a single build. Or just many processes on a single node. Speeds up your *slow* (minutes/hours not seconds) test suite by running multiple examples in parallel.
3
+
4
+ One CLI command to:
5
+
6
+ 1. Start a queue server for your current build
7
+ 2. Seed the queue server with all possible examples in the current project
8
+ 3. Execute
9
+
10
+ ## Install
11
+ Start by adding specwrk to your project or installing it.
12
+ ```sh
13
+ $ bundle add specwrk -g development,test
14
+ ```
15
+ ```sh
16
+ $ gem install specwrk
17
+ ```
18
+
19
+ ## CLI
20
+
21
+ ```sh
22
+ $ specwrk --help
23
+
24
+ Commands:
25
+ specwrk seed [DIR] # Seed the server with a list of specs for the run
26
+ specwrk serve # Start a queue server
27
+ specwrk start [DIR] # Start a server and workers, monitor until complete
28
+ specwrk version # Print version
29
+ specwrk work # Start one or more worker processes
30
+ ```
31
+
32
+ ### `specwrk start -c 8 spec/`
33
+ Indended for quick-adhoc runs in development. This command starts a queue server, seeds it with examples from the `spec/` directory, and starts `8` worker processes. It will report the ultimate success or failure.
34
+
35
+ ```sh
36
+ $ start --help
37
+ Command:
38
+ specwrk start
39
+
40
+ Usage:
41
+ specwrk start [DIR]
42
+
43
+ Description:
44
+ Start a server and workers, monitor until complete
45
+
46
+ Arguments:
47
+ DIR # Relative spec directory to run against
48
+
49
+ Options:
50
+ --uri=VALUE # HTTP URI of the server to pull jobs from. Overrides SPECWRK_SRV_PORT. Default 5138., default: "https://localhost:5138"
51
+ --key=VALUE, -k VALUE # Authentication key clients must use for access. Overrides SPECWRK_SRV_KEY. Default ''., default: ""
52
+ --run=VALUE, -r VALUE # The run identifier for this job execution. Overrides SPECWRK_RUN. Default main., default: "main"
53
+ --timeout=VALUE, -t VALUE # The amount of time to wait for the server to respond. Overrides SPECWRK_TIMEOUT. Default 5., default: "5"
54
+ --id=VALUE # The identifier for this worker. Default specwrk-worker(-COUNT_INDEX)., default: "specwrk-worker"
55
+ --count=VALUE, -c VALUE # The number of worker processes you want to start. Default 1., default: 1
56
+ --output=VALUE, -o VALUE # Directory where worker output is stored. Overrides SPECWRK_OUT. Default '.specwrk/'., default: ".specwrk/"
57
+ --port=VALUE, -p VALUE # Server port. Overrides SPECWRK_SRV_PORT. Default 5138., default: "5138"
58
+ --bind=VALUE, -b VALUE # Server bind address. Overrides SPECWRK_SRV_BIND. Default 127.0.0.1., default: "127.0.0.1"
59
+ --group-by=VALUE # How examples will be grouped for workers; fallback to file if no timings are found. Overrides SPECWERK_SRV_GROUP_BY. Default timings.: (file/timings), default: "timings"
60
+ --[no-]single-run # Act on shutdown requests from clients. Default: false., default: false
61
+ --[no-]verbose # Run in verbose mode. Default false., default: false
62
+ --help, -h # Print this help
63
+ ```
64
+
65
+ ### `specwrk serve`
66
+ Only start the server process. Intended for use in CI pipelines.
67
+
68
+ ```sh
69
+ $ specwrk serve --help
70
+ Command:
71
+ specwrk serve
72
+
73
+ Usage:
74
+ specwrk serve
75
+
76
+ Description:
77
+ Start a queue server
78
+
79
+ Options:
80
+ --port=VALUE, -p VALUE # Server port. Overrides SPECWRK_SRV_PORT. Default 5138., default: "5138"
81
+ --bind=VALUE, -b VALUE # Server bind address. Overrides SPECWRK_SRV_BIND. Default 127.0.0.1., default: "127.0.0.1"
82
+ --key=VALUE, -k VALUE # Authentication key clients must use for access. Overrides SPECWRK_SRV_KEY. Default ''., default: ""
83
+ --output=VALUE, -o VALUE # Directory where worker output is stored. Overrides SPECWRK_OUT. Default '.specwrk/'., default: ".specwrk/"
84
+ --group-by=VALUE # How examples will be grouped for workers; fallback to file if no timings are found. Overrides SPECWERK_SRV_GROUP_BY. Default timings.: (file/timings), default: "timings"
85
+ --[no-]single-run # Act on shutdown requests from clients. Default: false., default: false
86
+ --[no-]verbose # Run in verbose mode. Default false., default: false
87
+ --help, -h # Print this help
88
+ ```
89
+
90
+ ### `specwrk seed spec/`
91
+ Seed the configured server with examples from the `spec/` directory. Intended for use in CI pipelines.
92
+
93
+ ```sh
94
+ specwrk seed --help
95
+ Command:
96
+ specwrk seed
97
+
98
+ Usage:
99
+ specwrk seed [DIR]
100
+
101
+ Description:
102
+ Seed the server with a list of specs for the run
103
+
104
+ Arguments:
105
+ DIR # Relative spec directory to run against
106
+
107
+ Options:
108
+ --uri=VALUE # HTTP URI of the server to pull jobs from. Overrides SPECWRK_SRV_PORT. Default 5138., default: "https://localhost:5138"
109
+ --key=VALUE, -k VALUE # Authentication key clients must use for access. Overrides SPECWRK_SRV_KEY. Default ''., default: ""
110
+ --run=VALUE, -r VALUE # The run identifier for this job execution. Overrides SPECWRK_RUN. Default main., default: "main"
111
+ --timeout=VALUE, -t VALUE # The amount of time to wait for the server to respond. Overrides SPECWRK_TIMEOUT. Default 5., default: "5"
112
+ --help, -h # Print this help
113
+ ```
114
+
115
+ ### `specwrk work -c 8`
116
+ Starts `8` worker processes which will pull examples off the seeded server. Intended for use in CI pipelines.
117
+
118
+ ```sh
119
+ $ specwrk work --help
120
+ Command:
121
+ specwrk work
122
+
123
+ Usage:
124
+ specwrk work
125
+
126
+ Description:
127
+ Start one or more worker processes
128
+
129
+ Options:
130
+ --id=VALUE # The identifier for this worker. Default specwrk-worker(-COUNT_INDEX)., default: "specwrk-worker"
131
+ --count=VALUE, -c VALUE # The number of worker processes you want to start. Default 1., default: 1
132
+ --output=VALUE, -o VALUE # Directory where worker output is stored. Overrides SPECWRK_OUT. Default '.specwrk/'., default: ".specwrk/"
133
+ --uri=VALUE # HTTP URI of the server to pull jobs from. Overrides SPECWRK_SRV_PORT. Default 5138., default: "https://localhost:5138"
134
+ --key=VALUE, -k VALUE # Authentication key clients must use for access. Overrides SPECWRK_SRV_KEY. Default ''., default: ""
135
+ --run=VALUE, -r VALUE # The run identifier for this job execution. Overrides SPECWRK_RUN. Default main., default: "main"
136
+ --timeout=VALUE, -t VALUE # The amount of time to wait for the server to respond. Overrides SPECWRK_TIMEOUT. Default 5., default: "5"
137
+ --help, -h # Print this help
138
+ ```
139
+
140
+ ## Configuring your test environment
141
+ If you test suite tracks state, starts servers, etc. and you plan on running many processes on the same node, you'll need to make
142
+ adjustments to avoid conflicting port usage or database/state mutations.
143
+
144
+ `specwrk` workers will have `TEST_ENV_NUMBER={i}` set to help you configure approriately.
145
+
146
+ ### Rails
147
+ Rails has had easy multi-process test setup for a while now by creating unique test databases per process. For my rails v7.2 app which uses PostgreSQL and Capyabara, I made these changes to my `spec/rails_helper.rb`:
148
+
149
+ ```diff
150
+ ++ if ENV["TEST_ENV_NUMBER"]
151
+ ++ ActiveRecord::TestDatabases.create_and_load_schema(
152
+ ++ ENV["TEST_ENV_NUMBER"].to_i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
153
+ ++ )
154
+ ++ end
155
+ -- Capybara.server_port = 5550
156
+ ++ Capybara.server_port = 5550 + ENV.fetch("TEST_ENV_NUMBER", "1").to_i
157
+ ++ Capybara.always_include_port = true
158
+ ```
159
+
160
+ ## CI
161
+ 1 server N nodes with N processes => 🏎️
162
+
2
163
  TODO!
3
164
 
4
165
  ## Contributing
@@ -0,0 +1,20 @@
1
+ FROM ruby:3.4-alpine
2
+
3
+ WORKDIR /app
4
+
5
+ RUN mkdir .specwrk/
6
+
7
+ ARG SPECWRK_SRV_PORT=5138
8
+ ARG SPECWRK_VERSION=latest
9
+ ARG GEMFILE=specwrk-$SPECWRK_VERSION.gem
10
+
11
+ COPY $GEMFILE ./
12
+ RUN gem install ./$GEMFILE --no-document
13
+ RUN rm ./$GEMFILE
14
+
15
+ COPY docker/entrypoint.server.sh /usr/local/bin/entrypoint
16
+ RUN chmod +x /usr/local/bin/entrypoint
17
+
18
+ EXPOSE ${SPECWRK_SRV_PORT}
19
+
20
+ ENTRYPOINT ["entrypoint"]
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ exec specwrk serve --port ${PORT:-$SPECWRK_SRV_PORT} --bind 0.0.0.0 --no-single-run --verbose
data/lib/specwrk/cli.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require "fileutils"
4
5
 
5
6
  require "dry/cli"
6
7
 
@@ -42,6 +43,7 @@ module Specwrk
42
43
  ENV["SPECWRK_ID"] = id
43
44
  ENV["SPECWRK_COUNT"] = count.to_s
44
45
  ENV["SPECWRK_OUT"] = Pathname.new(output).expand_path(Dir.pwd).to_s
46
+ FileUtils.mkdir_p(ENV["SPECWRK_OUT"])
45
47
  end
46
48
 
47
49
  def start_workers
@@ -75,10 +77,14 @@ module Specwrk
75
77
  base.unique_option :verbose, type: :boolean, default: false, desc: "Run in verbose mode. Default false."
76
78
  end
77
79
 
78
- on_setup do |output:, port:, key:, single_run:, group_by:, verbose:, **|
79
- ENV["SPECWRK_SRV_LOG"] = Pathname.new(File.join(output, "server.log")).expand_path(Dir.pwd).to_s if output && !verbose
80
- ENV["SPECWRK_SRV_OUTPUT"] = Pathname.new(File.join(output, "report.json")).expand_path(Dir.pwd).to_s if output
80
+ on_setup do |port:, bind:, output:, key:, single_run:, group_by:, verbose:, **|
81
+ ENV["SPECWRK_OUT"] = Pathname.new(output).expand_path(Dir.pwd).to_s
82
+ FileUtils.mkdir_p(ENV["SPECWRK_OUT"])
83
+
84
+ ENV["SPECWRK_SRV_LOG"] ||= Pathname.new(File.join(ENV["SPECWRK_OUT"], "server.log")).to_s if output && !verbose
85
+ ENV["SPECWRK_SRV_OUTPUT"] ||= Pathname.new(File.join(ENV["SPECWRK_OUT"], "report.json")).expand_path(Dir.pwd).to_s if output
81
86
  ENV["SPECWRK_SRV_PORT"] = port
87
+ ENV["SPECWRK_SRV_BIND"] = bind
82
88
  ENV["SPECWRK_SRV_KEY"] = key
83
89
  ENV["SPECWRK_SRV_SINGLE_RUN"] = "1" if single_run
84
90
  ENV["SPECWRK_SRV_GROUP_BY"] = group_by
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Specwrk
4
- VERSION = "0.1.4"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -27,7 +27,7 @@ module Specwrk
27
27
 
28
28
  server_opts = {
29
29
  Port: ENV.fetch("SPECWRK_SRV_PORT", "5138").to_i,
30
- Host: ENV.fetch("SPECWRK_SRV_BIND", "127.0.0.1"),
30
+ BindAddress: ENV.fetch("SPECWRK_SRV_BIND", "127.0.0.1"),
31
31
  Logger: WEBrick::Log.new($stdout, WEBrick::Log::FATAL),
32
32
  AccessLog: [],
33
33
  KeepAliveTimeout: 300
@@ -29,9 +29,13 @@ module Specwrk
29
29
  break if Specwrk.force_quit
30
30
 
31
31
  execute
32
- rescue CompletedAllExamplesError, NoMoreExamplesError
33
- # TODO: Sleep on NoMoreExamplesError to allow for retries
32
+ rescue CompletedAllExamplesError
34
33
  break
34
+ rescue NoMoreExamplesError
35
+ # Wait for the other processes (workers) on the same host to finish
36
+ # This will cause workers to 'hang' until all work has been completed
37
+ # TODO: break here if all the other worker processes on this host are done executing examples
38
+ sleep 0.5
35
39
  end
36
40
 
37
41
  executor.final_output.tap(&:rewind).each_line { |line| $stdout.write line }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: specwrk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Westendorf
@@ -121,6 +121,20 @@ dependencies:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: gem-release
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
124
138
  email:
125
139
  - daniel@prowestech.com
126
140
  executables:
@@ -134,6 +148,8 @@ files:
134
148
  - LICENSE.txt
135
149
  - README.md
136
150
  - Rakefile
151
+ - docker/Dockerfile.server
152
+ - docker/entrypoint.server.sh
137
153
  - exe/specwrk
138
154
  - lib/specwrk.rb
139
155
  - lib/specwrk/cli.rb
@@ -155,7 +171,7 @@ files:
155
171
  - lib/specwrk/worker/progress_formatter.rb
156
172
  homepage: https://github.com/danielwestendorf/specwrk
157
173
  licenses:
158
- - LGPLv3
174
+ - GPL-3.0-or-later
159
175
  metadata:
160
176
  homepage_uri: https://github.com/danielwestendorf/specwrk
161
177
  source_code_uri: https://github.com/danielwestendorf/specwrk