Compare commits

...

11 Commits

Author SHA1 Message Date
semantic-release-bot
c71cbd0466 chore: Release v1.6.1 [skip ci]
## [1.6.1](https://github.com/ReVanced/revanced-api/compare/v1.6.0...v1.6.1) (2025-07-11)

### Bug Fixes

* Return latest regardless of prerelease parameter for release APIs ([53bd820](53bd82071d))
2025-07-11 10:12:16 +00:00
oSumAtrIX
f81f2a4f0e chore: Merge branch dev to main (#201)
This pull request will Merge branch `dev` to `main`.
2025-07-11 12:10:05 +02:00
semantic-release-bot
4149bc6bdb chore: Release v1.6.1-dev.1 [skip ci]
## [1.6.1-dev.1](https://github.com/ReVanced/revanced-api/compare/v1.6.0...v1.6.1-dev.1) (2025-07-10)

### Bug Fixes

* Return latest regardless of prerelease parameter for release APIs ([53bd820](53bd82071d))
2025-07-10 20:24:45 +00:00
oSumAtrIX
53bd82071d fix: Return latest regardless of prerelease parameter for release APIs 2025-06-27 23:24:26 +02:00
oSumAtrIX
ea86e9685f ci: Use action from other repo to purge unused images for consistency 2025-04-09 15:00:36 +02:00
oSumAtrIX
3242e551fd ci: Don't keep tagged images when purging them 2025-04-09 14:45:07 +02:00
semantic-release-bot
01d86ebba8 chore: Release v1.6.0 [skip ci]
# [1.6.0](https://github.com/ReVanced/revanced-api/compare/v1.5.0...v1.6.0) (2025-02-04)

### Features

* Add status page link to about ([8a957cd](8a957cd797))
* Add support for prereleases ([c25bc8b](c25bc8b4ba))
* Allow setting `Announcement.createdAt` when creating an announcement ([7f6e29d](7f6e29de52))
* Make some announcements schema fields nullable ([db22874](db22874f06))
2025-02-04 00:14:22 +00:00
oSumAtrIX
989094309f chore: Merge branch dev to main (#196)
This pull request will Merge branch `dev` to `main`.
2025-02-04 01:12:19 +01:00
semantic-release-bot
5b447aa62d chore: Release v1.6.0-dev.3 [skip ci]
# [1.6.0-dev.3](https://github.com/ReVanced/revanced-api/compare/v1.6.0-dev.2...v1.6.0-dev.3) (2024-12-25)

### Features

* Add status page link to about ([8a957cd](8a957cd797))
* Add support for prereleases ([c25bc8b](c25bc8b4ba))
2024-12-25 10:52:04 +00:00
oSumAtrIX
c25bc8b4ba feat: Add support for prereleases 2024-12-25 11:50:06 +01:00
oSumAtrIX
8a957cd797 feat: Add status page link to about 2024-12-25 11:50:05 +01:00
12 changed files with 106 additions and 30 deletions

View File

@@ -78,10 +78,10 @@ jobs:
webhook_url: ${{ env.PORTAINER_WEBHOOK_URL }}
- name: Purge outdated images
uses: actions/delete-package-versions@v5
uses: snok/container-retention-policy@v3.0.0
with:
package-name: 'revanced-api'
package-type: 'container'
min-versions-to-keep: 5
delete-only-untagged-versions: 'true'
account: ${{ github.repository_owner }}
token: ${{ secrets.GITHUB_TOKEN }}
image-names: revanced-api
keep-n-most-recent: 5
cut-off: 1w

View File

@@ -1,3 +1,35 @@
## [1.6.1](https://github.com/ReVanced/revanced-api/compare/v1.6.0...v1.6.1) (2025-07-11)
### Bug Fixes
* Return latest regardless of prerelease parameter for release APIs ([53bd820](https://github.com/ReVanced/revanced-api/commit/53bd82071db165741f8f08e7ec438b45abde4425))
## [1.6.1-dev.1](https://github.com/ReVanced/revanced-api/compare/v1.6.0...v1.6.1-dev.1) (2025-07-10)
### Bug Fixes
* Return latest regardless of prerelease parameter for release APIs ([53bd820](https://github.com/ReVanced/revanced-api/commit/53bd82071db165741f8f08e7ec438b45abde4425))
# [1.6.0](https://github.com/ReVanced/revanced-api/compare/v1.5.0...v1.6.0) (2025-02-04)
### Features
* Add status page link to about ([8a957cd](https://github.com/ReVanced/revanced-api/commit/8a957cd797e7e42f43670baaed60ac0d3543342f))
* Add support for prereleases ([c25bc8b](https://github.com/ReVanced/revanced-api/commit/c25bc8b4ba2bd4bf1708f19dc8bc228a7f54d548))
* Allow setting `Announcement.createdAt` when creating an announcement ([7f6e29d](https://github.com/ReVanced/revanced-api/commit/7f6e29de5205f63ac4aaea490c844b58e14000c8))
* Make some announcements schema fields nullable ([db22874](https://github.com/ReVanced/revanced-api/commit/db22874f063bae0c9e7f0c99a20cdf1b16addd89))
# [1.6.0-dev.3](https://github.com/ReVanced/revanced-api/compare/v1.6.0-dev.2...v1.6.0-dev.3) (2024-12-25)
### Features
* Add status page link to about ([8a957cd](https://github.com/ReVanced/revanced-api/commit/8a957cd797e7e42f43670baaed60ac0d3543342f))
* Add support for prereleases ([c25bc8b](https://github.com/ReVanced/revanced-api/commit/c25bc8b4ba2bd4bf1708f19dc8bc228a7f54d548))
# [1.6.0-dev.2](https://github.com/ReVanced/revanced-api/compare/v1.6.0-dev.1...v1.6.0-dev.2) (2024-12-20)

View File

@@ -5,6 +5,7 @@
"branding": {
"logo": "https://raw.githubusercontent.com/ReVanced/revanced-branding/main/assets/revanced-logo/revanced-logo.svg"
},
"status": "https://status.revanced.app",
"contact": {
"email": "contact@revanced.app"
},

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 1.6.0-dev.2
version = 1.6.1

View File

@@ -123,6 +123,7 @@ class APIAbout(
// Using a list instead of a set because set semantics are unnecessary here.
val socials: List<Social>?,
val donations: Donations?,
val status: String,
) {
@Serializable
class Branding(

View File

@@ -135,12 +135,14 @@ abstract class BackendRepository internal constructor(
* @property tag The tag of the release.
* @property assets The assets of the release.
* @property createdAt The date and time the release was created.
* @property prerelease Whether the release is a prerelease.
* @property releaseNote The release note of the release.
*/
class BackendRelease(
val tag: String,
val releaseNote: String,
val createdAt: LocalDateTime,
val prerelease: Boolean,
// Using a list instead of a set because set semantics are unnecessary here.
val assets: List<BackendAsset>,
) {
@@ -180,13 +182,13 @@ abstract class BackendRepository internal constructor(
*
* @param owner The owner of the repository.
* @param repository The name of the repository.
* @param tag The tag of the release. If null, the latest release is returned.
* @param prerelease Whether to get a prerelease.
* @return The release.
*/
abstract suspend fun release(
owner: String,
repository: String,
tag: String? = null,
prerelease: Boolean,
): BackendOrganization.BackendRepository.BackendRelease
/**

View File

@@ -24,10 +24,10 @@ class GitHubBackendRepository : BackendRepository("https://api.github.com", "htt
override suspend fun release(
owner: String,
repository: String,
tag: String?,
prerelease: Boolean,
): BackendRelease {
val release: GitHubRelease = if (tag != null) {
client.get(Releases.Tag(owner, repository, tag)).body()
val release: GitHubRelease = if (prerelease) {
client.get(Releases(owner, repository)).body<List<GitHubRelease>>().first()
} else {
client.get(Releases.Latest(owner, repository)).body()
}
@@ -36,6 +36,7 @@ class GitHubBackendRepository : BackendRepository("https://api.github.com", "htt
tag = release.tagName,
releaseNote = release.body,
createdAt = release.createdAt.toLocalDateTime(TimeZone.UTC),
prerelease = release.prerelease,
assets = release.assets.map {
BackendAsset(
name = it.name,
@@ -98,10 +99,10 @@ class GitHubBackendRepository : BackendRepository("https://api.github.com", "htt
url = user.htmlUrl,
bio = user.bio,
gpgKeys =
BackendMember.GpgKeys(
ids = gpgKeys.map { it.keyId },
url = "https://github.com/${user.login}.gpg",
),
BackendMember.GpgKeys(
ids = gpgKeys.map { it.keyId },
url = "https://github.com/${user.login}.gpg",
),
)
}
}
@@ -163,6 +164,7 @@ class GitHubOrganization {
// Using a list instead of a set because set semantics are unnecessary here.
val assets: List<GitHubAsset>,
val createdAt: Instant,
val prerelease: Boolean,
val body: String,
) {
@Serializable
@@ -200,10 +202,8 @@ class Organization {
@Resource("/repos/{owner}/{repo}/contributors")
class Contributors(val owner: String, val repo: String, @SerialName("per_page") val perPage: Int = 100)
class Releases {
@Resource("/repos/{owner}/{repo}/releases/tags/{tag}")
class Tag(val owner: String, val repo: String, val tag: String)
@Resource("/repos/{owner}/{repo}/releases")
class Releases(val owner: String, val repo: String, @SerialName("per_page") val perPage: Int = 1) {
@Resource("/repos/{owner}/{repo}/releases/latest")
class Latest(val owner: String, val repo: String)
}

View File

@@ -5,6 +5,8 @@ import app.revanced.api.configuration.ApiReleaseVersion
import app.revanced.api.configuration.installNotarizedRoute
import app.revanced.api.configuration.services.ManagerService
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.plugins.ratelimit.*
@@ -19,25 +21,38 @@ internal fun Route.managerRoute() = route("manager") {
rateLimit(RateLimitName("weak")) {
get {
call.respond(managerService.latestRelease())
val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false
call.respond(managerService.latestRelease(prerelease))
}
route("version") {
installManagerVersionRouteDocumentation()
get {
call.respond(managerService.latestVersion())
val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false
call.respond(managerService.latestVersion(prerelease))
}
}
}
}
private val prereleaseParameter = Parameter(
name = "prerelease",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING,
description = "Whether to get the current manager prerelease",
required = false,
)
private fun Route.installManagerRouteDocumentation() = installNotarizedRoute {
tags = setOf("Manager")
get = GetInfo.builder {
description("Get the current manager release")
summary("Get current manager release")
parameters(prereleaseParameter)
response {
description("The latest manager release")
mediaTypes("application/json")
@@ -53,6 +68,7 @@ private fun Route.installManagerVersionRouteDocumentation() = installNotarizedRo
get = GetInfo.builder {
description("Get the current manager release version")
summary("Get current manager release version")
parameters(prereleaseParameter)
response {
description("The current manager release version")
mediaTypes("application/json")

View File

@@ -7,6 +7,8 @@ import app.revanced.api.configuration.installCache
import app.revanced.api.configuration.installNotarizedRoute
import app.revanced.api.configuration.services.PatchesService
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.plugins.ratelimit.*
@@ -22,14 +24,18 @@ internal fun Route.patchesRoute() = route("patches") {
rateLimit(RateLimitName("weak")) {
get {
call.respond(patchesService.latestRelease())
val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false
call.respond(patchesService.latestRelease(prerelease))
}
route("version") {
installPatchesVersionRouteDocumentation()
get {
call.respond(patchesService.latestVersion())
val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false
call.respond(patchesService.latestVersion(prerelease))
}
}
}
@@ -39,7 +45,9 @@ internal fun Route.patchesRoute() = route("patches") {
installPatchesListRouteDocumentation()
get {
call.respondBytes(ContentType.Application.Json) { patchesService.list() }
val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false
call.respondBytes(ContentType.Application.Json) { patchesService.list(prerelease) }
}
}
}
@@ -57,12 +65,21 @@ internal fun Route.patchesRoute() = route("patches") {
}
}
private val prereleaseParameter = Parameter(
name = "prerelease",
`in` = Parameter.Location.query,
schema = TypeDefinition.STRING,
description = "Whether to get the current patches prerelease",
required = false,
)
private fun Route.installPatchesRouteDocumentation() = installNotarizedRoute {
tags = setOf("Patches")
get = GetInfo.builder {
description("Get the current patches release")
summary("Get current patches release")
parameters(prereleaseParameter)
response {
description("The current patches release")
mediaTypes("application/json")
@@ -78,6 +95,7 @@ private fun Route.installPatchesVersionRouteDocumentation() = installNotarizedRo
get = GetInfo.builder {
description("Get the current patches release version")
summary("Get current patches release version")
parameters(prereleaseParameter)
response {
description("The current patches release version")
mediaTypes("application/json")
@@ -93,6 +111,7 @@ private fun Route.installPatchesListRouteDocumentation() = installNotarizedRoute
get = GetInfo.builder {
description("Get the list of patches from the current patches release")
summary("Get list of patches from current patches release")
parameters(prereleaseParameter)
response {
description("The list of patches")
mediaTypes("application/json")

View File

@@ -10,10 +10,11 @@ internal class ManagerService(
private val backendRepository: BackendRepository,
private val configurationRepository: ConfigurationRepository,
) {
suspend fun latestRelease(): ApiRelease {
suspend fun latestRelease(prerelease: Boolean): ApiRelease {
val managerRelease = backendRepository.release(
configurationRepository.organization,
configurationRepository.manager.repository,
prerelease,
)
return ApiRelease(
@@ -24,10 +25,11 @@ internal class ManagerService(
)
}
suspend fun latestVersion(): ApiReleaseVersion {
suspend fun latestVersion(prerelease: Boolean): ApiReleaseVersion {
val managerRelease = backendRepository.release(
configurationRepository.organization,
configurationRepository.manager.repository,
prerelease,
)
return ApiReleaseVersion(managerRelease.tag)

View File

@@ -19,10 +19,11 @@ internal class PatchesService(
private val backendRepository: BackendRepository,
private val configurationRepository: ConfigurationRepository,
) {
suspend fun latestRelease(): ApiRelease {
suspend fun latestRelease(prerelease: Boolean): ApiRelease {
val patchesRelease = backendRepository.release(
configurationRepository.organization,
configurationRepository.patches.repository,
prerelease,
)
return ApiRelease(
@@ -34,10 +35,11 @@ internal class PatchesService(
)
}
suspend fun latestVersion(): ApiReleaseVersion {
suspend fun latestVersion(prerelease: Boolean): ApiReleaseVersion {
val patchesRelease = backendRepository.release(
configurationRepository.organization,
configurationRepository.patches.repository,
prerelease,
)
return ApiReleaseVersion(patchesRelease.tag)
@@ -48,10 +50,11 @@ internal class PatchesService(
.maximumSize(1)
.build<String, ByteArray>()
suspend fun list(): ByteArray {
suspend fun list(prerelease: Boolean): ByteArray {
val patchesRelease = backendRepository.release(
configurationRepository.organization,
configurationRepository.patches.repository,
prerelease,
)
return withContext(Dispatchers.IO) {

View File

@@ -12,7 +12,7 @@ import java.security.MessageDigest
internal class SignatureService {
private val signatureCache = Caffeine
.newBuilder()
.maximumSize(1) // 1 because currently only the latest patches is needed.
.maximumSize(2) // 2 because currently only the latest release and prerelease patches are needed.
.build<ByteArray, Boolean>() // Hash -> Verified.
fun verify(