Bootstrapping development with some basic types and builds. (#1)
All checks were successful
/ Build and Release Application (push) Successful in 1m20s

Reviewed-on: #1
This commit is contained in:
Pat Garrity 2024-05-19 17:58:57 +00:00
parent dcf62239c6
commit d10dcf4fb3
12 changed files with 450 additions and 1 deletions

View file

@ -0,0 +1,40 @@
on:
pull_request:
types: [opened, synchronize, reopened]
defaults:
run:
shell: bash
jobs:
library_snapshot:
runs-on: docker
container:
image: registry.garrity.co:8443/gs/ci-scala:latest
name: 'Build and Test Application Snapshot'
env:
GS_MAVEN_USER: ${{ vars.GS_MAVEN_USER }}
GS_MAVEN_TOKEN: ${{ secrets.GS_MAVEN_TOKEN }}
steps:
- uses: actions/checkout@v4
name: 'Checkout Repository'
with:
fetch-depth: 0
- name: 'Pre-Commit'
run: |
pre-commit install
pre-commit run --all-files
- name: 'Prepare Versioned Build'
run: |
latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')"
latest_commit_message="$(git show -s --format=%s HEAD)"
echo "Previous Git Tag: $latest_git_tag"
echo "Latest Commit: $latest_commit_message (SNAPSHOT)"
sbtn -Dsnapshot=true "api/calVerInfo"
- name: 'Unit Tests and Code Coverage'
run: |
sbtn clean
sbtn coverage
sbtn test
sbtn coverageReport
sbtn coverageAggregate

View file

@ -0,0 +1,53 @@
on:
push:
branches:
- main
defaults:
run:
shell: bash
jobs:
application_release:
runs-on: docker
container:
image: registry.garrity.co:8443/gs/ci-scala:latest
name: 'Build and Release Application'
env:
GS_MAVEN_USER: ${{ vars.GS_MAVEN_USER }}
GS_MAVEN_TOKEN: ${{ secrets.GS_MAVEN_TOKEN }}
steps:
- uses: actions/checkout@v4
name: 'Checkout Repository'
with:
fetch-depth: 0
- name: 'Pre-Commit'
run: |
pre-commit install
pre-commit run --all-files
- name: 'Prepare Versioned Build'
run: |
latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')"
latest_commit_message="$(git show -s --format=%s HEAD)"
echo "Previous Git Tag: $latest_git_tag"
echo "Latest Commit: $latest_commit_message"
sbtn -Drelease=true api/calVerInfo
- name: 'Unit Tests and Code Coverage'
run: |
sbtn clean
sbtn coverage
sbtn test
sbtn coverageReport
sbtn coverageAggregate
- name: 'Publish Release'
run: |
sbtn coverageOff
sbtn clean
sbtn api/calVerWriteVersionToFile
sbtn compile
- name: 'Create Git Tag'
run: |
selected_version="$(cat .version)"
echo "TAGGING IS CURRENTLY TURNED OFF -- $selected_version"
#git tag "$selected_version"
#git push origin "$selected_version"

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
target/
project/target/
project/project/
.version

16
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,16 @@
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: fix-byte-order-marker
- id: mixed-line-ending
args: ['--fix=lf']
description: Enforces using only 'LF' line endings.
- id: trailing-whitespace
- repo: https://git.garrity.co/garrity-software/gs-pre-commit-scala
rev: v1.0.1
hooks:
- id: scalafmt

72
.scalafmt.conf Normal file
View file

@ -0,0 +1,72 @@
// See: https://github.com/scalameta/scalafmt/tags for the latest tags.
version = 3.8.1
runner.dialect = scala3
maxColumn = 80
rewrite {
rules = [RedundantBraces, RedundantParens, Imports, SortModifiers]
imports.expand = true
imports.sort = scalastyle
redundantBraces.ifElseExpressions = true
redundantBraces.stringInterpolation = true
}
indent {
main = 2
callSite = 2
defnSite = 2
extendSite = 4
withSiteRelativeToExtends = 2
commaSiteRelativeToExtends = 2
}
align {
preset = more
openParenCallSite = false
openParenDefnSite = false
}
newlines {
implicitParamListModifierForce = [before,after]
topLevelStatementBlankLines = [
{
blanks = 1
}
]
afterCurlyLambdaParams = squash
}
danglingParentheses {
defnSite = true
callSite = true
ctrlSite = true
exclude = []
}
verticalMultiline {
atDefnSite = true
arityThreshold = 2
newlineAfterOpenParen = true
}
comments {
wrap = standalone
}
docstrings {
style = "SpaceAsterisk"
oneline = unfold
wrap = yes
forceBlankLineBefore = true
}
project {
excludePaths = [
"glob:**target/**",
"glob:**.metals/**",
"glob:**.bloop/**",
"glob:**.bsp/**",
"glob:**metals.sbt",
"glob:**.git/**"
]
}

View file

@ -8,7 +8,7 @@ Smol Kanban - dead simple tickets.
## Why Smolban?
I created smolban after looking for a free issue tracker that suited my needs.
I tend to prefer feature-light, and didn't want to install something larger
I tend to prefer feature-light, and didn't want to install something larger
or more "agile" focused. I explicitly do not want to use VCS issues. Smolban is
a self-contained issue tracker intended to be easy to deploy and use.

98
build.sbt Normal file
View file

@ -0,0 +1,98 @@
val scala3: String = "3.4.1"
ThisBuild / scalaVersion := scala3
ThisBuild / gsProjectName := "smolban"
ThisBuild / externalResolvers := Seq(
"Garrity Software Mirror" at "https://maven.garrity.co/releases",
"Garrity Software Releases" at "https://maven.garrity.co/gs"
)
lazy val sharedSettings = Seq(
scalaVersion := scala3,
version := calVer.value,
publish / skip := true,
publishLocal / skip := true,
publishArtifact := false
)
val Deps = new {
val Cats = new {
val Core: ModuleID = "org.typelevel" %% "cats-core" % "2.10.0"
val Effect: ModuleID = "org.typelevel" %% "cats-effect" % "3.5.4"
}
val Fs2 = new {
val Core: ModuleID = "co.fs2" %% "fs2-core" % "3.10.2"
}
val Doobie = new {
val Core: ModuleID = "org.tpolecat" %% "doobie-core" % "1.0.0-M5"
}
val Http4s = new {
val Core: ModuleID = "org.http4s" %% "http4s-core" % "1.0.0-M41"
val Dsl: ModuleID = "org.http4s" %% "http4s-dsl" % "1.0.0-M41"
val EmberServer: ModuleID =
"org.http4s" %% "http4s-ember-server" % "1.0.0-M41"
}
val Gs = new {
val Uuid: ModuleID = "gs" %% "gs-uuid-v0" % "0.2.4"
val Slug: ModuleID = "gs" %% "gs-slug-v0" % "0.1.3"
val Config: ModuleID = "gs" %% "gs-config-v0" % "0.1.1"
val Datagen: ModuleID = "gs" %% "gs-datagen-core-v0" % "0.1.1"
}
val MUnit: ModuleID = "org.scalameta" %% "munit" % "1.0.0-RC1"
}
lazy val testSettings = Seq(
libraryDependencies ++= Seq(
Deps.MUnit % Test,
Deps.Gs.Datagen % Test
)
)
lazy val smolban = project
.in(file("."))
.aggregate(model, db, api)
.settings(sharedSettings)
.settings(name := s"${gsProjectName.value}")
lazy val model = project
.in(file("modules/model"))
.settings(sharedSettings)
.settings(testSettings)
.settings(name := s"${gsProjectName.value}-model")
.settings(
libraryDependencies ++= Seq(
Deps.Gs.Uuid,
Deps.Gs.Slug,
Deps.Cats.Core
)
)
lazy val db = project
.in(file("modules/db"))
.settings(sharedSettings)
.settings(testSettings)
.settings(name := s"${gsProjectName.value}-db")
.settings(
libraryDependencies ++= Seq(
Deps.Doobie.Core
)
)
lazy val api = project
.in(file("modules/api"))
.settings(sharedSettings)
.settings(testSettings)
.settings(name := s"${gsProjectName.value}-api")
.settings(
libraryDependencies ++= Seq(
Deps.Http4s.Core,
Deps.Http4s.Dsl,
Deps.Http4s.EmberServer
)
)

View file

@ -0,0 +1,34 @@
package gs.smolban.model
import cats.Show
import java.time.Instant
/** Describes an instant at which something was created. Opaque type for
* `java.time.Instant`.
*/
opaque type CreatedAt = Instant
object CreatedAt:
/** Instantiate a new [[CreatedAt]].
*
* @param timestamp
* The underlying timestamp.
* @return
* The new instance.
*/
def apply(timestamp: Instant): CreatedAt = timestamp
given CanEqual[CreatedAt, CreatedAt] = CanEqual.derived
given Show[CreatedAt] = _.toInstant().toString()
extension (createdAt: CreatedAt)
/** Unwrap this value.
*
* @return
* The underlying `Instant` value.
*/
def toInstant(): Instant = createdAt
end CreatedAt

View file

@ -0,0 +1,54 @@
package gs.smolban.model
import cats.Show
import gs.slug.v0.Slug
import gs.uuid.v0.UUID
/** Groups are the basic unit of organization in Smolban. Each [[Ticket]]
* belongs to a single `Group`.
*
* @param id
* The unique identifier for the group.
* @param slug
* The unique slug for the group.
* @param createdAt
* The instant at which this group was created.
*/
case class Group(
id: Group.Id,
slug: Slug,
createdAt: CreatedAt
)
object Group:
/** Unique identifier for a [[Group]]. This is an opaque type for a UUID.
*/
opaque type Id = UUID
object Id:
/** Instantiate a new [[Group.Id]].
*
* @param id
* The underlying UUID.
* @return
* The new [[Group.Id]] instance.
*/
def apply(id: UUID): Id = id
given CanEqual[Id, Id] = CanEqual.derived
given Show[Id] = _.toUUID().withoutDashes()
extension (id: Id)
/** Unwrap this Group ID.
*
* @return
* The underlying UUID value.
*/
def toUUID(): UUID = id
end Id
end Group

View file

@ -0,0 +1,44 @@
package gs.smolban.model
import cats.Show
case class Ticket(
id: Long,
group: Group.Id,
createdAt: CreatedAt
)
object Ticket:
/** Unique identifier - relative to some [[Group]] - for a [[Ticket]]. This is
* an opaque type for a Long. In general, [[Ticket]] identifiers are
* sequences within a group.
*/
opaque type Id = Long
object Id:
/** Instantiate a new [[Ticket.Id]].
*
* @param id
* The underlying Long.
* @return
* The new [[Ticket.Id]] instance.
*/
def apply(id: Long): Id = id
given CanEqual[Id, Id] = CanEqual.derived
given Show[Id] = _.toLong().toString()
extension (id: Id)
/** Unwrap this Ticket ID.
*
* @return
* The underlying Long value.
*/
def toLong(): Long = id
end Id
end Ticket

1
project/build.properties Normal file
View file

@ -0,0 +1 @@
sbt.version=1.10.0

33
project/plugins.sbt Normal file
View file

@ -0,0 +1,33 @@
def selectCredentials(): Credentials =
if ((Path.userHome / ".sbt" / ".credentials").exists())
Credentials(Path.userHome / ".sbt" / ".credentials")
else
Credentials.apply(
realm = "Reposilite",
host = "maven.garrity.co",
userName = sys.env
.get("GS_MAVEN_USER")
.getOrElse(
throw new RuntimeException(
"You must either provide ~/.sbt/.credentials or specify the GS_MAVEN_USER environment variable."
)
),
passwd = sys.env
.get("GS_MAVEN_TOKEN")
.getOrElse(
throw new RuntimeException(
"You must either provide ~/.sbt/.credentials or specify the GS_MAVEN_TOKEN environment variable."
)
)
)
credentials += selectCredentials()
externalResolvers := Seq(
"Garrity Software Mirror" at "https://maven.garrity.co/releases",
"Garrity Software Releases" at "https://maven.garrity.co/gs"
)
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.8")
addSbtPlugin("gs" % "sbt-garrity-software" % "0.2.0")
addSbtPlugin("gs" % "sbt-gs-calver" % "0.2.0")