diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 964b583..94ac9b2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -27,7 +27,7 @@ repositories { } 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")))) val buildDir = layout.buildDirectory.get() diff --git a/app/src/main/kotlin/de/rpr/githubreleases/App.kt b/app/src/main/kotlin/de/rpr/githubreleases/App.kt index 7e8a4d4..ea32424 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/App.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/App.kt @@ -1,5 +1,9 @@ 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 java.util.concurrent.Executors import java.util.concurrent.TimeUnit @@ -27,7 +31,7 @@ class App( } private fun execute() { - + log("Processing feed...") config.githubRepos.forEach { githubRepo -> val existingReleases = releaseRepo.getExistingReleases(githubRepo) val feedService = FeedService(githubRepo, httpClient) @@ -35,6 +39,7 @@ class App( val publisher = publishers.forName(githubRepo.name) val publishedReleases = publisher.sendReleases(newReleases) releaseRepo.save(publishedReleases) + log("Finished feed processing...") } } } diff --git a/app/src/main/kotlin/de/rpr/githubreleases/Config.kt b/app/src/main/kotlin/de/rpr/githubreleases/Config.kt index 383e682..d23642d 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/Config.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/Config.kt @@ -1,6 +1,7 @@ package de.rpr.githubreleases; import de.rpr.githubreleases.LogLevel.ERROR +import de.rpr.githubreleases.model.GithubRepo class Config { @@ -45,7 +46,7 @@ class Config { } githubRepos = githubReposString.split(",").map { - GithubRepo(repoName(it), it) + GithubRepo(it) } 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 == '/' } - } } \ No newline at end of file diff --git a/app/src/main/kotlin/de/rpr/githubreleases/GithubRepo.kt b/app/src/main/kotlin/de/rpr/githubreleases/GithubRepo.kt deleted file mode 100644 index 564889a..0000000 --- a/app/src/main/kotlin/de/rpr/githubreleases/GithubRepo.kt +++ /dev/null @@ -1,6 +0,0 @@ -package de.rpr.githubreleases - -data class GithubRepo( - val name: String, - val url: String -) \ No newline at end of file diff --git a/app/src/main/kotlin/de/rpr/githubreleases/FeedReader.kt b/app/src/main/kotlin/de/rpr/githubreleases/feed/FeedReader.kt similarity index 75% rename from app/src/main/kotlin/de/rpr/githubreleases/FeedReader.kt rename to app/src/main/kotlin/de/rpr/githubreleases/feed/FeedReader.kt index 842542a..fbcb86c 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/FeedReader.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/feed/FeedReader.kt @@ -1,4 +1,4 @@ -package de.rpr.githubreleases +package de.rpr.githubreleases.feed import com.ouattararomuald.syndication.atom.AtomFeed diff --git a/app/src/main/kotlin/de/rpr/githubreleases/FeedService.kt b/app/src/main/kotlin/de/rpr/githubreleases/feed/FeedService.kt similarity index 63% rename from app/src/main/kotlin/de/rpr/githubreleases/FeedService.kt rename to app/src/main/kotlin/de/rpr/githubreleases/feed/FeedService.kt index cfa22f0..65fd439 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/FeedService.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/feed/FeedService.kt @@ -1,9 +1,16 @@ -package de.rpr.githubreleases +package de.rpr.githubreleases.feed 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 okhttp3.OkHttpClient import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.time.ZoneId class FeedService( private val githubRepo: GithubRepo, @@ -15,18 +22,19 @@ class FeedService( ) 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) return feedReader.readAtom() .items ?.map { - val created = LocalDateTime.parse(it.lastUpdatedTime, LocalDateTimeAdapter.formatter) + + val created = OffsetDateTime.parse(it.lastUpdatedTime) val link = it.links!!.first().href!! Release( id = it.title, link = link, - created = created, + created = created.atZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(), githubRepo = githubRepo ) } diff --git a/app/src/main/kotlin/de/rpr/githubreleases/model/GithubRepo.kt b/app/src/main/kotlin/de/rpr/githubreleases/model/GithubRepo.kt new file mode 100644 index 0000000..e416ecb --- /dev/null +++ b/app/src/main/kotlin/de/rpr/githubreleases/model/GithubRepo.kt @@ -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 + } + +} \ No newline at end of file diff --git a/app/src/main/kotlin/de/rpr/githubreleases/Releases.kt b/app/src/main/kotlin/de/rpr/githubreleases/model/Releases.kt similarity index 98% rename from app/src/main/kotlin/de/rpr/githubreleases/Releases.kt rename to app/src/main/kotlin/de/rpr/githubreleases/model/Releases.kt index d7ab887..cf18ac2 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/Releases.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/model/Releases.kt @@ -1,4 +1,4 @@ -package de.rpr.githubreleases +package de.rpr.githubreleases.model import java.time.LocalDateTime diff --git a/app/src/main/kotlin/de/rpr/githubreleases/MastodonClientFactory.kt b/app/src/main/kotlin/de/rpr/githubreleases/publishing/MastodonClientFactory.kt similarity index 82% rename from app/src/main/kotlin/de/rpr/githubreleases/MastodonClientFactory.kt rename to app/src/main/kotlin/de/rpr/githubreleases/publishing/MastodonClientFactory.kt index a8561ec..ac637e0 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/MastodonClientFactory.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/publishing/MastodonClientFactory.kt @@ -1,4 +1,4 @@ -package de.rpr.githubreleases +package de.rpr.githubreleases.publishing import social.bigbone.MastodonClient diff --git a/app/src/main/kotlin/de/rpr/githubreleases/Publisher.kt b/app/src/main/kotlin/de/rpr/githubreleases/publishing/Publisher.kt similarity index 89% rename from app/src/main/kotlin/de/rpr/githubreleases/Publisher.kt rename to app/src/main/kotlin/de/rpr/githubreleases/publishing/Publisher.kt index b22b1da..c64d87e 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/Publisher.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/publishing/Publisher.kt @@ -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.api.entity.data.Visibility import social.bigbone.api.exception.BigBoneRequestException @@ -11,6 +15,7 @@ class Publisher( ) { fun sendReleases(releases: Releases): Releases { + log("${releases.size} new releases to publish") val result = releases .onEach { release -> log("Publishing release: ${release.title}") } .mapNotNull { release -> diff --git a/app/src/main/kotlin/de/rpr/githubreleases/ReleaseRepository.kt b/app/src/main/kotlin/de/rpr/githubreleases/repository/ReleaseRepository.kt similarity index 85% rename from app/src/main/kotlin/de/rpr/githubreleases/ReleaseRepository.kt rename to app/src/main/kotlin/de/rpr/githubreleases/repository/ReleaseRepository.kt index a17dc07..c6c49fb 100644 --- a/app/src/main/kotlin/de/rpr/githubreleases/ReleaseRepository.kt +++ b/app/src/main/kotlin/de/rpr/githubreleases/repository/ReleaseRepository.kt @@ -1,7 +1,12 @@ -package de.rpr.githubreleases +package de.rpr.githubreleases.repository import com.google.gson.Gson 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.LocalDateTimeAdapter import java.io.File diff --git a/app/src/test/kotlin/de/rpr/githubreleases/ConfigTest.kt b/app/src/test/kotlin/de/rpr/githubreleases/ConfigTest.kt index dde1ec7..2346bb1 100644 --- a/app/src/test/kotlin/de/rpr/githubreleases/ConfigTest.kt +++ b/app/src/test/kotlin/de/rpr/githubreleases/ConfigTest.kt @@ -3,6 +3,7 @@ package de.rpr.githubreleases import assertk.assertThat import assertk.assertions.containsExactly import assertk.assertions.containsOnly +import de.rpr.githubreleases.model.GithubRepo import io.kotest.core.spec.style.DescribeSpec import io.kotest.extensions.system.withEnvironment import org.junit.jupiter.api.assertThrows @@ -22,7 +23,7 @@ class ConfigTest : DescribeSpec({ it("should populate instances from config") { val config = Config() assertThat(config.githubRepos).containsExactly( - GithubRepo("navidrome", "https://github.com/navidrome/navidrome/") + GithubRepo("https://github.com/navidrome/navidrome/") ) assertThat(config.mastodonCredentials).containsOnly( "navidrome" to Config.PublishingCredentials( diff --git a/app/src/test/kotlin/de/rpr/githubreleases/TestData.kt b/app/src/test/kotlin/de/rpr/githubreleases/TestData.kt index 4bde219..4c23910 100644 --- a/app/src/test/kotlin/de/rpr/githubreleases/TestData.kt +++ b/app/src/test/kotlin/de/rpr/githubreleases/TestData.kt @@ -1,8 +1,10 @@ package de.rpr.githubreleases +import de.rpr.githubreleases.model.GithubRepo +import de.rpr.githubreleases.model.Release import java.time.LocalDateTime -val testGithubRepo = GithubRepo("example", "https://github.com/example/example") +val testGithubRepo = GithubRepo("https://github.com/example/example") val testRelease = Release( id = "id", diff --git a/app/src/test/kotlin/de/rpr/githubreleases/feed/FeedServiceTest.kt b/app/src/test/kotlin/de/rpr/githubreleases/feed/FeedServiceTest.kt new file mode 100644 index 0000000..669b936 --- /dev/null +++ b/app/src/test/kotlin/de/rpr/githubreleases/feed/FeedServiceTest.kt @@ -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() + val mockCall = mockk() + val mockResponse = mockk() + val mockResponseBody = mockk() + + 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") + } + } +}) \ No newline at end of file diff --git a/app/src/test/kotlin/de/rpr/githubreleases/PublishersTest.kt b/app/src/test/kotlin/de/rpr/githubreleases/publishing/PublishersTest.kt similarity index 95% rename from app/src/test/kotlin/de/rpr/githubreleases/PublishersTest.kt rename to app/src/test/kotlin/de/rpr/githubreleases/publishing/PublishersTest.kt index 9f3419b..05cfbbf 100644 --- a/app/src/test/kotlin/de/rpr/githubreleases/PublishersTest.kt +++ b/app/src/test/kotlin/de/rpr/githubreleases/publishing/PublishersTest.kt @@ -1,9 +1,13 @@ -package de.rpr.githubreleases +package de.rpr.githubreleases.publishing import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.isTrue 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.extensions.system.withEnvironment import io.mockk.* diff --git a/app/src/test/kotlin/de/rpr/githubreleases/ReleaseRepositoryTest.kt b/app/src/test/kotlin/de/rpr/githubreleases/repository/ReleaseRepositoryTest.kt similarity index 90% rename from app/src/test/kotlin/de/rpr/githubreleases/ReleaseRepositoryTest.kt rename to app/src/test/kotlin/de/rpr/githubreleases/repository/ReleaseRepositoryTest.kt index fe8cf06..fa6ecce 100644 --- a/app/src/test/kotlin/de/rpr/githubreleases/ReleaseRepositoryTest.kt +++ b/app/src/test/kotlin/de/rpr/githubreleases/repository/ReleaseRepositoryTest.kt @@ -1,8 +1,14 @@ -package de.rpr.githubreleases +package de.rpr.githubreleases.repository import assertk.assertThat import assertk.assertions.contains 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 java.io.File import java.nio.file.Files