Skip to content

Commit

Permalink
Replayed CTP changes on top
Browse files Browse the repository at this point in the history
  • Loading branch information
kjc1 committed Aug 12, 2022
1 parent 27be427 commit 300e699
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 87 deletions.
1 change: 1 addition & 0 deletions .github/pr-labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
automerge: ['update/*']
37 changes: 37 additions & 0 deletions .github/workflows/label_and_automerge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: label_and_automerge
on:
pull_request:
types:
- labeled
- unlabeled
- synchronize
- opened
- edited
- ready_for_review
- reopened
- unlocked
pull_request_review:
types:
- submitted
check_suite:
types:
- completed
status: {}
jobs:

automerge:
runs-on: ubuntu-latest
steps:
- id: automerge
name: automerge
uses: "pascalgn/[email protected]"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
pr-labeler:
runs-on: ubuntu-latest
steps:
- uses: TimonVS/pr-labeler-action@v3
with:
configuration-path: .github/pr-labeler.yml # optional, .github/pr-labeler.yml is the default value
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 changes: 26 additions & 0 deletions .github/workflows/scala.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Scala CI

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up JDK 8
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'temurin'
cache: 'sbt'
- name: Run tests
run: sbt test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
target/
.idea/
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ Scala wrapper around [the Google Sheets API](https://developers.google.com/sheet

gsheets4s is available for Scala 2.12 on Maven central at the following coordinates:

```bash
"com.github.benfradet" %% "gsheets4s" % "0.2.0"
```
`"com.itv" %% "ctp-gsheets4s" % "0.14.0"`

## Credentials management

Expand Down
33 changes: 15 additions & 18 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
inThisBuild(List(
organization := "com.github.benfradet",
homepage := Some(url("https://github.com/BenFradet/gsheets4s")),
licenses := List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")),
developers := List(
Developer(
"BenFradet",
"Ben Fradet",
"[email protected]",
url("https://benfradet.github.io")
)
)
))
name := "ctp-gsheets4s"
organization := "com.itv"

lazy val compilerOptions = Seq(
"-deprecation",
Expand All @@ -19,12 +8,9 @@ lazy val compilerOptions = Seq(
"-language:existentials",
"-language:higherKinds",
"-unchecked",
"-Yno-adapted-args",
"-Ywarn-dead-code",
"-Ywarn-numeric-widen",
"-Ywarn-unused-import",
"-Xfuture",
"-Ypartial-unification"
"-Xfuture"
)

lazy val baseSettings = Seq(
Expand Down Expand Up @@ -55,8 +41,9 @@ lazy val gsheets4s = project.in(file("."))
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-core" % catsVersion,
"org.typelevel" %% "cats-effect" % catsEffectVersion,
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.5",
"eu.timepit" %% "refined" % refinedVersion,
"io.lemonlabs" %% "scala-uri" % scalaUriVersion,
"io.lemonlabs" %% "scala-uri" % scalaUriVersion
) ++ Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
Expand All @@ -74,3 +61,13 @@ lazy val gsheets4s = project.in(file("."))
"eu.timepit" %% "refined-scalacheck" % refinedVersion
).map(_ % "test")
)

gitVersioningSnapshotLowerBound in ThisBuild := "0.4.0"

resolvers += "Artifactory Realm" at "https://itvrepos.jfrog.io/itvrepos/fp-scala-libs/"

credentials += Credentials(Path.userHome / ".ivy2" / "fp-scala-libs.credentials")

publishArtifact := true
publishArtifact in Test := false
publishTo := Some("Artifactory Realm" at "https://itvrepos.jfrog.io/itvrepos/fp-scala-libs/")
7 changes: 4 additions & 3 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1")
addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.9")
addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.20")
resolvers += Resolver.bintrayIvyRepo("rallyhealth", "sbt-plugins")
addSbtPlugin("com.rallyhealth.sbt" % "sbt-git-versioning" % "1.6.0")

addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3")
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package gsheets4s
package interpreters

import cats.syntax.show._
import io.circe.generic.auto._
import io.lemonlabs.uri.typesafe.dsl._

import algebras.SpreadsheetsValues
import http._
import model._

class RestSpreadsheetsValues[F[_]](client: HttpClient[F]) extends SpreadsheetsValues[F] {
def get(spreadsheetID: String, range: A1Notation): F[Either[GsheetsError, ValueRange]] =
client.get(spreadsheetID / "values" / range)
client.get(io.lemonlabs.uri.Url.parse(s"$spreadsheetID/values/${range.show}"))

def update(
spreadsheetID: String,
range: A1Notation,
updates: ValueRange,
valueInputOption: ValueInputOption
): F[Either[GsheetsError, UpdateValuesResponse]] =
client.put(spreadsheetID / "values" / range, updates,
client.put(io.lemonlabs.uri.Url.parse(s"$spreadsheetID/values/${range.show}"), updates,
List(("valueInputOption", valueInputOption.value)))
}
60 changes: 16 additions & 44 deletions src/main/scala/gsheets4s/model.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ import cats.Show
import cats.syntax.apply._
import cats.syntax.either._
import cats.syntax.show._
import com.typesafe.scalalogging.StrictLogging
import eu.timepit.refined.api.Refined
import eu.timepit.refined.boolean._
import eu.timepit.refined.char._
import eu.timepit.refined.collection._
import eu.timepit.refined.numeric._
import gsheets4s.model.A1Notation
import io.circe.{Decoder, DecodingFailure, Encoder, HCursor}
import io.circe.generic.semiauto._
import io.lemonlabs.uri.typesafe._

object model extends A1NotationLiteralSyntax {
object model extends StrictLogging{
type ValidCol = NonEmpty And Forall[UpperCase]
type Col = String Refined ValidCol
type ValidRow = Positive
Expand Down Expand Up @@ -51,7 +50,6 @@ object model extends A1NotationLiteralSyntax {

sealed trait A1Notation
object A1Notation {
implicit val pathPartA1Notation: PathPart[A1Notation] = _.show
implicit val showA1Notation: Show[A1Notation] = Show.show {
case SheetNameNotation(s) => s.toString
case RangeNotation(r) => r.show
Expand All @@ -62,35 +60,6 @@ object model extends A1NotationLiteralSyntax {
.mapN(SheetNameRangeNotation.apply) |
Range.parser.map(RangeNotation(_): A1Notation) |
stringOf1(elem(_ => true)).map(SheetNameNotation(_): A1Notation)

/** Thanks to ip4s for the singlePartInterpolator implementation
* https://github.com/Comcast/ip4s/blob/b4f01a4637f2766a8e12668492a3814c478c6a03/shared/src/main/scala/com/comcast/ip4s/LiteralSyntaxMacros.scala
*/
object LiteralSyntaxMacros {
import scala.reflect.macros.blackbox

def a1NotationInterpolator(c: blackbox.Context)(args: c.Expr[Any]*): c.Expr[A1Notation] =
singlePartInterpolator(c)(
args,
"A1Notation",
A1Notation.parser.parseOnly(_).either,
s => c.universe.reify(A1Notation.parser.parseOnly(s.splice).option.get))

private def singlePartInterpolator[A](c: blackbox.Context)(
args: Seq[c.Expr[Any]],
typeName: String,
validate: String => Either[String, _],
construct: c.Expr[String] => c.Expr[A]): c.Expr[A] = {
import c.universe._
identity(args)
c.prefix.tree match {
case Apply(_, List(Apply(_, (lcp@Literal(Constant(p: String))) :: Nil))) =>
val valid = validate(p)
if (valid.isRight) construct(c.Expr(lcp))
else c.abort(c.enclosingPosition, s"invalid $typeName: ${valid.left.get}")
}
}
}
}
final case class SheetNameNotation(sheetName: String) extends A1Notation
final case class RangeNotation(range: Range) extends A1Notation
Expand Down Expand Up @@ -121,7 +90,7 @@ object model extends A1NotationLiteralSyntax {
final case class ValueRange(
range: A1Notation,
majorDimension: Dimension,
values: List[List[String]]
values: List[List[String]] // Todo this value should be optional incase the sheet is empty
)

final case class UpdateValuesResponse(
Expand All @@ -137,8 +106,20 @@ object model extends A1NotationLiteralSyntax {
message: String,
status: String
)

val fallbackdecoder: Decoder[GsheetsError] =
new Decoder[GsheetsError] {
final def apply(c: HCursor): Decoder.Result[GsheetsError] = {
val msg = s"gsheets4s errorDecoder raw json ${c.focus.map(_.noSpaces)}. Have you added a row to the sheet? If not please add one ;)"
logger.error(msg)
GsheetsError(400, msg, "").asRight[DecodingFailure]
}
}

implicit val errorDecoder: Decoder[GsheetsError] =
deriveDecoder[GsheetsError].prepare(_.downField("error"))
deriveDecoder[GsheetsError].prepare{ j =>
j.downField("error")
}.handleErrorWith(_ => fallbackdecoder)

final case class Credentials(
accessToken: String,
Expand All @@ -150,12 +131,3 @@ object model extends A1NotationLiteralSyntax {
implicit def eitherDecoder[L, R](implicit l: Decoder[L], r: Decoder[R]): Decoder[Either[L, R]] =
r.map(Right(_): Either[L, R]).or(l.map(Left(_): Either[L, R]))
}

trait A1NotationLiteralSyntax {
implicit def toA1NotationLiteralOps(sc: StringContext): A1NotationLiteralOps =
new A1NotationLiteralOps(sc)
}

final class A1NotationLiteralOps(val sc: StringContext) extends AnyVal {
def a1(args: Any*): A1Notation = macro A1Notation.LiteralSyntaxMacros.a1NotationInterpolator
}
16 changes: 0 additions & 16 deletions src/test/scala/gsheets4s/A1NotationLiteralsSpec.scala

This file was deleted.

12 changes: 12 additions & 0 deletions src/test/scala/gsheets4s/ModelSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,16 @@ object ModelSpec extends Properties("model") {
case Right(r) => decode[Either[GsheetsError, ValueRange]](r.asJson.noSpaces) == Right(e)
}
}

property("Either decoder fallback") = forAll { e: Either[GsheetsError, ValueRange] =>
e match {
case Left(l) =>
val js = Json.obj(("error-V2", l.asJson)).noSpaces
val x = decode[Either[GsheetsError, ValueRange]](js)
val y = Right(Left(GsheetsError(400, s"gsheets4s errorDecoder raw json Some($js). Have you added a row to the sheet? If not please add one ;)", "")))
x == y
case Right(r) =>
decode[Either[GsheetsError, ValueRange]](r.asJson.noSpaces) == Right(e)
}
} //${c.focus.map(_.noSpaces)}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package interpreters

import cats.Id
import cats.syntax.foldable._
import cats.instances.int._
import cats.instances.option._

import algebras._
import model._
Expand Down

0 comments on commit 300e699

Please sign in to comment.