diff --git a/.github/scripts/replace_string.py b/.github/scripts/replace_string.py
old mode 100644
new mode 100755
index f398e8e11..9835ccdc7
--- a/.github/scripts/replace_string.py
+++ b/.github/scripts/replace_string.py
@@ -2,6 +2,9 @@
import argparse
from pathlib import Path
+import sys
+import git
+
def main() -> None:
parser = argparse.ArgumentParser()
@@ -13,11 +16,20 @@ def main() -> None:
def replace_string(path: Path, old_string: str, new_string: str) -> None:
+ repo = git.Repo(path, search_parent_directories=True)
for file in path.glob('**/*'):
- if file.is_file():
+ if not should_replace(repo, file):
+ continue
+ try:
text = file.read_text()
text = text.replace(old_string, new_string)
file.write_text(text)
+ except UnicodeError as e:
+ print(f'Error processing file {file}:', e, file=sys.stderr)
+
+
+def should_replace(repo, file):
+ return file.is_file() and not repo.ignored(file) and file.parts[0] != '.git'
if __name__ == "__main__":
diff --git a/.github/scripts/requirements.txt b/.github/scripts/requirements.txt
new file mode 100644
index 000000000..239991ab1
--- /dev/null
+++ b/.github/scripts/requirements.txt
@@ -0,0 +1 @@
+GitPython==3.1.31
diff --git a/.github/scripts/test_replace_string.py b/.github/scripts/test_replace_string.py
old mode 100644
new mode 100755
index 6099b990f..29f94f43a
--- a/.github/scripts/test_replace_string.py
+++ b/.github/scripts/test_replace_string.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import unittest
+from unittest import mock
from pathlib import Path
from shutil import copytree
from tempfile import TemporaryDirectory
@@ -10,7 +11,9 @@
class TestReplaceString(unittest.TestCase):
- def test_replace_string(self):
+ @mock.patch('git.Repo')
+ def test_replace_string(self, repo):
+ repo.return_value.ignored.return_value = False
old = '0.17.0'
new = '0.17.1'
files = ('README.md', 'build.gradle.kts', 'notebook.ipynb')
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index f0362a6c7..eb0b56d33 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -26,6 +26,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
+ - run: pip install -r .github/scripts/requirements.txt
- name: 'unittest discover'
run: python3 -m unittest discover -bs .github/scripts
diff --git a/.github/workflows/update-examples.yml b/.github/workflows/update-examples.yml
index ba891e993..592805704 100644
--- a/.github/workflows/update-examples.yml
+++ b/.github/workflows/update-examples.yml
@@ -16,6 +16,7 @@ jobs:
steps:
- name: 'Checkout'
uses: actions/checkout@v3
+ - run: pip install -r .github/scripts/requirements.txt
- name: 'Get versions'
run: |
old_version="$(git tag --sort=-v:refname | head -n 2 | tail -n 1)"
diff --git a/README.md b/README.md
index 2fa4d8e12..f8c08fe37 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# Gradle Enterprise API Kotlin
-[][14]
-[][7]
+[][14]
+[][7]
A Kotlin library to access the [Gradle Enterprise API][1], easy to use from:
@@ -9,10 +9,9 @@ A Kotlin library to access the [Gradle Enterprise API][1], easy to use from:
- [Kotlin scripts (`kts`)][27]
- [Kotlin projects][28]
-Using the API is as easy as this:
-
```kotlin
-GradleEnterpriseApi.buildsApi.getBuilds(since = yesterdayMilli).forEach {
+val api = GradleEnterpriseApi.newInstance()
+api.buildsApi.getBuilds(since = yesterdayMilli).forEach {
println(it)
}
```
@@ -53,7 +52,7 @@ recommended over JitPack.
```
%useLatestDescriptors
-%use gradle-enterprise-api-kotlin(version=0.16.2)
+%use gradle-enterprise-api-kotlin(version=0.17.0)
```
@@ -62,7 +61,7 @@ recommended over JitPack.
Add to a Kotlin script
```kotlin
-@file:DependsOn("com.gabrielfeo:gradle-enterprise-api-kotlin:0.16.2")
+@file:DependsOn("com.gabrielfeo:gradle-enterprise-api-kotlin:0.17.0")
```
@@ -72,7 +71,7 @@ recommended over JitPack.
```kotlin
dependencies {
- implementation("com.gabrielfeo:gradle-enterprise-api-kotlin:0.16.2")
+ implementation("com.gabrielfeo:gradle-enterprise-api-kotlin:0.17.0")
}
```
@@ -101,11 +100,13 @@ For example, [`BuildsApi`][20] contains all endpoints under `/api/builds/`:
### Calling the APIs
-For simple use cases, you may use the companion instance ([DefaultInstance][23]) directly, as if
-calling static methods:
+API methods are generated as suspend functions.
+For most cases like scripts and notebooks, simply use [runBlocking][30]:
```kotlin
-GradleEnterpriseApi.buildsApi.getBuilds(since = yesterdayMilli)
+runBlocking {
+ val builds: List = api.buildsApi.getBuilds(since = yesterdayMilli)
+}
```
It's recommended to call [`GradleEnterpriseApi.shutdown()`][11] at the end of scripts to release
@@ -130,7 +131,7 @@ also takes care of paging under-the-hood, returning a [`Flow`][26] of all builds
date, so you don't have to worry about the REST API's limit of 1000 builds per request:
```kotlin
-val builds = GradleEnterpriseApi.buildsApi.getGradleAttributesFlow(since = lastYear)
+val builds: Flow = api.buildsApi.getGradleAttributesFlow(since = lastYear)
builds.collect {
// ...
}
@@ -189,7 +190,7 @@ import com.gabrielfeo.gradle.enterprise.api.model.extension.*
[11]: https://gabrielfeo.github.io/gradle-enterprise-api-kotlin/library/com.gabrielfeo.gradle.enterprise.api/-gradle-enterprise-api/shutdown.html
[12]: https://gabrielfeo.github.io/gradle-enterprise-api-kotlin/library/com.gabrielfeo.gradle.enterprise.api/-config/-cache-config/cache-enabled.html
[13]: https://gabrielfeo.github.io/gradle-enterprise-api-kotlin/library/com.gabrielfeo.gradle.enterprise.api/-config/-cache-config/index.html
-[14]: https://central.sonatype.com/artifact/com.gabrielfeo/gradle-enterprise-api-kotlin/0.16.2
+[14]: https://central.sonatype.com/artifact/com.gabrielfeo/gradle-enterprise-api-kotlin/0.17.0
[16]: https://gabrielfeo.github.io/gradle-enterprise-api-kotlin/library/com.gabrielfeo.gradle.enterprise.api/-config/api-url.html
[17]: https://gabrielfeo.github.io/gradle-enterprise-api-kotlin/library/com.gabrielfeo.gradle.enterprise.api/-config/api-token.html
[18]: https://gabrielfeo.github.io/gradle-enterprise-api-kotlin/library/com.gabrielfeo.gradle.enterprise.api/-builds-api/index.html
@@ -204,3 +205,4 @@ import com.gabrielfeo.gradle.enterprise.api.model.extension.*
[27]: ./examples/example-script.main.kts
[28]: ./examples/example-project
[29]: https://nbviewer.org/github/gabrielfeo/gradle-enterprise-api-kotlin/blob/main/examples/example-notebooks/MostFrequentBuilds.ipynb
+[30]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
diff --git a/examples/example-notebooks/MostFrequentBuilds.ipynb b/examples/example-notebooks/MostFrequentBuilds.ipynb
index ef21c547d..9ddadc789 100644
--- a/examples/example-notebooks/MostFrequentBuilds.ipynb
+++ b/examples/example-notebooks/MostFrequentBuilds.ipynb
@@ -35,7 +35,7 @@
"Add libraries to use, via line magics. `%use` is a [line magic](https://github.com/Kotlin/kotlin-jupyter#line-magics) of the Kotlin kernel that can do much more than adding the library. To illustrate, this setup can be replaced with a single line magic.\n",
"\n",
"```kotlin\n",
- "@file:DependsOn(\"com.gabrielfeo:gradle-enterprise-api-kotlin:0.16.2\")\n",
+ "@file:DependsOn(\"com.gabrielfeo:gradle-enterprise-api-kotlin:0.17.0\")\n",
"\n",
"import com.gabrielfeo.gradle.enterprise.api.*\n",
"import com.gabrielfeo.gradle.enterprise.api.model.*\n",
@@ -45,7 +45,7 @@
"is the same as:\n",
"\n",
"```\n",
- "%use gradle-enterprise-api-kotlin(version=0.16.2)\n",
+ "%use gradle-enterprise-api-kotlin(version=0.17.0)\n",
"```"
]
},
@@ -57,7 +57,7 @@
"outputs": [],
"source": [
"%useLatestDescriptors\n",
- "%use gradle-enterprise-api-kotlin(version=0.16.2)\n",
+ "%use gradle-enterprise-api-kotlin(version=0.17.0)\n",
"%use coroutines(v=1.7.1)"
]
},
@@ -112,9 +112,10 @@
"import java.time.temporal.*\n",
"import java.util.LinkedList\n",
"\n",
+ "val api = GradleEnterpriseApi.newInstance()\n",
"val builds: List = runBlocking {\n",
" val startMilli = startDate.atStartOfDay(ZoneId.of(\"UTC\")).toInstant().toEpochMilli()\n",
- " GradleEnterpriseApi.buildsApi.getGradleAttributesFlow(since = startMilli)\n",
+ " api.buildsApi.getGradleAttributesFlow(since = startMilli)\n",
" .filter(buildFilter)\n",
" .toList(LinkedList())\n",
"}"
diff --git a/examples/example-project/app/build.gradle.kts b/examples/example-project/app/build.gradle.kts
index 4989d92b9..bc23c0fd0 100644
--- a/examples/example-project/app/build.gradle.kts
+++ b/examples/example-project/app/build.gradle.kts
@@ -14,5 +14,5 @@ java {
}
dependencies {
- implementation("com.gabrielfeo:gradle-enterprise-api-kotlin:0.16.2")
+ implementation("com.gabrielfeo:gradle-enterprise-api-kotlin:0.17.0")
}
diff --git a/examples/example-script.main.kts b/examples/example-script.main.kts
index 8f6789ad6..24c63b6b0 100644
--- a/examples/example-script.main.kts
+++ b/examples/example-script.main.kts
@@ -15,7 +15,7 @@
* legacy tests. We should suggest they run test instead, leaving check for CI to run."
*/
-@file:DependsOn("com.gabrielfeo:gradle-enterprise-api-kotlin:0.16.2")
+@file:DependsOn("com.gabrielfeo:gradle-enterprise-api-kotlin:0.17.0")
import com.gabrielfeo.gradle.enterprise.api.*
import com.gabrielfeo.gradle.enterprise.api.model.*
@@ -32,9 +32,10 @@ val buildFilter: (GradleAttributes) -> Boolean = { build ->
}
// Fetch builds from the API
+val api = GradleEnterpriseApi.newInstance()
val builds: List = runBlocking {
val startMilli = startDate.atStartOfDay(ZoneId.of("UTC")).toInstant().toEpochMilli()
- GradleEnterpriseApi.buildsApi.getGradleAttributesFlow(since = startMilli)
+ api.buildsApi.getGradleAttributesFlow(since = startMilli)
.filter(buildFilter)
.toList(LinkedList())
}
diff --git a/library/src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/GradleEnterpriseApi.kt b/library/src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/GradleEnterpriseApi.kt
index 01074faec..1bbb1f163 100644
--- a/library/src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/GradleEnterpriseApi.kt
+++ b/library/src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/GradleEnterpriseApi.kt
@@ -3,6 +3,7 @@ package com.gabrielfeo.gradle.enterprise.api
import com.gabrielfeo.gradle.enterprise.api.internal.buildOkHttpClient
import com.gabrielfeo.gradle.enterprise.api.internal.buildRetrofit
import com.gabrielfeo.gradle.enterprise.api.internal.infrastructure.Serializer
+import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.create
@@ -15,15 +16,14 @@ import retrofit2.create
* - [metaApi]
* - [testDistributionApi]
*
- * For simple use cases, you may use the companion instance ([DefaultInstance]) directly, as if
- * calling static methods:
+ * Create an instance with [newInstance]:
*
* ```kotlin
- * GradleEnterpriseApi.buildsApi.getBuilds(...)
+ * val api = GradleEnterpriseApi.newInstance()
+ * api.buildsApi.getBuilds(...)
* ```
*
- * However, if you need to change [config] at runtime or own the instance's lifecycle (e.g.
- * with an IoC container like Dagger), create a new instance:
+ * You may pass a default [Config], e.g. for sharing [OkHttpClient] resources:
*
* ```kotlin
* val options = Options(clientBuilder = myOwnOkHttpClient.newBuilder())
@@ -48,10 +48,6 @@ interface GradleEnterpriseApi {
*/
fun shutdown()
- /**
- * The default, companion instance of the Gradle Enterprise API client. See
- * [GradleEnterpriseApi].
- */
companion object {
/**