-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbuild.fsx
324 lines (259 loc) · 9.19 KB
/
build.fsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#r "nuget: Fun.Build, 0.3.8"
#r "nuget: Fake.IO.FileSystem, 5.23.1"
#r "nuget: Fake.Core.Environment, 5.23.1"
#r "nuget: Fake.Tools.Git, 5.23.1"
#r "nuget: Fake.Api.GitHub, 5.23.1"
#r "nuget: SimpleExec, 11.0.0"
#r "nuget: BlackFox.CommandLine, 1.0.0"
#r "nuget: FsToolkit.ErrorHandling, 4.6.0"
open Fun.Build
open Fake.IO
open Fake.IO.FileSystemOperators
open Fake.IO.Globbing.Operators
open Fake.Api
open Fake.Tools
let gitOwner = "thoth-org"
let repoName = "Thoth.Elmish.Debouncer"
module Glob =
open Fake.IO.FileSystemOperators
let fableJs baseDir = baseDir </> "**/*.fs.js"
let fableJsMap baseDir = baseDir </> "**/*.fs.js.map"
let js baseDir = baseDir </> "**/*.js"
let jsMap baseDir = baseDir </> "**/*.js.map"
// Module to print colored message in the console
module Logger =
open System
let consoleColor (fc : ConsoleColor) =
let current = Console.ForegroundColor
Console.ForegroundColor <- fc
{ new IDisposable with
member x.Dispose() = Console.ForegroundColor <- current }
let warn str = Printf.kprintf (fun s -> use c = consoleColor ConsoleColor.DarkYellow in printf "%s" s) str
let warnfn str = Printf.kprintf (fun s -> use c = consoleColor ConsoleColor.DarkYellow in printfn "%s" s) str
let error str = Printf.kprintf (fun s -> use c = consoleColor ConsoleColor.Red in printf "%s" s) str
let errorfn str = Printf.kprintf (fun s -> use c = consoleColor ConsoleColor.Red in printfn "%s" s) str
module Changelog =
open System.Text.RegularExpressions
open System.IO
let versionRegex = Regex("^## ?\\[?v?([\\w\\d.-]+\\.[\\w\\d.-]+[a-zA-Z0-9])\\]?", RegexOptions.IgnoreCase)
let getLastVersion () =
File.ReadLines("CHANGELOG.md")
|> Seq.tryPick (fun line ->
let m = versionRegex.Match(line)
if m.Success then Some m else None)
|> function
| None -> failwith "Couldn't find version in changelog file"
| Some m ->
m.Groups.[1].Value
let isPreRelease (version : string) =
let regex = Regex(".*(alpha|beta|rc).*", RegexOptions.IgnoreCase)
regex.IsMatch(version)
let getNotes (version : string) =
File.ReadLines("CHANGELOG.md")
|> Seq.skipWhile(fun line ->
let m = versionRegex.Match(line)
if m.Success then
not (m.Groups.[1].Value = version)
else
true
)
// Remove the version line
|> Seq.skip 1
// Take all until the next version line
|> Seq.takeWhile (fun line ->
let m = versionRegex.Match(line)
not m.Success
)
module Util =
open System.IO
open System.Text.RegularExpressions
let visitFile (visitor: string -> string) (fileName : string) =
File.ReadAllLines(fileName)
|> Array.map (visitor)
|> fun lines -> File.WriteAllLines(fileName, lines)
let replaceLines (replacer: string -> Match -> string option) (reg: Regex) (fileName: string) =
fileName |> visitFile (fun line ->
let m = reg.Match(line)
if not m.Success
then line
else
match replacer line m with
| None -> line
| Some newLine -> newLine)
module Nuget =
open System.Text.RegularExpressions
open System.IO
open BlackFox.CommandLine
open FsToolkit.ErrorHandling
let private needsPublishing (versionRegex: Regex) (newVersion: string) projFile =
printfn "Project: %s" projFile
if newVersion.ToUpper().EndsWith("NEXT")
|| newVersion.ToUpper().EndsWith("UNRELEASED")
then
Logger.warnfn "Version marked as unreleased version in Changelog, don't publish yet."
false
else
File.ReadLines(projFile)
|> Seq.tryPick (fun line ->
let m = versionRegex.Match(line)
if m.Success then Some m else None)
|> function
| None -> failwith "Couldn't find version in project file"
| Some m ->
let sameVersion = m.Groups.[1].Value = newVersion
if sameVersion then
Logger.warnfn "Already version %s, no need to publish." newVersion
not sameVersion
let push (newVersion : string) (projFile: string) (ctx: Internal.StageContext)=
asyncResult {
let versionRegex = Regex("<Version>(.*?)</Version>", RegexOptions.IgnoreCase)
if needsPublishing versionRegex newVersion projFile then
let projDir = Path.GetDirectoryName(projFile)
(versionRegex, projFile) ||> Util.replaceLines (fun line _ ->
versionRegex.Replace(line, "<Version>" + newVersion + "</Version>") |> Some)
do! CmdLine.empty
|> CmdLine.appendRaw "dotnet"
|> CmdLine.appendRaw "pack"
|> CmdLine.appendRaw projFile
|> CmdLine.appendPrefix "-c" "Release"
|> CmdLine.toString
|> ctx.RunCommand
let file =
Directory.GetFiles(projDir </> "bin" </> "Release", "*.nupkg")
|> Array.find (fun nupkg -> nupkg.Contains(newVersion))
let nugetKey = ctx.GetEnvVar "NUGET_KEY"
let nugetPushCmd =
CmdLine.empty
|> CmdLine.appendRaw "dotnet"
|> CmdLine.appendRaw "nuget"
|> CmdLine.appendRaw "push"
|> CmdLine.appendRaw file
|> CmdLine.appendPrefix "--source" "https://www.nuget.org/api/v2/package"
|> CmdLine.appendPrefix "--api-key" nugetKey
|> CmdLine.toString
do! ctx.RunSensitiveCommand($"{nugetPushCmd}")
}
module Stages =
let clean =
stage "Clean" {
paralle
run(fun _ ->
[
"src/bin"
"src/obj"
"demo/bin"
"demo/obj"
"demo/dist/"
"docs_deploy"
]
|> Shell.cleanDirs
)
run(fun _ ->
!!(Glob.fableJs "src")
++ (Glob.fableJsMap "src")
++ (Glob.fableJs "demo/src")
++ (Glob.fableJsMap "demo/src")
|> Seq.iter Shell.rm
)
}
let pnpmInstall =
stage "pnpm - install" {
paralle
run "pnpm install"
run "cd demo && pnpm install"
}
let dotnetRestore =
stage "DotnetRestore" {
paralle
run "dotnet restore src"
run "dotnet restore demo"
}
module Conditions =
let whenWatch =
whenCmd {
name "--watch"
alias "-w"
description "Watch for changes and rebuild"
}
pipeline "Demo" {
Stages.clean
Stages.pnpmInstall
Stages.dotnetRestore
stage "Watch" {
Conditions.whenWatch
workingDir "demo"
paralle
run "npx vite"
run "dotnet fable watch"
}
stage "Build" {
whenNot {
Conditions.whenWatch
}
workingDir "demo"
run "dotnet fable --noCache"
run "npx vite build"
}
runIfOnlySpecified
}
pipeline "Format" {
stage "Format" {
run "dotnet fantomas -r src"
run "dotnet fantomas -r demo"
}
}
pipeline "ReleaseDocs" {
Stages.clean
Stages.pnpmInstall
Stages.dotnetRestore
stage "Build docs site" {
run "npx nacara"
}
stage "Build demo" {
workingDir "demo"
run "dotnet fable --noCache"
run "npx vite build"
}
stage "Copy demo files" {
run(fun _ ->
Shell.mkdir "./docs_deploy/demo"
Shell.cp "./demo/dist/assets/index.js" "./docs_deploy/demo"
)
}
stage "Publish docs" {
run "npx gh-pages -d docs_deploy"
}
runIfOnlySpecified
}
pipeline "ReleasePackage" {
Stages.clean
Stages.pnpmInstall
Stages.dotnetRestore
whenAll {
envVar "NUGET_KEY"
envVar "GITHUB_TOKEN_THOTH_ORG"
}
stage "Publish nuget package" {
run (fun ctx ->
let newVersion = Changelog.getLastVersion()
Nuget.push newVersion "src/Thoth.Elmish.Debouncer.fsproj" ctx
)
}
stage "Github release" {
run (fun ctx ->
let root = __SOURCE_DIRECTORY__
let version = Changelog.getLastVersion()
Git.Staging.stageAll root
let commitMsg = sprintf "Release version %s" version
Git.Commit.exec root commitMsg
Git.Branches.push root
let token = ctx.GetEnvVar "GITHUB_TOKEN_THOTH_ORG"
GitHub.createClientWithToken token
|> GitHub.draftNewRelease gitOwner repoName version (Changelog.isPreRelease version) (Changelog.getNotes version)
|> GitHub.publishDraft
|> Async.RunSynchronously
)
}
runIfOnlySpecified
}
tryPrintPipelineCommandHelp()