diff --git a/docs/website/overrides/main.html b/docs/website/overrides/main.html index 2deccec..d2c539f 100644 --- a/docs/website/overrides/main.html +++ b/docs/website/overrides/main.html @@ -8,6 +8,6 @@ {% endif %} {% endblock %} -{% block announce %} - Do you like our projects?    Support us by following Ivan on GitHub! -{% endblock %} + + + -- 2.51.2 From 7eda841825abf928cde8473f561e22c8a0ed599e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Sun, 13 Apr 2025 12:19:48 +0200 Subject: [PATCH 02/14] build(website): Decrease the visibility of the 'news' section in the site search --- docs/website/generate-news.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/website/generate-news.sh b/docs/website/generate-news.sh index d748dad..21b5723 100755 --- a/docs/website/generate-news.sh +++ b/docs/website/generate-news.sh @@ -7,7 +7,7 @@ for tag in $(git tag --list -n1 | cut -d' ' -f1); do tag_file="docs/news/posts/releases/release-$tag.md" git for-each-ref \ - --format="---%ndate:%n created: %(taggerdate:short)%nslug: v$tag%ntags: %n - Releases%n---%n%n# $tag • %(subject)%n%n%(contents:body)" \ + --format="---%ndate:%n created: %(taggerdate:short)%nsearch:%n boost: 0.25%nslug: v$tag%ntags: %n - Releases%n---%n%n# $tag • %(subject)%n%n%(contents:body)" \ "refs/tags/$tag" \ | sed 's/%n/\n/g' \ | sed -r "s~\#([0-9]+)~[#\1]($CI_PROJECT_URL/-/issues/\1)~g" \ -- 2.51.2 From 5aafb5e372245c289ae173df153f9c97f3a19456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Sun, 22 Mar 2026 12:59:29 +0100 Subject: [PATCH 03/14] feat(website): Display the full page title in social images --- docs/website/layouts/default.yml | 257 +++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 docs/website/layouts/default.yml diff --git a/docs/website/layouts/default.yml b/docs/website/layouts/default.yml new file mode 100644 index 0000000..7b997ac --- /dev/null +++ b/docs/website/layouts/default.yml @@ -0,0 +1,257 @@ +# Copyright (c) 2016-2025 Martin Donath + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +# ----------------------------------------------------------------------------- +# Configuration +# ----------------------------------------------------------------------------- + +# Definitions +definitions: + + # Background image + - &background_image >- + {{ layout.background_image | x }} + + # Background color (default: indigo) + - &background_color >- + {%- if layout.background_color -%} + {{ layout.background_color }} + {%- else -%} + {%- set palette = config.theme.palette or {} -%} + {%- if not palette is mapping -%} + {%- set list = palette | selectattr("primary") | list + palette -%} + {%- set palette = list | first -%} + {%- endif -%} + {%- set primary = palette.get("primary", "indigo") -%} + {%- set primary = primary.replace(" ", "-") -%} + {{ { + "red": "#ef5552", + "pink": "#e92063", + "purple": "#ab47bd", + "deep-purple": "#7e56c2", + "indigo": "#4051b5", + "blue": "#2094f3", + "light-blue": "#02a6f2", + "cyan": "#00bdd6", + "teal": "#009485", + "green": "#4cae4f", + "light-green": "#8bc34b", + "lime": "#cbdc38", + "yellow": "#ffec3d", + "amber": "#ffc105", + "orange": "#ffa724", + "deep-orange": "#ff6e42", + "brown": "#795649", + "grey": "#757575", + "blue-grey": "#546d78", + "black": "#000000", + "white": "#ffffff" + }[primary] or "#4051b5" }} + {%- endif -%} + + # Text color (default: white) + - &color >- + {%- if layout.color -%} + {{ layout.color }} + {%- else -%} + {%- set palette = config.theme.palette or {} -%} + {%- if not palette is mapping -%} + {%- set list = palette | selectattr("primary") | list + palette -%} + {%- set palette = list | first -%} + {%- endif -%} + {%- set primary = palette.get("primary", "indigo") -%} + {%- set primary = primary.replace(" ", "-") -%} + {{ { + "red": "#ffffff", + "pink": "#ffffff", + "purple": "#ffffff", + "deep-purple": "#ffffff", + "indigo": "#ffffff", + "blue": "#ffffff", + "light-blue": "#ffffff", + "cyan": "#ffffff", + "teal": "#ffffff", + "green": "#ffffff", + "light-green": "#ffffff", + "lime": "#000000", + "yellow": "#000000", + "amber": "#000000", + "orange": "#000000", + "deep-orange": "#ffffff", + "brown": "#ffffff", + "grey": "#ffffff", + "blue-grey": "#ffffff", + "black": "#ffffff", + "white": "#000000" + }[primary] or "#ffffff" }} + {%- endif -%} + + # Font family (default: Roboto) + - &font_family >- + {%- if layout.font_family -%} + {{ layout.font_family }} + {%- elif config.theme.font is mapping -%} + {{ config.theme.font.get("text", "Roboto") }} + {%- else -%} + Roboto + {%- endif -%} + + # Font variant + - &font_variant >- + {%- if layout.font_variant -%} + {{ layout.font_variant }} + {%- endif -%} + + # Site name + - &site_name >- + {{ config.site_name }} + + # Page title + # + # Modified by OpenSavvy: prefer the page's first heading over the (possibly + # short) navigation title, matching overrides/main.html's tag logic. + - &page_title >- + {%- if layout.title -%} + {{ layout.title }} + {%- elif page.toc | first is defined -%} + {{ page.toc.items[0].title }} + {%- else -%} + {{ page.meta.get("title", page.title) }} + {%- endif -%} + + # Page title with site name + # + # Modified by OpenSavvy: prefer the page's first heading over the (possibly + # short) navigation title, matching overrides/main.html's <title> tag logic. + - &page_title_with_site_name >- + {%- if not page.is_homepage -%} + {%- if page.toc | first is defined -%} + {%- set title = page.toc.items[0].title -%} + {%- else -%} + {%- set title = page.meta.get("title", page.title) -%} + {%- endif -%} + {{ title }} - {{ config.site_name }} + {%- else -%} + {{ config.site_name }} + {%- endif -%} + + # Page description + - &page_description >- + {%- if layout.description -%} + {{ layout.description }} + {%- else -%} + {{ page.meta.get("description", config.site_description) | x }} + {%- endif -%} + + # Logo + - &logo >- + {%- if layout.logo -%} + {{ layout.logo }} + {%- elif config.theme.logo -%} + {{ config.docs_dir }}/{{ config.theme.logo }} + {%- endif -%} + + # Logo (icon) + - &logo_icon >- + {%- if not layout.logo and config.theme.icon -%} + {{ config.theme.icon.logo | x }} + {%- endif -%} + +# Meta tags +tags: + + # Open Graph + og:type: website + og:title: *page_title_with_site_name + og:description: *page_description + og:image: "{{ image.url }}" + og:image:type: "{{ image.type }}" + og:image:width: "{{ image.width }}" + og:image:height: "{{ image.height }}" + og:url: "{{ page.canonical_url }}" + + # Twitter + twitter:card: summary_large_image + twitter:title: *page_title_with_site_name + twitter:description: *page_description + twitter:image: "{{ image.url }}" + +# ----------------------------------------------------------------------------- +# Specification +# ----------------------------------------------------------------------------- + +# Card size and layers +size: { width: 1200, height: 630 } +layers: + + # Background + - background: + image: *background_image + color: *background_color + + # Logo + - size: { width: 144, height: 144 } + offset: { x: 992, y: 64 } + background: + image: *logo + icon: + value: *logo_icon + color: *color + + # Site name + - size: { width: 832, height: 42 } + offset: { x: 64, y: 64 } + typography: + content: *site_name + color: *color + font: + family: *font_family + variant: *font_variant + style: Bold + + # Page title + - size: { width: 832, height: 310 } + offset: { x: 62, y: 160 } + typography: + content: *page_title + align: start + color: *color + line: + amount: 3 + height: 1.25 + font: + family: *font_family + variant: *font_variant + style: Bold + + # Page description + - size: { width: 832, height: 64 } + offset: { x: 64, y: 512 } + typography: + content: *page_description + align: start + color: *color + line: + amount: 2 + height: 1.5 + font: + family: *font_family + variant: *font_variant + style: Regular -- 2.51.2 From 5b9e6634e4e7ebf686eccfd064947b3739cab4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Thu, 2 Jul 2026 09:37:37 +0200 Subject: [PATCH 04/14] ci(gitlab): OpenSavvy Containers 0.8.10 --- .gitlab-ci.main.kts | 2 +- .gitlab-ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.main.kts b/.gitlab-ci.main.kts index 07b3bb3..90a0bd8 100755 --- a/.gitlab-ci.main.kts +++ b/.gitlab-ci.main.kts @@ -10,7 +10,7 @@ import opensavvy.gitlab.ci.script.shell /** * [OpenSavvy's CI container images](https://gitlab.com/opensavvy/automation/containers/-/releases) */ -val ciContainers = "0.8.7" +val ciContainers = "0.8.10" /** * The URL of the website built by /docs/website. diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8e7e36b..17fb572 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ include: variables: # https://gitlab.com/opensavvy/automation/containers - ci_containers: 0.8.7 + ci_containers: 0.8.10 workflow: rules: -- 2.51.2 From 6c7b79dab75955b13d28890d4abb3df04ccc8fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Sat, 1 Aug 2026 15:52:06 +0200 Subject: [PATCH 05/14] upgrade: Kotest 6.2.4 --- gradle/common.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/common.versions.toml b/gradle/common.versions.toml index 904b822..06dd404 100644 --- a/gradle/common.versions.toml +++ b/gradle/common.versions.toml @@ -14,7 +14,7 @@ ksp = "2.3.10" compose = "1.11.1" # https://github.com/kotest/kotest/releases -kotest = "6.1.11" +kotest = "6.2.4" # https://github.com/infix-de/testBalloon/releases testBalloon = "1.0.1-K2.4.0" -- 2.51.2 From c55ac9c65613a726b61ceb45786e62029906224e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Sat, 1 Aug 2026 15:52:20 +0200 Subject: [PATCH 06/14] upgrade: Pedestal 3.2.2 --- gradle/common.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/common.versions.toml b/gradle/common.versions.toml index 06dd404..3537f33 100644 --- a/gradle/common.versions.toml +++ b/gradle/common.versions.toml @@ -20,7 +20,7 @@ kotest = "6.2.4" testBalloon = "1.0.1-K2.4.0" # https://gitlab.com/opensavvy/groundwork/pedestal/-/releases -pedestal = "3.2.1" +pedestal = "3.2.2" # https://prepared.opensavvy.dev/news prepared = "2.5.3" -- 2.51.2 From 49f999f78521cde1b44d42cca537df7be02c594d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Sat, 1 Aug 2026 15:52:27 +0200 Subject: [PATCH 07/14] upgrade: Prepared 2.6.0 --- gradle/common.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/common.versions.toml b/gradle/common.versions.toml index 3537f33..5b49989 100644 --- a/gradle/common.versions.toml +++ b/gradle/common.versions.toml @@ -23,7 +23,7 @@ testBalloon = "1.0.1-K2.4.0" pedestal = "3.2.2" # https://prepared.opensavvy.dev/news -prepared = "2.5.3" +prepared = "2.6.0" # https://spine.opensavvy.dev/news spine = "0.12.0" -- 2.51.2 From d0390763b543f84bfe4aa83f4e27920e376a1256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Sat, 1 Aug 2026 15:52:34 +0200 Subject: [PATCH 08/14] upgrade: Spine 0.12.1 --- gradle/common.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/common.versions.toml b/gradle/common.versions.toml index 5b49989..8da89ad 100644 --- a/gradle/common.versions.toml +++ b/gradle/common.versions.toml @@ -26,7 +26,7 @@ pedestal = "3.2.2" prepared = "2.6.0" # https://spine.opensavvy.dev/news -spine = "0.12.0" +spine = "0.12.1" # https://ktmongo.opensavvy.dev/news ktmongo = "0.31.0" -- 2.51.2 From 90ed3f1d3d4c803a873bd42b3834036a0a1d7bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Mon, 24 Aug 2026 15:33:13 +0200 Subject: [PATCH 09/14] upgrade: KSP 2.3.11 --- gradle/common.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/common.versions.toml b/gradle/common.versions.toml index 8da89ad..2351fca 100644 --- a/gradle/common.versions.toml +++ b/gradle/common.versions.toml @@ -8,7 +8,7 @@ kotlin = "2.4.10" # https://github.com/google/ksp/releases -ksp = "2.3.10" +ksp = "2.3.11" # https://github.com/JetBrains/compose-multiplatform/releases compose = "1.11.1" -- 2.51.2 From fc845fc99f4e23566212aa0a71f0c24f8c4188b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Mon, 24 Aug 2026 15:33:34 +0200 Subject: [PATCH 10/14] upgrade: KtMongo 0.32.1 --- gradle/common.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/common.versions.toml b/gradle/common.versions.toml index 2351fca..c720728 100644 --- a/gradle/common.versions.toml +++ b/gradle/common.versions.toml @@ -29,7 +29,7 @@ prepared = "2.6.0" spine = "0.12.1" # https://ktmongo.opensavvy.dev/news -ktmongo = "0.31.0" +ktmongo = "0.32.1" # https://gitlab.com/opensavvy/telegram-bot/-/releases telegram-bot = "0.3.1" -- 2.51.2 From 7c56d47a14770791b697f34d1538d87e52128a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Mon, 10 Aug 2026 09:44:44 +0200 Subject: [PATCH 11/14] ci(gitlab): Install tvOS on macOS runners --- .gitlab-ci.main.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.main.kts b/.gitlab-ci.main.kts index b41e78f..74f9d36 100755 --- a/.gitlab-ci.main.kts +++ b/.gitlab-ci.main.kts @@ -84,6 +84,7 @@ fun Job.nativeIosArm64() { beforeScript { shell("xcodebuild -downloadPlatform iOS") shell("xcodebuild -downloadPlatform watchOS") + shell("xcodebuild -downloadPlatform tvOS") } tag("saas-macos-medium-m1") -- 2.51.2 From b1d129fcec7214d34847dc7a691f82edf7a9d255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Tue, 11 Aug 2026 14:35:06 +0200 Subject: [PATCH 12/14] build(gradle): Fix the JS and Wasm tests running for the templates in non-playground projects --- gradle/templates/template-lib/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/templates/template-lib/build.gradle.kts b/gradle/templates/template-lib/build.gradle.kts index e129127..5dd56e1 100644 --- a/gradle/templates/template-lib/build.gradle.kts +++ b/gradle/templates/template-lib/build.gradle.kts @@ -66,7 +66,7 @@ if (appGroup != "dev.opensavvy.playground") { onlyIf("Publishing is only enabled when built as part of the Playground") { false } } - if (this is Test) { + if (this is AbstractTestTask) { onlyIf("The template tests do not need to run when not building as part of the Playground") { System.getenv("CI") != null } } } -- 2.51.2 From c50ad9ecdd24a8701d98fdc6c54ee114746198e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Tue, 11 Aug 2026 14:37:09 +0200 Subject: [PATCH 13/14] build(gradle): The template app should not execute tests when the template lib doesn't --- .../templates/template-app/build.gradle.kts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/gradle/templates/template-app/build.gradle.kts b/gradle/templates/template-app/build.gradle.kts index 63db16c..f7ab4dc 100644 --- a/gradle/templates/template-app/build.gradle.kts +++ b/gradle/templates/template-app/build.gradle.kts @@ -51,3 +51,24 @@ tasks.withType<AbstractTestTask> { // Kotest doesn't report test correctly as of now failOnNoDiscoveredTests = false } + +// region Publication test +// Even though this module is included in all repositories that import the Playground, we +// don't want to always publish this template. + +val appGroup: String? by project + +@Suppress("UnstableApiUsage") // 'onlyIf' is unstable +if (appGroup != "dev.opensavvy.playground") { + tasks.configureEach { + if (name.startsWith("publish")) { + onlyIf("Publishing is only enabled when built as part of the Playground") { false } + } + + if (this is AbstractTestTask) { + onlyIf("The template tests do not need to run when not building as part of the Playground") { System.getenv("CI") != null } + } + } +} + +// endregion -- 2.51.2 From 2925582d03bd9a6247551d3fe094c2bad0067408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= <ivan.canet@gmail.com> Date: Tue, 18 Aug 2026 17:05:15 +0200 Subject: [PATCH 14/14] ci(gitlab): Create a job to run a pipeline with experimental Gradle dependencies --- .gitlab-ci.main.kts | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.main.kts b/.gitlab-ci.main.kts index b41e78f..540adea 100755 --- a/.gitlab-ci.main.kts +++ b/.gitlab-ci.main.kts @@ -21,8 +21,8 @@ val siteUrl = "\$CI_PAGES_URL" // *** -fun Job.opensavvyImage(name: String) = - image("registry.gitlab.com/opensavvy/automation/containers/$name", ciContainers) +fun Job.opensavvyImage(name: String, configuration: ContainerImage.() -> Unit = {}) = + image("registry.gitlab.com/opensavvy/automation/containers/$name", ciContainers, configuration = configuration) // region GitLab @@ -103,10 +103,45 @@ gitlabCi { val test by stage() val deploy by stage() + // region Gradle upgrades + + val experimentalGradleDependencies = System.getenv("upgrade_experimental")?.let { + job("experimentalGradleDependencies", stage = build) { + opensavvyImage("caupain") { + entrypoint = listOf("") + } + + script { + shell("caupain -i gradle/common.versions.toml --in-place --policy=always --no-cache") + shell("caupain -i gradle/libs.versions.toml --in-place --policy=always --no-cache") + } + + artifacts { + name("gradle-catalogs") + include("gradle/common.versions.toml") + include("gradle/libs.versions.toml") + } + } + } + + fun Job.withExperimentalGradleDependenciesIfAvailable() { + if (experimentalGradleDependencies != null) { + dependsOn(experimentalGradleDependencies, artifacts = true) + + beforeScript { + shell("echo THIS JOB IS RUNNING WITH EXPERIMENTAL DEPENDENCIES:") + shell("cat gradle/common.versions.toml") + shell("cat gradle/libs.versions.toml") + } + } + } + + // endregion // region Tests val checkJvm by job(stage = test) { jvm() + withExperimentalGradleDependenciesIfAvailable() script { gradlew.tasks( @@ -139,6 +174,7 @@ gitlabCi { val checkJsBrowser by job(stage = test) { jsBrowser() + withExperimentalGradleDependenciesIfAvailable() script { gradlew.tasks( @@ -152,6 +188,7 @@ gitlabCi { val checkJsNode by job(stage = test) { jsNode() + withExperimentalGradleDependenciesIfAvailable() script { gradlew.tasks( @@ -165,6 +202,7 @@ gitlabCi { val checkLinuxX64 by job(stage = test) { nativeLinuxX64() + withExperimentalGradleDependenciesIfAvailable() script { gradlew.tasks( @@ -178,6 +216,7 @@ gitlabCi { val checkIosArm64 by job(stage = test) { nativeIosArm64() + withExperimentalGradleDependenciesIfAvailable() script { gradlew.tasks( @@ -195,6 +234,7 @@ gitlabCi { val mkdocs by job(stage = build) { opensavvyImage("mkdocs") variable("GIT_DEPTH", "0") + withExperimentalGradleDependenciesIfAvailable() beforeScript { shell("./docs/website/verify-marker.sh") @@ -231,6 +271,7 @@ gitlabCi { val dokka by job(stage = build) { jvm() + withExperimentalGradleDependenciesIfAvailable() script { gradlew.tasks(