forked from http4s/http4s
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Http4sPlugin.scala
306 lines (280 loc) · 15.9 KB
/
Http4sPlugin.scala
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
package org.http4s.build
import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin
import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin.autoImport._
import com.typesafe.sbt.SbtGit.git
import com.typesafe.sbt.SbtPgp.autoImport._
import com.typesafe.sbt.git.JGit
import com.typesafe.sbt.pgp.PgpKeys.publishSigned
import com.typesafe.tools.mima.plugin.MimaPlugin
import com.typesafe.tools.mima.plugin.MimaPlugin.autoImport._
import sbt.Keys._
import sbt._
import sbtrelease.ReleasePlugin.autoImport._
import sbtrelease.ReleaseStateTransformations._
import sbtrelease._
import scoverage.ScoverageKeys.{coverageEnabled, coverageHighlighting}
import verizon.build.RigPlugin
import verizon.build.RigPlugin.autoImport._
import verizon.build.common._
object Http4sPlugin extends AutoPlugin {
object autoImport {
val http4sMimaVersion = settingKey[Option[String]]("Version to target for MiMa compatibility")
val http4sPrimary = settingKey[Boolean]("Is this the primary build?")
val http4sPublish = settingKey[Boolean]("Is this a publishing build?")
val http4sMasterBranch = settingKey[Boolean]("Is this the master branch?")
val http4sApiVersion = taskKey[(Int, Int)]("API version of http4s")
val http4sJvmTarget = taskKey[String]("JVM target")
val http4sBuildData = taskKey[Unit]("Export build metadata for Hugo")
}
import autoImport._
override def trigger = allRequirements
override def requires = RigPlugin && MimaPlugin && ScalafmtCorePlugin
override lazy val buildSettings = Seq(
// Many steps only run on one build. We distinguish the primary build from
// secondary builds by the Travis build number.
http4sPrimary := sys.env.get("TRAVIS_JOB_NUMBER").fold(true)(_.endsWith(".1")),
// Publishing to gh-pages and sonatype only done from select branches and
// never from pull requests.
http4sPublish := {
sys.env.get("TRAVIS") == Some("true") &&
sys.env.get("TRAVIS_PULL_REQUEST") == Some("false") &&
sys.env.get("TRAVIS_REPO_SLUG") == Some("http4s/http4s") &&
sys.env.get("TRAVIS_JDK_VERSION") == Some("oraclejdk8") &&
(sys.env.get("TRAVIS_BRANCH") match {
case Some("master") => true
case Some(branch) if branch.startsWith("release-") => true
case _ => false
})
},
http4sMasterBranch := sys.env.get("TRAVIS_BRANCH") == Some("master"),
http4sApiVersion in ThisBuild := (version in ThisBuild).map {
case VersionNumber(Seq(major, minor, _*), _, _) => (major.toInt, minor.toInt)
}.value,
coverageEnabled := isTravisBuild.value && http4sPrimary.value,
coverageHighlighting := true,
git.remoteRepo := "git@github.com:http4s/http4s.git"
) ++ signingSettings
override lazy val projectSettings: Seq[Setting[_]] = Seq(
scalaVersion := (sys.env.get("TRAVIS_SCALA_VERSION") orElse sys.env.get("SCALA_VERSION") getOrElse "2.12.6"),
// Rig will take care of this on production builds. We haven't fully
// implemented that machinery yet, so we're going to live without this
// one for now.
scalacOptions -= "-Xcheckinit",
// https://github.com/tkawachi/sbt-doctest/issues/102
scalacOptions in (Test, compile) -= "-Ywarn-unused:params",
http4sMimaVersion := {
version.value match {
case VersionNumber(Seq(major, minor, patch), _, _) if patch.toInt > 0 =>
Some(s"${major}.${minor}.${patch.toInt - 1}")
case _ =>
None
}
},
mimaFailOnProblem := http4sMimaVersion.value.isDefined,
mimaPreviousArtifacts := (http4sMimaVersion.value map {
organization.value % s"${moduleName.value}_${scalaBinaryVersion.value}" % _
}).toSet,
addCompilerPlugin("org.spire-math" % "kind-projector" % "0.9.6" cross CrossVersion.binary),
scalafmtVersion := "1.4.0",
scalafmt in Test := {
(scalafmt in Compile).value
(scalafmt in Test).value
()
},
test in (Test, scalafmt) := {
(test in (Compile, scalafmt)).value
(test in (Test, scalafmt)).value
()
},
http4sBuildData := {
val dest = target.value / "hugo-data" / "build.toml"
val (major, minor) = http4sApiVersion.value
val releases = latestPerMinorVersion(baseDirectory.value)
.map { case ((major, minor), v) => s""""$major.$minor" = "${v.string}""""}
.mkString("\n")
// Would be more elegant if `[versions.http4s]` was nested, but then
// the index lookups in `shortcodes/version.html` get complicated.
val buildData: String =
s"""
|[versions]
|"http4s.api" = "$major.$minor"
|"http4s.current" = "${version.value}"
|"http4s.doc" = "${docExampleVersion(version.value)}"
|circe = "${circeJawn.revision}"
|cryptobits = "${cryptobits.revision}"
|"argonaut-shapeless_6.2" = "1.2.0-M6"
|
|[releases]
|${releases}
""".stripMargin
IO.write(dest, buildData)
}
) ++ releaseSettings
val releaseSettings = Seq(
// Reset a couple sbt-release defaults that rig changed
releaseVersion := { ver =>
Version(ver).map(v =>
v.copy(qualifier = v.qualifier.map(_.replaceAllLiterally("-SNAPSHOT", "")))
.string
).getOrElse(versionFormatError)
},
releaseTagName := s"v${if (releaseUseGlobalVersion.value) (version in ThisBuild).value else version.value}",
releasePublishArtifactsAction := Def.taskDyn {
if (isSnapshot.value) publish
else publishSigned
}.value,
releaseProcess := {
implicit class StepSyntax(val step: ReleaseStep) {
def when(cond: Boolean) =
if (cond) step else ReleaseStep(identity)
}
implicit class StateFCommand(val step: State => State) {
def when(cond: Boolean) =
StepSyntax(step).when(cond)
}
val release = !isSnapshot.value
val publishable = http4sPublish.value
val primary = http4sPrimary.value
val master = http4sMasterBranch.value
Seq(
checkSnapshotDependencies.when(release),
inquireVersions.when(release),
setReleaseVersion.when(release),
tagRelease.when(primary && release),
runTestWithCoverage,
releaseStepCommand("mimaReportBinaryIssues"),
releaseStepCommand("test:scalafmt::test").when(primary),
releaseStepCommand("docs/makeSite").when(primary),
releaseStepCommand("website/makeSite").when(primary),
openSonatypeRepo.when(publishable && release),
publishToSonatypeWithoutInstrumentation.when(publishable),
releaseAndClose.when(publishable && release),
releaseStepCommand("docs/ghpagesPushSite").when(publishable && primary),
releaseStepCommand("website/ghpagesPushSite").when(publishable && primary && master),
setNextVersion.when(publishable && primary && release),
commitNextVersion.when(publishable && primary && release),
pushChanges.when(publishable && primary && release),
// We need a superfluous final step to ensure exit code
// propagation from failed steps above.
//
// https://github.com/sbt/sbt-release/issues/95
releaseStepCommand("show core/version")
)
}
)
val signingSettings = Seq(
useGpg := false,
usePgpKeyHex("42FAD8A85B13261D"),
pgpPublicRing := baseDirectory.value / "project" / ".gnupg" / "pubring.gpg",
pgpSecretRing := baseDirectory.value / "project" / ".gnupg" / "secring.gpg",
pgpPassphrase := sys.env.get("PGP_PASS").map(_.toArray),
)
def extractApiVersion(version: String) = {
val VersionExtractor = """(\d+)\.(\d+)\..*""".r
version match {
case VersionExtractor(major, minor) => (major.toInt, minor.toInt)
}
}
def extractDocsPrefix(version: String) =
extractApiVersion(version).productIterator.mkString("/v", ".", "")
/**
* @return the version we want to document, for example in tuts,
* given the version being built.
*
* For snapshots after a stable release, return the previous stable
* release. For snapshots of 0.16.0 and 0.17.0, return the latest
* milestone. Otherwise, just return the current version. Favors
* scalaz-7.2 "a" versions for 0.15.x and 0.16.x.
*/
def docExampleVersion(currentVersion: String) = {
val MilestoneVersionExtractor = """(0).(16|17).(0)a?-SNAPSHOT""".r
val latestMilestone = "M1"
val VersionExtractor = """(\d+)\.(\d+)\.(\d+).*""".r
currentVersion match {
case MilestoneVersionExtractor(major, minor, patch) if minor.toInt == 16 =>
s"${major.toInt}.${minor.toInt}.${patch.toInt}a-$latestMilestone" // scalaz-7.2 for 0.16.x
case MilestoneVersionExtractor(major, minor, patch) =>
s"${major.toInt}.${minor.toInt}.${patch.toInt}-$latestMilestone"
case VersionExtractor(major, minor, patch) if minor.toInt == 15 =>
s"${major.toInt}.${minor.toInt}.${patch.toInt - 1}a" // scalaz-7.2 for 0.15.x
case VersionExtractor(major, minor, patch) if patch.toInt > 0 =>
s"${major.toInt}.${minor.toInt}.${patch.toInt - 1}"
case _ =>
currentVersion
}
}
val macroParadiseSetting =
libraryDependencies += compilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)
def latestPerMinorVersion(file: File): Map[(Int, Int), Version] =
JGit(file).tags.collect {
case ref if ref.getName.startsWith("refs/tags/v") =>
Version(ref.getName.substring("refs/tags/v".size))
}.foldLeft(Map.empty[(Int, Int), Version]) {
case (m, Some(v)) =>
def toMinor(v: Version) = (v.major, v.subversions.headOption.getOrElse(0))
def patch(v: Version) = v.subversions.drop(1).headOption.getOrElse(0)
// M before RC before final
def milestone(v: Version) = v.qualifier match {
case Some(q) if q.startsWith("-M") => (0, q.substring(2).toInt)
case Some(q) if q.startsWith("-RC") => (1, q.substring(3).toInt)
case None => (2, 0)
}
val versionOrdering: Ordering[Version] =
Ordering[(Int, (Int, Int))].on(v => (patch(v), milestone(v)))
val key = toMinor(v)
val max = m.get(key).fold(v) { v0 => versionOrdering.max(v, v0) }
m.updated(key, max)
case (m, None) => m
}
lazy val alpnBoot = "org.mortbay.jetty.alpn" % "alpn-boot" % "8.1.12.v20180117"
lazy val argonaut = "io.argonaut" %% "argonaut" % "6.2.1"
lazy val asyncHttpClient = "org.asynchttpclient" % "async-http-client" % "2.0.39"
lazy val blaze = "org.http4s" %% "blaze-http" % "0.12.13"
lazy val cats = "org.typelevel" %% "cats-core" % "1.1.0"
lazy val catsEffect = "org.typelevel" %% "cats-effect" % "0.10.1"
lazy val catsEffectLaws = "org.typelevel" %% "cats-effect-laws" % catsEffect.revision
lazy val catsKernelLaws = "org.typelevel" %% "cats-kernel-laws" % cats.revision
lazy val catsLaws = "org.typelevel" %% "cats-laws" % cats.revision
lazy val circeGeneric = "io.circe" %% "circe-generic" % circeJawn.revision
lazy val circeJawn = "io.circe" %% "circe-jawn" % "0.9.3"
lazy val circeLiteral = "io.circe" %% "circe-literal" % circeJawn.revision
lazy val circeParser = "io.circe" %% "circe-parser" % circeJawn.revision
lazy val circeTesting = "io.circe" %% "circe-testing" % circeJawn.revision
lazy val cryptobits = "org.reactormonk" %% "cryptobits" % "1.1"
lazy val discipline = "org.typelevel" %% "discipline" % "0.9.0"
lazy val fs2Io = "co.fs2" %% "fs2-io" % "0.10.4"
lazy val fs2ReactiveStreams = "com.github.zainab-ali" %% "fs2-reactive-streams" % "0.5.1"
lazy val fs2Scodec = "co.fs2" %% "fs2-scodec" % fs2Io.revision
lazy val gatlingTest = "io.gatling" % "gatling-test-framework" % "2.3.1"
lazy val gatlingHighCharts = "io.gatling.highcharts" % "gatling-charts-highcharts" % gatlingTest.revision
lazy val http4sWebsocket = "org.http4s" %% "http4s-websocket" % "0.2.1"
lazy val javaxServletApi = "javax.servlet" % "javax.servlet-api" % "3.1.0"
lazy val jawnJson4s = "org.spire-math" %% "jawn-json4s" % "0.11.1"
lazy val jawnFs2 = "org.http4s" %% "jawn-fs2" % "0.12.2"
lazy val jettyServer = "org.eclipse.jetty" % "jetty-server" % "9.4.9.v20180320"
lazy val jettyServlet = "org.eclipse.jetty" % "jetty-servlet" % jettyServer.revision
lazy val json4sCore = "org.json4s" %% "json4s-core" % "3.5.3"
lazy val json4sJackson = "org.json4s" %% "json4s-jackson" % json4sCore.revision
lazy val json4sNative = "org.json4s" %% "json4s-native" % json4sCore.revision
lazy val jspApi = "javax.servlet.jsp" % "javax.servlet.jsp-api" % "2.3.1" // YourKit hack
lazy val log4s = "org.log4s" %% "log4s" % "1.6.1"
lazy val logbackClassic = "ch.qos.logback" % "logback-classic" % "1.2.3"
lazy val macroCompat = "org.typelevel" %% "macro-compat" % "1.1.1"
lazy val metricsCore = "io.dropwizard.metrics" % "metrics-core" % "4.0.2"
lazy val metricsJson = "io.dropwizard.metrics" % "metrics-json" % metricsCore.revision
lazy val prometheusClient = "io.prometheus" % "simpleclient_common" % "0.3.0"
lazy val prometheusHotspot = "io.prometheus" % "simpleclient_hotspot" % prometheusClient.revision
lazy val parboiled = "org.http4s" %% "parboiled" % "1.0.0"
lazy val quasiquotes = "org.scalamacros" %% "quasiquotes" % "2.1.0"
lazy val scalacheck = "org.scalacheck" %% "scalacheck" % "1.13.5"
def scalaCompiler(so: String, sv: String) = so % "scala-compiler" % sv
def scalaReflect(so: String, sv: String) = so % "scala-reflect" % sv
lazy val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "1.0.6"
lazy val scodecBits = "org.scodec" %% "scodec-bits" % "1.1.5"
lazy val specs2Core = "org.specs2" %% "specs2-core" % "4.1.0"
lazy val specs2MatcherExtra = "org.specs2" %% "specs2-matcher-extra" % specs2Core.revision
lazy val specs2Scalacheck = "org.specs2" %% "specs2-scalacheck" % specs2Core.revision
lazy val tomcatCatalina = "org.apache.tomcat" % "tomcat-catalina" % "9.0.7"
lazy val tomcatCoyote = "org.apache.tomcat" % "tomcat-coyote" % tomcatCatalina.revision
lazy val twirlApi = "com.typesafe.play" %% "twirl-api" % "1.3.15"
}