Tests, logging, restructuring

This commit is contained in:
Ryan Harg 2024-02-13 09:17:34 +01:00
parent 536ac398c4
commit fdcef5d209
16 changed files with 118 additions and 26 deletions

View file

@ -27,7 +27,7 @@ repositories {
} }
jib { jib {
to.image = "antifa-info-bot" to.image = "github-release-bot"
container.creationTime.set(DateTimeFormatter.ISO_DATE_TIME.format(Instant.now().atZone(ZoneId.of("UTC")))) container.creationTime.set(DateTimeFormatter.ISO_DATE_TIME.format(Instant.now().atZone(ZoneId.of("UTC"))))
val buildDir = layout.buildDirectory.get() val buildDir = layout.buildDirectory.get()

View file

@ -1,5 +1,9 @@
package de.rpr.githubreleases package de.rpr.githubreleases
import de.rpr.githubreleases.feed.FeedService
import de.rpr.githubreleases.publishing.MastodonClientFactory
import de.rpr.githubreleases.publishing.Publishers
import de.rpr.githubreleases.repository.ReleaseRepository
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -27,7 +31,7 @@ class App(
} }
private fun execute() { private fun execute() {
log("Processing feed...")
config.githubRepos.forEach { githubRepo -> config.githubRepos.forEach { githubRepo ->
val existingReleases = releaseRepo.getExistingReleases(githubRepo) val existingReleases = releaseRepo.getExistingReleases(githubRepo)
val feedService = FeedService(githubRepo, httpClient) val feedService = FeedService(githubRepo, httpClient)
@ -35,6 +39,7 @@ class App(
val publisher = publishers.forName(githubRepo.name) val publisher = publishers.forName(githubRepo.name)
val publishedReleases = publisher.sendReleases(newReleases) val publishedReleases = publisher.sendReleases(newReleases)
releaseRepo.save(publishedReleases) releaseRepo.save(publishedReleases)
log("Finished feed processing...")
} }
} }
} }

View file

@ -1,6 +1,7 @@
package de.rpr.githubreleases; package de.rpr.githubreleases;
import de.rpr.githubreleases.LogLevel.ERROR import de.rpr.githubreleases.LogLevel.ERROR
import de.rpr.githubreleases.model.GithubRepo
class Config { class Config {
@ -45,7 +46,7 @@ class Config {
} }
githubRepos = githubReposString.split(",").map { githubRepos = githubReposString.split(",").map {
GithubRepo(repoName(it), it) GithubRepo(it)
} }
mastodonCredentials = githubRepos.associate { mastodonCredentials = githubRepos.associate {
@ -73,9 +74,5 @@ class Config {
} }
} }
private fun repoName(url: String): String {
val usernameEnd = url.indexOf("/", startIndex = 20)
return url.substring(usernameEnd + 1).trimEnd { ch -> ch == '/' }
}
} }

View file

@ -1,6 +0,0 @@
package de.rpr.githubreleases
data class GithubRepo(
val name: String,
val url: String
)

View file

@ -1,4 +1,4 @@
package de.rpr.githubreleases package de.rpr.githubreleases.feed
import com.ouattararomuald.syndication.atom.AtomFeed import com.ouattararomuald.syndication.atom.AtomFeed

View file

@ -1,9 +1,16 @@
package de.rpr.githubreleases package de.rpr.githubreleases.feed
import com.ouattararomuald.syndication.Syndication import com.ouattararomuald.syndication.Syndication
import de.rpr.githubreleases.*
import de.rpr.githubreleases.model.GithubRepo
import de.rpr.githubreleases.model.Release
import de.rpr.githubreleases.model.Releases
import de.rpr.githubreleases.model.asCollection
import de.rpr.terminenbg.LocalDateTimeAdapter import de.rpr.terminenbg.LocalDateTimeAdapter
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.OffsetDateTime
import java.time.ZoneId
class FeedService( class FeedService(
private val githubRepo: GithubRepo, private val githubRepo: GithubRepo,
@ -15,18 +22,19 @@ class FeedService(
) )
fun getNewReleases(existingReleases: Releases): Releases { fun getNewReleases(existingReleases: Releases): Releases {
log("Consuming releases feed for ${githubRepo.url}") log("Consuming releases feed for ${githubRepo.repoPath}")
val feedReader = syndication.create(FeedReader::class.java) val feedReader = syndication.create(FeedReader::class.java)
return feedReader.readAtom() return feedReader.readAtom()
.items .items
?.map { ?.map {
val created = LocalDateTime.parse(it.lastUpdatedTime, LocalDateTimeAdapter.formatter)
val created = OffsetDateTime.parse(it.lastUpdatedTime)
val link = it.links!!.first().href!! val link = it.links!!.first().href!!
Release( Release(
id = it.title, id = it.title,
link = link, link = link,
created = created, created = created.atZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(),
githubRepo = githubRepo githubRepo = githubRepo
) )
} }

View file

@ -0,0 +1,22 @@
package de.rpr.githubreleases.model
data class GithubRepo(private val repositoryPath: String) {
private val urlPrefix = "https://github.com/"
val name: String
get() {
val usernameEnd = repoPath.indexOf("/")
return repoPath.substring(usernameEnd + 1).trimEnd { ch -> ch == '/' }
}
val repoPath: String = repoPath(repositoryPath)
val url = urlPrefix + repoPath
private fun repoPath(repositoryPath: String) = if (repositoryPath.startsWith(urlPrefix)) {
repositoryPath.substring(19)
} else {
repositoryPath
}
}

View file

@ -1,4 +1,4 @@
package de.rpr.githubreleases package de.rpr.githubreleases.model
import java.time.LocalDateTime import java.time.LocalDateTime

View file

@ -1,4 +1,4 @@
package de.rpr.githubreleases package de.rpr.githubreleases.publishing
import social.bigbone.MastodonClient import social.bigbone.MastodonClient

View file

@ -1,5 +1,9 @@
package de.rpr.githubreleases package de.rpr.githubreleases.publishing
import de.rpr.githubreleases.Config
import de.rpr.githubreleases.LogLevel
import de.rpr.githubreleases.model.Releases
import de.rpr.githubreleases.log
import social.bigbone.MastodonClient import social.bigbone.MastodonClient
import social.bigbone.api.entity.data.Visibility import social.bigbone.api.entity.data.Visibility
import social.bigbone.api.exception.BigBoneRequestException import social.bigbone.api.exception.BigBoneRequestException
@ -11,6 +15,7 @@ class Publisher(
) { ) {
fun sendReleases(releases: Releases): Releases { fun sendReleases(releases: Releases): Releases {
log("${releases.size} new releases to publish")
val result = releases val result = releases
.onEach { release -> log("Publishing release: ${release.title}") } .onEach { release -> log("Publishing release: ${release.title}") }
.mapNotNull { release -> .mapNotNull { release ->

View file

@ -1,7 +1,12 @@
package de.rpr.githubreleases package de.rpr.githubreleases.repository
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import de.rpr.githubreleases.*
import de.rpr.githubreleases.model.GithubRepo
import de.rpr.githubreleases.model.Release
import de.rpr.githubreleases.model.Releases
import de.rpr.githubreleases.model.asCollection
import de.rpr.terminenbg.LocalDateAdapter import de.rpr.terminenbg.LocalDateAdapter
import de.rpr.terminenbg.LocalDateTimeAdapter import de.rpr.terminenbg.LocalDateTimeAdapter
import java.io.File import java.io.File

View file

@ -3,6 +3,7 @@ package de.rpr.githubreleases
import assertk.assertThat import assertk.assertThat
import assertk.assertions.containsExactly import assertk.assertions.containsExactly
import assertk.assertions.containsOnly import assertk.assertions.containsOnly
import de.rpr.githubreleases.model.GithubRepo
import io.kotest.core.spec.style.DescribeSpec import io.kotest.core.spec.style.DescribeSpec
import io.kotest.extensions.system.withEnvironment import io.kotest.extensions.system.withEnvironment
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
@ -22,7 +23,7 @@ class ConfigTest : DescribeSpec({
it("should populate instances from config") { it("should populate instances from config") {
val config = Config() val config = Config()
assertThat(config.githubRepos).containsExactly( assertThat(config.githubRepos).containsExactly(
GithubRepo("navidrome", "https://github.com/navidrome/navidrome/") GithubRepo("https://github.com/navidrome/navidrome/")
) )
assertThat(config.mastodonCredentials).containsOnly( assertThat(config.mastodonCredentials).containsOnly(
"navidrome" to Config.PublishingCredentials( "navidrome" to Config.PublishingCredentials(

View file

@ -1,8 +1,10 @@
package de.rpr.githubreleases package de.rpr.githubreleases
import de.rpr.githubreleases.model.GithubRepo
import de.rpr.githubreleases.model.Release
import java.time.LocalDateTime import java.time.LocalDateTime
val testGithubRepo = GithubRepo("example", "https://github.com/example/example") val testGithubRepo = GithubRepo("https://github.com/example/example")
val testRelease = Release( val testRelease = Release(
id = "id", id = "id",

View file

@ -0,0 +1,43 @@
package de.rpr.githubreleases.feed
import assertk.assertThat
import assertk.assertions.doesNotContain
import de.rpr.githubreleases.model.GithubRepo
import de.rpr.githubreleases.model.asCollection
import de.rpr.githubreleases.testRelease
import io.kotest.core.spec.style.DescribeSpec
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.mockk
import okhttp3.Call
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.ResponseBody
class FeedServiceTest : DescribeSpec({
val feedData = this::class.java.classLoader.getResource("releases.atom")?.readText()!!
val httpClient = mockk<OkHttpClient>()
val mockCall = mockk<Call>()
val mockResponse = mockk<Response>()
val mockResponseBody = mockk<ResponseBody>()
beforeTest {
clearAllMocks()
every { mockResponse.isSuccessful } returns true
every { mockResponse.body } returns mockResponseBody
every { mockResponseBody.string() } returns feedData
every { mockCall.execute() } returns mockResponse
every { httpClient.newCall(any()) } returns mockCall
}
describe("FeedService") {
it("should only return new releases") {
val feedService = FeedService(GithubRepo("navidrome/navidrome"), httpClient)
val result = feedService.getNewReleases(testRelease.copy(id = "v0.50.2").asCollection())
assertThat(result.map { it.id }).doesNotContain("v0.50.2")
}
}
})

View file

@ -1,9 +1,13 @@
package de.rpr.githubreleases package de.rpr.githubreleases.publishing
import assertk.assertThat import assertk.assertThat
import assertk.assertions.isEqualTo import assertk.assertions.isEqualTo
import assertk.assertions.isTrue import assertk.assertions.isTrue
import assertk.assertions.prop import assertk.assertions.prop
import de.rpr.githubreleases.Config
import de.rpr.githubreleases.model.Releases
import de.rpr.githubreleases.model.asCollection
import de.rpr.githubreleases.testRelease
import io.kotest.core.spec.style.DescribeSpec import io.kotest.core.spec.style.DescribeSpec
import io.kotest.extensions.system.withEnvironment import io.kotest.extensions.system.withEnvironment
import io.mockk.* import io.mockk.*

View file

@ -1,8 +1,14 @@
package de.rpr.githubreleases package de.rpr.githubreleases.repository
import assertk.assertThat import assertk.assertThat
import assertk.assertions.contains import assertk.assertions.contains
import assertk.assertions.isTrue import assertk.assertions.isTrue
import de.rpr.githubreleases.model.Release
import de.rpr.githubreleases.model.Releases
import de.rpr.githubreleases.testGithubRepo
import de.rpr.githubreleases.testRelease
import de.rpr.githubreleases.toFile
import de.rpr.githubreleases.toPath
import io.kotest.core.spec.style.DescribeSpec import io.kotest.core.spec.style.DescribeSpec
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files