zarro 1.99.1 → 1.99.4
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.
- package/README.md +260 -260
- package/gulp-tasks/build.js +28 -6
- package/gulp-tasks/clean.js +37 -37
- package/gulp-tasks/cover-dotnet.js +56 -56
- package/gulp-tasks/dotnet-publish.js +24 -24
- package/gulp-tasks/git-submodules.js +83 -83
- package/gulp-tasks/modules/ask.ts +41 -41
- package/gulp-tasks/modules/download-nuget.js +104 -104
- package/gulp-tasks/modules/ensure-folder-exists.js +28 -28
- package/gulp-tasks/modules/env-helpers.ts +67 -67
- package/gulp-tasks/modules/env.js +361 -337
- package/gulp-tasks/modules/fail-after.ts +34 -34
- package/gulp-tasks/modules/find-npm-base.js +42 -42
- package/gulp-tasks/modules/fs.js +79 -79
- package/gulp-tasks/modules/get-tools-folder.js +12 -0
- package/gulp-tasks/modules/git-push-tags.ts +42 -42
- package/gulp-tasks/modules/git-push.js +53 -53
- package/gulp-tasks/modules/git-tag.js +36 -36
- package/gulp-tasks/modules/gulp-dotnetcover.js +537 -537
- package/gulp-tasks/modules/gulp-git-tag-from-csproj.ts +71 -71
- package/gulp-tasks/modules/gulp-git-tag-from-package-nuspec.js +55 -55
- package/gulp-tasks/modules/gulp-increment-nuget-package-dependency-version.js +40 -40
- package/gulp-tasks/modules/gulp-increment-nuget-package-version.ts +122 -122
- package/gulp-tasks/modules/gulp-msbuild.js +1 -1
- package/gulp-tasks/modules/gulp-npm-run.ts +52 -52
- package/gulp-tasks/modules/gulp-nuget-pack.js +168 -168
- package/gulp-tasks/modules/gulp-nuget-restore.js +106 -106
- package/gulp-tasks/modules/gulp-nunit-runner/.jshintrc +6 -7
- package/gulp-tasks/modules/gulp-nunit-runner/README.md +300 -300
- package/gulp-tasks/modules/gulp-nunit-runner/index.js +1 -1
- package/gulp-tasks/modules/gulp-nunit-runner/lib/index.js +205 -205
- package/gulp-tasks/modules/gulp-nunit-runner/lib/teamcity.js +86 -86
- package/gulp-tasks/modules/gulp-purge.js +88 -88
- package/gulp-tasks/modules/gulp.js +92 -92
- package/gulp-tasks/modules/http-downloader.js +113 -113
- package/gulp-tasks/modules/import-npm-tasks.js +33 -33
- package/gulp-tasks/modules/increment-version-string.js +18 -18
- package/gulp-tasks/modules/increment-version.ts +41 -41
- package/gulp-tasks/modules/install-local-tools.js +122 -122
- package/gulp-tasks/modules/load-xml-file.ts +15 -15
- package/gulp-tasks/modules/log-config.js +31 -26
- package/gulp-tasks/modules/multi-split.js +28 -27
- package/gulp-tasks/modules/net-framework-test-assembly-filter.js +45 -0
- package/gulp-tasks/modules/nuget-push.ts +72 -72
- package/gulp-tasks/modules/nuget-update-self.js +9 -9
- package/gulp-tasks/modules/nuget.ts +14 -14
- package/gulp-tasks/modules/pad-left.js +4 -7
- package/gulp-tasks/modules/pad-right.js +4 -7
- package/gulp-tasks/modules/pad.js +25 -25
- package/gulp-tasks/modules/parse-xml-string.ts +6 -6
- package/gulp-tasks/modules/promisify-function.ts +18 -18
- package/gulp-tasks/modules/promisify-stream.js +73 -73
- package/gulp-tasks/modules/read-all-git-branches.ts +13 -13
- package/gulp-tasks/modules/read-all-git-remotes.ts +44 -44
- package/gulp-tasks/modules/read-csproj-package-version.ts +26 -26
- package/gulp-tasks/modules/read-csproj-version.ts +26 -26
- package/gulp-tasks/modules/read-current-git-branch.ts +16 -16
- package/gulp-tasks/modules/read-git-commit-delta-count.ts +33 -33
- package/gulp-tasks/modules/read-git-info.ts +31 -31
- package/gulp-tasks/modules/read-git-remote.ts +23 -23
- package/gulp-tasks/modules/read-last-fetch-time.ts +17 -17
- package/gulp-tasks/modules/read-main-branch-name.ts +75 -75
- package/gulp-tasks/modules/read-nuspec-version.ts +22 -22
- package/gulp-tasks/modules/read-package-json.ts +22 -22
- package/gulp-tasks/modules/register-environment-variables.js +531 -458
- package/gulp-tasks/modules/resolve-git-branch.ts +13 -13
- package/gulp-tasks/modules/resolve-git-remote.ts +13 -13
- package/gulp-tasks/modules/resolve-masks.js +45 -38
- package/gulp-tasks/modules/resolve-nuget.js +135 -135
- package/gulp-tasks/modules/resolve-test-masks.js +10 -12
- package/gulp-tasks/modules/rewrite-file.ts +34 -34
- package/gulp-tasks/modules/run-sequence.js +16 -16
- package/gulp-tasks/modules/safe-git.ts +23 -23
- package/gulp-tasks/modules/seed.js +4 -8
- package/gulp-tasks/modules/testutil-finder.js +174 -148
- package/gulp-tasks/modules/uniq.ts +5 -5
- package/gulp-tasks/modules/version-reading-shared.ts +16 -16
- package/gulp-tasks/modules/zarro-error.js +6 -8
- package/gulp-tasks/nuget-restore.js +57 -57
- package/gulp-tasks/pack.js +118 -118
- package/gulp-tasks/release-npm.ts +81 -81
- package/gulp-tasks/start/_package.json +39 -39
- package/gulp-tasks/start/gulpfile.js +204 -204
- package/gulp-tasks/start/update-starter-packages.js +63 -63
- package/gulp-tasks/test-dotnet.js +196 -146
- package/gulp-tasks/update-git-submodules.ts +29 -29
- package/gulp-tasks/update-self.js +4 -4
- package/gulp-tasks/update-self.ts +88 -88
- package/gulp-tasks/verify-up-to-date.js +3 -3
- package/gulp-tasks/verify-up-to-date.ts +119 -119
- package/index-modules/contains-any.js +31 -31
- package/index-modules/handlers/show-env.js +46 -46
- package/index.js +0 -0
- package/package.json +1 -2
- package/tsconfig.json +66 -66
- package/types.d.ts +757 -865
- package/gulp-tasks/modules/env.ts +0 -432
- package/gulp-tasks/modules/find-tools-folder.js +0 -11
- package/gulp-tasks/modules/find-tools-folder.ts +0 -12
- package/gulp-tasks/modules/generate-net-framework-test-assembly-filter.js +0 -35
- package/gulp-tasks/modules/generate-net-framework-test-assembly-filter.ts +0 -48
- package/gulp-tasks/modules/gulp-nunit-runner/.editorconfig +0 -16
- package/gulp-tasks/modules/gulp-nunit-runner/.gitignore +0 -59
- package/gulp-tasks/modules/gulp-nunit-runner/.jscsrc +0 -4
- package/gulp-tasks/modules/gulp-nunit-runner/.travis.yml +0 -7
- package/gulp-tasks/modules/gulp-nunit-runner/gulpfile.js +0 -26
- package/gulp-tasks/modules/gulp-nunit-runner/test/gulp-nunit-runner-index.spec.js +0 -209
- package/gulp-tasks/modules/gulp-nunit-runner/test/gulp-nunit-runner-teamcity.spec.js +0 -105
- package/gulp-tasks/modules/gulp-nunit-runner/test/teamcity.xml +0 -191
- package/gulp-tasks/modules/log-config.ts +0 -48
- package/gulp-tasks/modules/multi-split.ts +0 -35
- package/gulp-tasks/modules/pad-left.ts +0 -10
- package/gulp-tasks/modules/pad-right.ts +0 -10
- package/gulp-tasks/modules/pad.ts +0 -32
- package/gulp-tasks/modules/register-environment-variables.ts +0 -558
- package/gulp-tasks/modules/resolve-masks.ts +0 -51
- package/gulp-tasks/modules/resolve-test-masks.ts +0 -12
- package/gulp-tasks/modules/seed.ts +0 -12
- package/gulp-tasks/modules/testutil-finder.ts +0 -214
- package/gulp-tasks/test-dotnet.ts +0 -219
package/README.md
CHANGED
|
@@ -1,260 +1,260 @@
|
|
|
1
|
-
# Zarro
|
|
2
|
-

|
|
3
|
-
|
|
4
|
-

|
|
5
|
-
|
|
6
|
-
## What is this?
|
|
7
|
-
|
|
8
|
-
Standing on the shoulders of giants, zarro is a zero- or low-conf orchestration for
|
|
9
|
-
(primarily) dotnet/.NET build and test (eg at CI), but it's also so much more - since
|
|
10
|
-
it's easy to add your own tasks, you can use zarro for whatever you like, but if you're
|
|
11
|
-
looking for CI build / test / coverage* for dotnet/.NET, this might be what you're looking
|
|
12
|
-
for.
|
|
13
|
-
|
|
14
|
-
_(* coverage works well for NUnit / .NET Framework, but I haven't found a nice process
|
|
15
|
-
for dotnet core - yet)_
|
|
16
|
-
|
|
17
|
-
## Why not just use `msbuild`?
|
|
18
|
-
|
|
19
|
-
Zarro wraps msbuild, using `gulp` orchestration under the hood. It does, however,
|
|
20
|
-
take away the pain of:
|
|
21
|
-
- knowing _where_ msbuild lives (since it consumes [gulp-msbuild](https://www.npmjs.com/package/gulp-msbuild)
|
|
22
|
-
- being able to use a specific version of msbuild (again, thanks to `gulp-msbuild`)
|
|
23
|
-
- running tests via `dotnet test` or via the NUnit CLI runner, as appropriate
|
|
24
|
-
- running coverage reporting (.NET Framework) via OpenCover
|
|
25
|
-
- downloading local variants of tooling required for the above so that your CI server
|
|
26
|
-
doesn't have to have them installed, or kept up to date
|
|
27
|
-
- note: zarro will not download msbuild tooling, but should work fine with any
|
|
28
|
-
installed version of:
|
|
29
|
-
- VS Community / Professional / Enterprise
|
|
30
|
-
- VS Build Tools
|
|
31
|
-
- dotnet sdk (dotnet kindly adds itself to the path)
|
|
32
|
-
- packing nuget packages, either from .nuspecs (.NET Framework) or directly
|
|
33
|
-
from the .csproj (dotnet core)
|
|
34
|
-
|
|
35
|
-
## Fine, but I can do all of that with a batch file?
|
|
36
|
-
|
|
37
|
-
Perhaps (though the msbuild discovery is a bit of a PITA, especially since Microsoft
|
|
38
|
-
likes to keep us on our toes, mixing up exactly _where_ that's installed to, eg in
|
|
39
|
-
vs2019. The real win comes from:
|
|
40
|
-
- out of the box, on a simple-ish repo, zarro should be able to build and test,
|
|
41
|
-
as long as you use the naming convention of `{Assembly}.Tests` for test projects
|
|
42
|
-
(though it will also find `Test.{Assembly}` and an ubiquitous `Tests` assembluy)
|
|
43
|
-
- it's easy to add more tasks to your pipeline for further processing
|
|
44
|
-
- use the `gulp` orchestration framework to extend or override available tasks
|
|
45
|
-
|
|
46
|
-
## _Which_ `gulp`? 3 or 4? They don't play well together!
|
|
47
|
-
|
|
48
|
-
Zarro has you covered here. The heart of Zarro was originally built for gulp 3.
|
|
49
|
-
Version 4 came out and broke _everything_. I didn't feel like rewriting perfectly
|
|
50
|
-
acceptable tasks, but I did want to keep up with the latest version of `gulp` and
|
|
51
|
-
the speed advantages that were promised. As such, Zarro can consume and adapt
|
|
52
|
-
gulp 3 tasks to run under gulp 4.
|
|
53
|
-
|
|
54
|
-
## Getting started
|
|
55
|
-
|
|
56
|
-
1. `npm init -y` (if you don't already have a `package.json`
|
|
57
|
-
2. `npm install --save-dev zarro`
|
|
58
|
-
3. start adding scripts! for example:
|
|
59
|
-
```json
|
|
60
|
-
"scripts": {
|
|
61
|
-
"build": "zarro build",
|
|
62
|
-
"test": "zarro test-dotnet",
|
|
63
|
-
"zarro": "zarro"
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
(the `test-dotnet` task should invoke zarro's inbuilt `build` task (and some earlier
|
|
67
|
-
ones to download tooling, as required) so that when test-time comes, assemblies
|
|
68
|
-
are already built (required for .NET Framework / NUnit runner, and optimised for
|
|
69
|
-
`dotnet` by performing the build and testing without rebuild)).
|
|
70
|
-
|
|
71
|
-
## What's in the box
|
|
72
|
-
There are an array of pre-defined tasks you get out of the box with zarro. I hope to eventually
|
|
73
|
-
provide more documentation for them, but running `zarro --tasks` should tell you something
|
|
74
|
-
similar to:
|
|
75
|
-
|
|
76
|
-
- help
|
|
77
|
-
- shows help / usage
|
|
78
|
-
- help:environment
|
|
79
|
-
- shows help about environment variables zarro observes (same as running with --help)
|
|
80
|
-
- build
|
|
81
|
-
- attempts to build all found .net solutions
|
|
82
|
-
- test-dotnet
|
|
83
|
-
- test .net projects based on conventions
|
|
84
|
-
- test project names should match `*.Tests` or `*.Test` or plain old `Tests`
|
|
85
|
-
- assumes test are nunit
|
|
86
|
-
- cover-dotnet
|
|
87
|
-
- test with coverage
|
|
88
|
-
- can use dotCover or OpenCover
|
|
89
|
-
- generate-reports
|
|
90
|
-
- generate html reports from OpenCover results
|
|
91
|
-
- default-tools-installer
|
|
92
|
-
- installs the default helper tooling from nuget
|
|
93
|
-
- nunit cli
|
|
94
|
-
- dotCover
|
|
95
|
-
- OpenCover
|
|
96
|
-
- ReportGenerator
|
|
97
|
-
- install-tools
|
|
98
|
-
- called before build
|
|
99
|
-
- defaults to install default tools
|
|
100
|
-
- override with an empty task if not useful
|
|
101
|
-
- dotnet-publish
|
|
102
|
-
- runs dotnet cli build with publish options
|
|
103
|
-
- nuget-restor
|
|
104
|
-
- restores nuget packages
|
|
105
|
-
- run automatically as part of build
|
|
106
|
-
- release-npm
|
|
107
|
-
- perform guided release of npm packages
|
|
108
|
-
- can do beta releases
|
|
109
|
-
- will automatically
|
|
110
|
-
- increment version
|
|
111
|
-
- git commit
|
|
112
|
-
- git tag
|
|
113
|
-
- git push
|
|
114
|
-
- update-self
|
|
115
|
-
- updates to zarro@latest
|
|
116
|
-
- update-git-submodules
|
|
117
|
-
- updates all git submodules in the repo
|
|
118
|
-
- pretest
|
|
119
|
-
- place-holder: override this to run something before testing
|
|
120
|
-
- verify-up-to-date
|
|
121
|
-
- verifies that the current branch is up-to-date with the main one
|
|
122
|
-
- will check against {remote}/{main branch} if possible
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
Running the above would also list any custom tasks you have defined
|
|
126
|
-
|
|
127
|
-
## Zarro doesn't do what I want out of the box
|
|
128
|
-
|
|
129
|
-
Zarro is designed to be zero- to low- conf. You can guide many aspects of available
|
|
130
|
-
tasks with environment variables. Running `npm run zarro -- --show-env` will show you
|
|
131
|
-
all observed environment variables and where they are applicable. I suggest using
|
|
132
|
-
`cross-env` and applying these variables in one place, to keep things simpler. For
|
|
133
|
-
example, [NExpect](https://github.com/fluffynuts/NExpect) does the following:
|
|
134
|
-
|
|
135
|
-
```json
|
|
136
|
-
"scripts": {
|
|
137
|
-
"zarro": "cross-env DOTNET_CORE=1 BUILD_EXCLUDE=src/PeanutButter/**/* PACK_INCLUDE=* PACK_EXCLUDE=*Tests*,CoreConsumer,src/PeanutButter/**/* TEST_EXCLUDE=src/PeanutButter/**/* zarro",
|
|
138
|
-
"build": "run-s \"zarro build\"",
|
|
139
|
-
"test": "run-s \"zarro test-dotnet\""
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
in the above:
|
|
144
|
-
- `DOTNET_CORE=1` instructs zarro to use `dotnet` instead of searching for `msbuild`
|
|
145
|
-
- `BUILD_EXCLUDE=...` instructs zarro to exclude everything under that folder, recursively
|
|
146
|
-
(NExpect imports PeanutButter as a submodule to use some shared code without relying
|
|
147
|
-
on another package dependency)
|
|
148
|
-
- similarly `TEST_EXCLUDE` excludes PeanutButter tests
|
|
149
|
-
- similarly, `PACK_INCLUDE` and `PACK_EXCLUDE` control nuget packing within NExpect
|
|
150
|
-
|
|
151
|
-
## Custom tasks
|
|
152
|
-
|
|
153
|
-
Zarro will also search two folders:
|
|
154
|
-
- local-tasks
|
|
155
|
-
- override-tasks
|
|
156
|
-
in the root of your repo, for extra tasks that you can access from your npm scripts.
|
|
157
|
-
|
|
158
|
-
These can be brand-new functionality you'd like to add to your repo's build system,
|
|
159
|
-
or you can _override existing tasks_, if they don't suit you. For example, if the `pack`
|
|
160
|
-
task doesn't do exactly what you want, copy `pack.js` from `node_modules/zarro/gulp-tasks`
|
|
161
|
-
into your `local-tasks` folder and modify it to suit you. If you find a generic solution
|
|
162
|
-
to the problem you have which others might find useful or fix a bug, I'd like to know
|
|
163
|
-
about it. PRs for fixes and extension tasks which others could use will be appreciated.
|
|
164
|
-
|
|
165
|
-
## Examples of custom tasks that I've written in the past
|
|
166
|
-
- a watcher to automatically recompile scss to .css
|
|
167
|
-
- orchestration of build / test of sub-projects that aren't .NET
|
|
168
|
-
- automatic version incrementing of packages before release
|
|
169
|
-
- committing, tagging and pushing new changes to GitHub
|
|
170
|
-
- I've found that writing a meta task called `release` can make it much
|
|
171
|
-
less painful to perform a release of my nuget packages, for example.
|
|
172
|
-
This meta task would:
|
|
173
|
-
- build
|
|
174
|
-
- test
|
|
175
|
-
- increment package versions
|
|
176
|
-
- pack
|
|
177
|
-
- push packages
|
|
178
|
-
- commit the updates package definitions
|
|
179
|
-
- tag the release
|
|
180
|
-
- push the tag and changes to GitHub
|
|
181
|
-
|
|
182
|
-
## API
|
|
183
|
-
|
|
184
|
-
Zarro provides some convenience functionality from baked-in modules. To access a module,
|
|
185
|
-
the global `requireModule` function will resolve the correct location for you. Modules
|
|
186
|
-
live under the `gulp-tasks/modules` folder. Most modules will return a single function,
|
|
187
|
-
though there are some exceptions. Some modules may be of interest to custom tasks, eg:
|
|
188
|
-
|
|
189
|
-
- `gulp`
|
|
190
|
-
- you should `requireModule("gulp")` wherever you would have normally
|
|
191
|
-
done `require("gulp")`. This gets you the patched version of gulp 4 which
|
|
192
|
-
will happily consume gulp 3 tasks and which has inbuilt support for help
|
|
193
|
-
for your tasks on both gulp 3 and 4. Most importantly, if you _do not_ use this
|
|
194
|
-
export, your tasks may not be correctly registered.
|
|
195
|
-
- `env`
|
|
196
|
-
- provides a utility object to resolve environment variables for you
|
|
197
|
-
- `register` can register an environment variable as known with a default
|
|
198
|
-
value and help. See `register-environment-variables.
|
|
199
|
-
When you use this function, you can have a central configuration for
|
|
200
|
-
a default value for an environment variable and your environment
|
|
201
|
-
variable will be displayed in the `--show-env` output
|
|
202
|
-
- `resolve` resolves environment variables for you. It can be invoked with
|
|
203
|
-
one or more variable names, so can be used to fall back from one variable
|
|
204
|
-
onto another. It will also resolve back values if registered.
|
|
205
|
-
- `associate` associates one or more variables with one or more tasks,
|
|
206
|
-
primarily to show which tasks are affected by which variables when
|
|
207
|
-
running with `--show-env`
|
|
208
|
-
- `resolveArray` can resolve an environment variable to an array for you,
|
|
209
|
-
with an optional `delimiter` parameter, which defaults to comma
|
|
210
|
-
- `resolveNumber` resolves a numeric value from the named environment
|
|
211
|
-
value or throws if the value can't be resolved as a number, effectively
|
|
212
|
-
stopping execution. If you're expecting a number (eg port or max thread
|
|
213
|
-
count) you can simply `resolveNumber` and an invalid value would cause
|
|
214
|
-
execution to stop with a reasonable message
|
|
215
|
-
- `resolveFlag` resolves boolean values from environment variables
|
|
216
|
-
- `true` for: "yes", "true" or "1"
|
|
217
|
-
- `false` for: "no", "false" or "0"
|
|
218
|
-
- throws for unknown values
|
|
219
|
-
- `resolve-masks`
|
|
220
|
-
- single function to resolve an array of masks that could be used in a `gulp.src`
|
|
221
|
-
where those masks can be inclusive or exclusive
|
|
222
|
-
- `find-local-nuget`
|
|
223
|
-
- provides a single function to find a locally-downloaded `nuget.exe`, automatically
|
|
224
|
-
downloading it if required. Use this if you need to use `nuget.exe` operations
|
|
225
|
-
and don't want to set up your build host with a pathed `nuget.exe`
|
|
226
|
-
- git utilities
|
|
227
|
-
- `git-tag`
|
|
228
|
-
- `git-push`
|
|
229
|
-
- `git-push-tags`
|
|
230
|
-
- string padding
|
|
231
|
-
- `pad`
|
|
232
|
-
- `pad-left`
|
|
233
|
-
- `pad-right`
|
|
234
|
-
|
|
235
|
-
There are many more utilities in there, feel free to browse the source.
|
|
236
|
-
|
|
237
|
-
## History
|
|
238
|
-
|
|
239
|
-
If you've made it thus far, some light history might be of interest. Zarro's core
|
|
240
|
-
functionality comes from another repo of mine: [gulp-tasks](https://github.com/fluffynuts/gulp-tasks)
|
|
241
|
-
which was traditionally consumed as a git submodule. However, it seems that a lot
|
|
242
|
-
of people don't really "get" git submodules:
|
|
243
|
-
- people forget (or don't understand that they need to) `git submodule update --init` after
|
|
244
|
-
a `git clone` or a `git pull`. Some modern git clients are doing this for the user,
|
|
245
|
-
but not all of them.
|
|
246
|
-
- people don't seem to understand how submodules are stored (literally just a hash and
|
|
247
|
-
an url), so they don't pay attention when committing them. In particular, I have seen
|
|
248
|
-
my fair share of inadvertent "submodule wars" where changes upstream aren't applied
|
|
249
|
-
after a `pull` (ie, people forget to run `git submodule update --init`), then they
|
|
250
|
-
re-commit back the _old version_ of the module that they have locally. So fixes tend
|
|
251
|
-
to become unfixed
|
|
252
|
-
- in addition, `gulp-tasks` requires dependencies to be installed in the hosting repo's
|
|
253
|
-
package.json, meaning that (a) the hosting repo has to "know too much" about the
|
|
254
|
-
requirements of `gulp-tasks` and (b) upstream changes may require changes to a repo's
|
|
255
|
-
package.json (and an `npm install`). Whilst this was (eventually) automated as part
|
|
256
|
-
of `gulp-tasks`, it seems unnecessarily complex.
|
|
257
|
-
- the solution seemed clear: make `gulp-tasks` available via an npm package
|
|
258
|
-
- the name is inspired from the old bugzilla, which would proudly proclaim "zarro boogs"
|
|
259
|
-
when there were zero bug matches for a query, because (a) names are hard and (b)
|
|
260
|
-
zarro aims to be zero- to low-conf
|
|
1
|
+
# Zarro
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
## What is this?
|
|
7
|
+
|
|
8
|
+
Standing on the shoulders of giants, zarro is a zero- or low-conf orchestration for
|
|
9
|
+
(primarily) dotnet/.NET build and test (eg at CI), but it's also so much more - since
|
|
10
|
+
it's easy to add your own tasks, you can use zarro for whatever you like, but if you're
|
|
11
|
+
looking for CI build / test / coverage* for dotnet/.NET, this might be what you're looking
|
|
12
|
+
for.
|
|
13
|
+
|
|
14
|
+
_(* coverage works well for NUnit / .NET Framework, but I haven't found a nice process
|
|
15
|
+
for dotnet core - yet)_
|
|
16
|
+
|
|
17
|
+
## Why not just use `msbuild`?
|
|
18
|
+
|
|
19
|
+
Zarro wraps msbuild, using `gulp` orchestration under the hood. It does, however,
|
|
20
|
+
take away the pain of:
|
|
21
|
+
- knowing _where_ msbuild lives (since it consumes [gulp-msbuild](https://www.npmjs.com/package/gulp-msbuild)
|
|
22
|
+
- being able to use a specific version of msbuild (again, thanks to `gulp-msbuild`)
|
|
23
|
+
- running tests via `dotnet test` or via the NUnit CLI runner, as appropriate
|
|
24
|
+
- running coverage reporting (.NET Framework) via OpenCover
|
|
25
|
+
- downloading local variants of tooling required for the above so that your CI server
|
|
26
|
+
doesn't have to have them installed, or kept up to date
|
|
27
|
+
- note: zarro will not download msbuild tooling, but should work fine with any
|
|
28
|
+
installed version of:
|
|
29
|
+
- VS Community / Professional / Enterprise
|
|
30
|
+
- VS Build Tools
|
|
31
|
+
- dotnet sdk (dotnet kindly adds itself to the path)
|
|
32
|
+
- packing nuget packages, either from .nuspecs (.NET Framework) or directly
|
|
33
|
+
from the .csproj (dotnet core)
|
|
34
|
+
|
|
35
|
+
## Fine, but I can do all of that with a batch file?
|
|
36
|
+
|
|
37
|
+
Perhaps (though the msbuild discovery is a bit of a PITA, especially since Microsoft
|
|
38
|
+
likes to keep us on our toes, mixing up exactly _where_ that's installed to, eg in
|
|
39
|
+
vs2019. The real win comes from:
|
|
40
|
+
- out of the box, on a simple-ish repo, zarro should be able to build and test,
|
|
41
|
+
as long as you use the naming convention of `{Assembly}.Tests` for test projects
|
|
42
|
+
(though it will also find `Test.{Assembly}` and an ubiquitous `Tests` assembluy)
|
|
43
|
+
- it's easy to add more tasks to your pipeline for further processing
|
|
44
|
+
- use the `gulp` orchestration framework to extend or override available tasks
|
|
45
|
+
|
|
46
|
+
## _Which_ `gulp`? 3 or 4? They don't play well together!
|
|
47
|
+
|
|
48
|
+
Zarro has you covered here. The heart of Zarro was originally built for gulp 3.
|
|
49
|
+
Version 4 came out and broke _everything_. I didn't feel like rewriting perfectly
|
|
50
|
+
acceptable tasks, but I did want to keep up with the latest version of `gulp` and
|
|
51
|
+
the speed advantages that were promised. As such, Zarro can consume and adapt
|
|
52
|
+
gulp 3 tasks to run under gulp 4.
|
|
53
|
+
|
|
54
|
+
## Getting started
|
|
55
|
+
|
|
56
|
+
1. `npm init -y` (if you don't already have a `package.json`
|
|
57
|
+
2. `npm install --save-dev zarro`
|
|
58
|
+
3. start adding scripts! for example:
|
|
59
|
+
```json
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "zarro build",
|
|
62
|
+
"test": "zarro test-dotnet",
|
|
63
|
+
"zarro": "zarro"
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
(the `test-dotnet` task should invoke zarro's inbuilt `build` task (and some earlier
|
|
67
|
+
ones to download tooling, as required) so that when test-time comes, assemblies
|
|
68
|
+
are already built (required for .NET Framework / NUnit runner, and optimised for
|
|
69
|
+
`dotnet` by performing the build and testing without rebuild)).
|
|
70
|
+
|
|
71
|
+
## What's in the box
|
|
72
|
+
There are an array of pre-defined tasks you get out of the box with zarro. I hope to eventually
|
|
73
|
+
provide more documentation for them, but running `zarro --tasks` should tell you something
|
|
74
|
+
similar to:
|
|
75
|
+
|
|
76
|
+
- help
|
|
77
|
+
- shows help / usage
|
|
78
|
+
- help:environment
|
|
79
|
+
- shows help about environment variables zarro observes (same as running with --help)
|
|
80
|
+
- build
|
|
81
|
+
- attempts to build all found .net solutions
|
|
82
|
+
- test-dotnet
|
|
83
|
+
- test .net projects based on conventions
|
|
84
|
+
- test project names should match `*.Tests` or `*.Test` or plain old `Tests`
|
|
85
|
+
- assumes test are nunit
|
|
86
|
+
- cover-dotnet
|
|
87
|
+
- test with coverage
|
|
88
|
+
- can use dotCover or OpenCover
|
|
89
|
+
- generate-reports
|
|
90
|
+
- generate html reports from OpenCover results
|
|
91
|
+
- default-tools-installer
|
|
92
|
+
- installs the default helper tooling from nuget
|
|
93
|
+
- nunit cli
|
|
94
|
+
- dotCover
|
|
95
|
+
- OpenCover
|
|
96
|
+
- ReportGenerator
|
|
97
|
+
- install-tools
|
|
98
|
+
- called before build
|
|
99
|
+
- defaults to install default tools
|
|
100
|
+
- override with an empty task if not useful
|
|
101
|
+
- dotnet-publish
|
|
102
|
+
- runs dotnet cli build with publish options
|
|
103
|
+
- nuget-restor
|
|
104
|
+
- restores nuget packages
|
|
105
|
+
- run automatically as part of build
|
|
106
|
+
- release-npm
|
|
107
|
+
- perform guided release of npm packages
|
|
108
|
+
- can do beta releases
|
|
109
|
+
- will automatically
|
|
110
|
+
- increment version
|
|
111
|
+
- git commit
|
|
112
|
+
- git tag
|
|
113
|
+
- git push
|
|
114
|
+
- update-self
|
|
115
|
+
- updates to zarro@latest
|
|
116
|
+
- update-git-submodules
|
|
117
|
+
- updates all git submodules in the repo
|
|
118
|
+
- pretest
|
|
119
|
+
- place-holder: override this to run something before testing
|
|
120
|
+
- verify-up-to-date
|
|
121
|
+
- verifies that the current branch is up-to-date with the main one
|
|
122
|
+
- will check against {remote}/{main branch} if possible
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
Running the above would also list any custom tasks you have defined
|
|
126
|
+
|
|
127
|
+
## Zarro doesn't do what I want out of the box
|
|
128
|
+
|
|
129
|
+
Zarro is designed to be zero- to low- conf. You can guide many aspects of available
|
|
130
|
+
tasks with environment variables. Running `npm run zarro -- --show-env` will show you
|
|
131
|
+
all observed environment variables and where they are applicable. I suggest using
|
|
132
|
+
`cross-env` and applying these variables in one place, to keep things simpler. For
|
|
133
|
+
example, [NExpect](https://github.com/fluffynuts/NExpect) does the following:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
"scripts": {
|
|
137
|
+
"zarro": "cross-env DOTNET_CORE=1 BUILD_EXCLUDE=src/PeanutButter/**/* PACK_INCLUDE=* PACK_EXCLUDE=*Tests*,CoreConsumer,src/PeanutButter/**/* TEST_EXCLUDE=src/PeanutButter/**/* zarro",
|
|
138
|
+
"build": "run-s \"zarro build\"",
|
|
139
|
+
"test": "run-s \"zarro test-dotnet\""
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
in the above:
|
|
144
|
+
- `DOTNET_CORE=1` instructs zarro to use `dotnet` instead of searching for `msbuild`
|
|
145
|
+
- `BUILD_EXCLUDE=...` instructs zarro to exclude everything under that folder, recursively
|
|
146
|
+
(NExpect imports PeanutButter as a submodule to use some shared code without relying
|
|
147
|
+
on another package dependency)
|
|
148
|
+
- similarly `TEST_EXCLUDE` excludes PeanutButter tests
|
|
149
|
+
- similarly, `PACK_INCLUDE` and `PACK_EXCLUDE` control nuget packing within NExpect
|
|
150
|
+
|
|
151
|
+
## Custom tasks
|
|
152
|
+
|
|
153
|
+
Zarro will also search two folders:
|
|
154
|
+
- local-tasks
|
|
155
|
+
- override-tasks
|
|
156
|
+
in the root of your repo, for extra tasks that you can access from your npm scripts.
|
|
157
|
+
|
|
158
|
+
These can be brand-new functionality you'd like to add to your repo's build system,
|
|
159
|
+
or you can _override existing tasks_, if they don't suit you. For example, if the `pack`
|
|
160
|
+
task doesn't do exactly what you want, copy `pack.js` from `node_modules/zarro/gulp-tasks`
|
|
161
|
+
into your `local-tasks` folder and modify it to suit you. If you find a generic solution
|
|
162
|
+
to the problem you have which others might find useful or fix a bug, I'd like to know
|
|
163
|
+
about it. PRs for fixes and extension tasks which others could use will be appreciated.
|
|
164
|
+
|
|
165
|
+
## Examples of custom tasks that I've written in the past
|
|
166
|
+
- a watcher to automatically recompile scss to .css
|
|
167
|
+
- orchestration of build / test of sub-projects that aren't .NET
|
|
168
|
+
- automatic version incrementing of packages before release
|
|
169
|
+
- committing, tagging and pushing new changes to GitHub
|
|
170
|
+
- I've found that writing a meta task called `release` can make it much
|
|
171
|
+
less painful to perform a release of my nuget packages, for example.
|
|
172
|
+
This meta task would:
|
|
173
|
+
- build
|
|
174
|
+
- test
|
|
175
|
+
- increment package versions
|
|
176
|
+
- pack
|
|
177
|
+
- push packages
|
|
178
|
+
- commit the updates package definitions
|
|
179
|
+
- tag the release
|
|
180
|
+
- push the tag and changes to GitHub
|
|
181
|
+
|
|
182
|
+
## API
|
|
183
|
+
|
|
184
|
+
Zarro provides some convenience functionality from baked-in modules. To access a module,
|
|
185
|
+
the global `requireModule` function will resolve the correct location for you. Modules
|
|
186
|
+
live under the `gulp-tasks/modules` folder. Most modules will return a single function,
|
|
187
|
+
though there are some exceptions. Some modules may be of interest to custom tasks, eg:
|
|
188
|
+
|
|
189
|
+
- `gulp`
|
|
190
|
+
- you should `requireModule("gulp")` wherever you would have normally
|
|
191
|
+
done `require("gulp")`. This gets you the patched version of gulp 4 which
|
|
192
|
+
will happily consume gulp 3 tasks and which has inbuilt support for help
|
|
193
|
+
for your tasks on both gulp 3 and 4. Most importantly, if you _do not_ use this
|
|
194
|
+
export, your tasks may not be correctly registered.
|
|
195
|
+
- `env`
|
|
196
|
+
- provides a utility object to resolve environment variables for you
|
|
197
|
+
- `register` can register an environment variable as known with a default
|
|
198
|
+
value and help. See `register-environment-variables.js` for examples.
|
|
199
|
+
When you use this function, you can have a central configuration for
|
|
200
|
+
a default value for an environment variable and your environment
|
|
201
|
+
variable will be displayed in the `--show-env` output
|
|
202
|
+
- `resolve` resolves environment variables for you. It can be invoked with
|
|
203
|
+
one or more variable names, so can be used to fall back from one variable
|
|
204
|
+
onto another. It will also resolve back values if registered.
|
|
205
|
+
- `associate` associates one or more variables with one or more tasks,
|
|
206
|
+
primarily to show which tasks are affected by which variables when
|
|
207
|
+
running with `--show-env`
|
|
208
|
+
- `resolveArray` can resolve an environment variable to an array for you,
|
|
209
|
+
with an optional `delimiter` parameter, which defaults to comma
|
|
210
|
+
- `resolveNumber` resolves a numeric value from the named environment
|
|
211
|
+
value or throws if the value can't be resolved as a number, effectively
|
|
212
|
+
stopping execution. If you're expecting a number (eg port or max thread
|
|
213
|
+
count) you can simply `resolveNumber` and an invalid value would cause
|
|
214
|
+
execution to stop with a reasonable message
|
|
215
|
+
- `resolveFlag` resolves boolean values from environment variables
|
|
216
|
+
- `true` for: "yes", "true" or "1"
|
|
217
|
+
- `false` for: "no", "false" or "0"
|
|
218
|
+
- throws for unknown values
|
|
219
|
+
- `resolve-masks`
|
|
220
|
+
- single function to resolve an array of masks that could be used in a `gulp.src`
|
|
221
|
+
where those masks can be inclusive or exclusive
|
|
222
|
+
- `find-local-nuget`
|
|
223
|
+
- provides a single function to find a locally-downloaded `nuget.exe`, automatically
|
|
224
|
+
downloading it if required. Use this if you need to use `nuget.exe` operations
|
|
225
|
+
and don't want to set up your build host with a pathed `nuget.exe`
|
|
226
|
+
- git utilities
|
|
227
|
+
- `git-tag`
|
|
228
|
+
- `git-push`
|
|
229
|
+
- `git-push-tags`
|
|
230
|
+
- string padding
|
|
231
|
+
- `pad`
|
|
232
|
+
- `pad-left`
|
|
233
|
+
- `pad-right`
|
|
234
|
+
|
|
235
|
+
There are many more utilities in there, feel free to browse the source.
|
|
236
|
+
|
|
237
|
+
## History
|
|
238
|
+
|
|
239
|
+
If you've made it thus far, some light history might be of interest. Zarro's core
|
|
240
|
+
functionality comes from another repo of mine: [gulp-tasks](https://github.com/fluffynuts/gulp-tasks)
|
|
241
|
+
which was traditionally consumed as a git submodule. However, it seems that a lot
|
|
242
|
+
of people don't really "get" git submodules:
|
|
243
|
+
- people forget (or don't understand that they need to) `git submodule update --init` after
|
|
244
|
+
a `git clone` or a `git pull`. Some modern git clients are doing this for the user,
|
|
245
|
+
but not all of them.
|
|
246
|
+
- people don't seem to understand how submodules are stored (literally just a hash and
|
|
247
|
+
an url), so they don't pay attention when committing them. In particular, I have seen
|
|
248
|
+
my fair share of inadvertent "submodule wars" where changes upstream aren't applied
|
|
249
|
+
after a `pull` (ie, people forget to run `git submodule update --init`), then they
|
|
250
|
+
re-commit back the _old version_ of the module that they have locally. So fixes tend
|
|
251
|
+
to become unfixed
|
|
252
|
+
- in addition, `gulp-tasks` requires dependencies to be installed in the hosting repo's
|
|
253
|
+
package.json, meaning that (a) the hosting repo has to "know too much" about the
|
|
254
|
+
requirements of `gulp-tasks` and (b) upstream changes may require changes to a repo's
|
|
255
|
+
package.json (and an `npm install`). Whilst this was (eventually) automated as part
|
|
256
|
+
of `gulp-tasks`, it seems unnecessarily complex.
|
|
257
|
+
- the solution seemed clear: make `gulp-tasks` available via an npm package
|
|
258
|
+
- the name is inspired from the old bugzilla, which would proudly proclaim "zarro boogs"
|
|
259
|
+
when there were zero bug matches for a query, because (a) names are hard and (b)
|
|
260
|
+
zarro aims to be zero- to low-conf
|
package/gulp-tasks/build.js
CHANGED
|
@@ -33,7 +33,8 @@ const myTasks = ["build"],
|
|
|
33
33
|
"BUILD_EXCLUDE",
|
|
34
34
|
"BUILD_ADDITIONAL_EXCLUDE",
|
|
35
35
|
"BUILD_SHOW_INFO",
|
|
36
|
-
"BUILD_FAIL_ON_ERROR"
|
|
36
|
+
"BUILD_FAIL_ON_ERROR",
|
|
37
|
+
"BUILD_RETRIES"
|
|
37
38
|
];
|
|
38
39
|
env.associate(myVars, myTasks);
|
|
39
40
|
|
|
@@ -41,25 +42,46 @@ gulp.task(
|
|
|
41
42
|
"build",
|
|
42
43
|
"Builds Visual Studio solutions in tree",
|
|
43
44
|
["prebuild"],
|
|
44
|
-
|
|
45
|
+
tryBuild
|
|
45
46
|
);
|
|
46
47
|
|
|
47
|
-
gulp.task("quick-build", "Quick build without pre-cursors",
|
|
48
|
+
gulp.task("quick-build", "Quick build without pre-cursors", tryBuild);
|
|
49
|
+
|
|
50
|
+
async function tryBuild() {
|
|
51
|
+
let totalAttempts = env.resolveNumber("BUILD_RETRIES") + 1;
|
|
52
|
+
if (totalAttempts < 0) {
|
|
53
|
+
totalAttempts = 1;
|
|
54
|
+
}
|
|
55
|
+
const totalRetries = totalAttempts - 1;
|
|
56
|
+
|
|
57
|
+
while (totalAttempts-- > 0) {
|
|
58
|
+
try {
|
|
59
|
+
await build();
|
|
60
|
+
} catch (e) {
|
|
61
|
+
if (totalAttempts > 0) {
|
|
62
|
+
console.error(chalk.red(`Build fails: ${e}`));
|
|
63
|
+
console.log(chalk.green(`Retrying (${totalRetries - totalAttempts} / ${totalRetries })`));
|
|
64
|
+
} else {
|
|
65
|
+
throw e;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
48
70
|
|
|
49
71
|
async function build() {
|
|
50
|
-
const slnMasks = resolveMasks("BUILD_INCLUDE", [
|
|
72
|
+
const slnMasks = resolveMasks("BUILD_INCLUDE", ["BUILD_EXCLUDE", "BUILD_ADDITIONAL_EXCLUDE"]);
|
|
51
73
|
debug({
|
|
52
74
|
slnMasks,
|
|
53
75
|
cwd: process.cwd()
|
|
54
76
|
});
|
|
55
77
|
const solutions = gulp
|
|
56
78
|
.src(slnMasks, { allowEmpty: true })
|
|
57
|
-
.pipe(throwIfNoFiles(`No solutions found matching masks: ${slnMasks}}`));
|
|
79
|
+
.pipe(throwIfNoFiles(`No solutions found matching masks: ${ slnMasks }}`));
|
|
58
80
|
|
|
59
81
|
// TODO: find a reliable, quick way to determine if the projects to be compiled
|
|
60
82
|
// are all dotnet core -- trawling *.csproj is slow and has caused hangups
|
|
61
83
|
// here, so for now, DNC build must be requested via env DONET_CORE
|
|
62
|
-
return env.resolveFlag("
|
|
84
|
+
return env.resolveFlag("DOTNET_CORE")
|
|
63
85
|
? buildForNetCore(solutions)
|
|
64
86
|
: buildForNETFramework(solutions);
|
|
65
87
|
}
|
package/gulp-tasks/clean.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
const gulp = requireModule("gulp"),
|
|
2
|
-
msbuild = require("gulp-msbuild"),
|
|
3
|
-
env = requireModule("env");
|
|
4
|
-
|
|
5
|
-
const myVars = [
|
|
6
|
-
"BUILD_TOOLSVERSION",
|
|
7
|
-
"BUILD_CONFIGURATION",
|
|
8
|
-
"BUILD_VERBOSITY",
|
|
9
|
-
"BUILD_MAX_CPU_COUNT",
|
|
10
|
-
"BUILD_FAIL_ON_ERROR",
|
|
11
|
-
"BUILD_PLATFORM",
|
|
12
|
-
"BUILD_ARCHITECTURE",
|
|
13
|
-
"BUILD_MSBUILD_NODE_REUSE"
|
|
14
|
-
];
|
|
15
|
-
env.associate(myVars, "clean");
|
|
16
|
-
|
|
17
|
-
gulp.task(
|
|
18
|
-
"clean",
|
|
19
|
-
"Invokes the 'Clean' target on all solutions in the tree",
|
|
20
|
-
function() {
|
|
21
|
-
return gulp.src("**/*.sln").pipe(
|
|
22
|
-
msbuild({
|
|
23
|
-
toolsVersion: env.resolve("BUILD_TOOLSVERSION"),
|
|
24
|
-
targets: ["Clean"],
|
|
25
|
-
configuration: env.resolve("BUILD_CONFIGURATION"),
|
|
26
|
-
stdout: true,
|
|
27
|
-
logCommand: true,
|
|
28
|
-
errorOnFail: env.resolveFlag("BUILD_FAIL_ON_ERROR"),
|
|
29
|
-
solutionPlatform: env.resolve("BUILD_PLATFORM"),
|
|
30
|
-
architecture: env.resolve("BUILD_ARCHITECTURE"),
|
|
31
|
-
verbosity: env.resolve("BUILD_VERBOSITY"),
|
|
32
|
-
nodeReuse: env.resolveFlag("BUILD_MSBUILD_NODE_REUSE"),
|
|
33
|
-
maxcpucount: env.resolveNumber("BUILD_MAX_CPU_COUNT")
|
|
34
|
-
})
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
);
|
|
1
|
+
const gulp = requireModule("gulp"),
|
|
2
|
+
msbuild = require("gulp-msbuild"),
|
|
3
|
+
env = requireModule("env");
|
|
4
|
+
|
|
5
|
+
const myVars = [
|
|
6
|
+
"BUILD_TOOLSVERSION",
|
|
7
|
+
"BUILD_CONFIGURATION",
|
|
8
|
+
"BUILD_VERBOSITY",
|
|
9
|
+
"BUILD_MAX_CPU_COUNT",
|
|
10
|
+
"BUILD_FAIL_ON_ERROR",
|
|
11
|
+
"BUILD_PLATFORM",
|
|
12
|
+
"BUILD_ARCHITECTURE",
|
|
13
|
+
"BUILD_MSBUILD_NODE_REUSE"
|
|
14
|
+
];
|
|
15
|
+
env.associate(myVars, "clean");
|
|
16
|
+
|
|
17
|
+
gulp.task(
|
|
18
|
+
"clean",
|
|
19
|
+
"Invokes the 'Clean' target on all solutions in the tree",
|
|
20
|
+
function() {
|
|
21
|
+
return gulp.src("**/*.sln").pipe(
|
|
22
|
+
msbuild({
|
|
23
|
+
toolsVersion: env.resolve("BUILD_TOOLSVERSION"),
|
|
24
|
+
targets: ["Clean"],
|
|
25
|
+
configuration: env.resolve("BUILD_CONFIGURATION"),
|
|
26
|
+
stdout: true,
|
|
27
|
+
logCommand: true,
|
|
28
|
+
errorOnFail: env.resolveFlag("BUILD_FAIL_ON_ERROR"),
|
|
29
|
+
solutionPlatform: env.resolve("BUILD_PLATFORM"),
|
|
30
|
+
architecture: env.resolve("BUILD_ARCHITECTURE"),
|
|
31
|
+
verbosity: env.resolve("BUILD_VERBOSITY"),
|
|
32
|
+
nodeReuse: env.resolveFlag("BUILD_MSBUILD_NODE_REUSE"),
|
|
33
|
+
maxcpucount: env.resolveNumber("BUILD_MAX_CPU_COUNT")
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
);
|