Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ name: android
on:
push:
branches: [main]
# a release tag publishes the Maven artifacts (see the `publish` job)
tags: ['v*']
paths:
- 'android/**'
- '.github/workflows/android.yml'
Expand Down Expand Up @@ -82,3 +84,34 @@ jobs:
sleep 8
adb logcat -d AndroidRuntime:E '*:S' | tee /tmp/crash.log
test ! -s /tmp/crash.log || { echo "the sample crashed on the emulator"; exit 1; }

# Publish the Kotlin artifacts to GitHub Packages on a release tag, so a single `git tag vX.Y.Z`
# releases every platform at one version: release.yml publishes npm, SPM resolves the Swift tag,
# and this publishes com.fundamental:{fundamental-core,fundamental-compose}:X.Y.Z. The version is
# derived from the tag (-PreleaseVersion), never hardcoded, and auth uses the Actions GITHUB_TOKEN
# — no personal token, no laptop publish.
publish:
name: publish maven (release tag)
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- name: set up Android SDK
uses: android-actions/setup-android@v3
- name: publish core + compose to GitHub Packages
working-directory: android
env:
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${GITHUB_REF_NAME#v}"
echo "publishing com.fundamental:*:$VERSION from tag $GITHUB_REF_NAME"
./gradlew :fundamental-core:publish :fundamental-compose:publish -PreleaseVersion="$VERSION"
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ a git tag (see [RELEASING.md](RELEASING.md)).

## [Unreleased]

- **Android artifacts publish from CI on a release tag, at a tag-derived version.** `android.yml` gains a `publish` job (`if: refs/tags/v*`, `packages: write`, Actions `GITHUB_TOKEN` — no personal token) that runs `:fundamental-core:publish :fundamental-compose:publish`. The version is derived from the tag via `-PreleaseVersion` and defaults to a `SNAPSHOT` locally — the hardcoded `version = "0.9.5"` is gone, so a publish can never silently overwrite a release with different code. One `git tag vX.Y.Z` now releases every plane at one version: npm via `release.yml`, Swift via the SPM tag, Kotlin via this. Publication config verified against the local Maven repo before merge.
- **Positioning made consistent site-wide.** The homepage rewrite changed the hero, title and description, but the footer — which renders on *every* page — still read "a readable behavior layer for host objects", so the homepage contradicted itself on the same screen. The `Base.astro` default title carried it too. Both now say "a physics engine for interfaces". The only surviving instance is the changelog entry above, which quotes the old phrase to explain why it was retired; historical records that cite a former term are left intact.

- **Finished retiring the freeze vocabulary across `docs/canonical/`.** The earlier change corrected the authoritative sources but left the wording in nine other canonical documents, where "the freeze contract" and "the frozen surface" still described a promise the project had stopped making. All now say *protected* / *removal-protection*. Four uses of the word are deliberately untouched because they mean something else entirely — `Object.freeze`'d policy clones, "freeze the sim" for reduced motion, "frozen particles" in the poster render mode, and "frozen design history" for the planning archive. A pattern-matched sweep would have broken all four.
Expand Down
1 change: 1 addition & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ build/
.idea/
*.iml
local.properties
gpr.key
12 changes: 12 additions & 0 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,15 @@ plugins {
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
id("org.jetbrains.kotlin.plugin.compose") version "2.1.0" apply false
}

// Coordinates for the published Android/JVM artifacts (GitHub Packages). Mirrors the
// npm scope @fundamental-engine and the Swift package products.
//
// The version is DERIVED, never typed: CI passes -PreleaseVersion=<tag without the v> on a
// release tag, so the published version always equals the git tag and can never silently
// overwrite a prior release with different code. A local build with no property is a SNAPSHOT,
// which GitHub Packages will not mistake for a release.
subprojects {
group = "com.fundamental"
version = (findProperty("releaseVersion") as String?) ?: "0.0.0-SNAPSHOT"
}
15 changes: 15 additions & 0 deletions android/fundamental-compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
`maven-publish`
}

android {
publishing { singleVariant("release") }
namespace = "com.fundamental.compose"
compileSdk = 34
buildToolsVersion = "34.0.0"
Expand Down Expand Up @@ -42,3 +44,16 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7")
implementation("androidx.core:core-ktx:1.13.1")
}

// ── Publishing ──────────────────────────────────────────────────────────────
apply(from = rootProject.file("gradle/github-packages.gradle.kts"))
afterEvaluate {
publishing {
publications {
create<MavenPublication>("release") {
from(components["release"]) // AGP's release AAR + POM (transitive core dep included)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Export Compose API dependencies from the AAR

Publishing components["release"] makes Gradle publish the release variant with this module's api/implementation separation. In the inspected Compose API, FieldView/Modifier.fieldBody expose @Composable, Modifier, Color, and LayoutCoordinates (FieldView.kt:78, 83-89, 262-263), but the corresponding Compose UI/runtime BOM/deps remain implementation, so a downstream app that follows the new coordinates and declares only com.fundamental:fundamental-compose will not get those classes on its compile classpath. Move the public Compose dependencies (and BOM constraint) to api or the published artifact is not self-contained.

Useful? React with 👍 / 👎.

artifactId = "fundamental-compose"
}
}
}
}
12 changes: 12 additions & 0 deletions android/fundamental-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
kotlin("jvm")
kotlin("plugin.serialization")
`maven-publish`
}

dependencies {
Expand Down Expand Up @@ -86,3 +87,14 @@ sourceSets.main {
tasks.named<ProcessResources>("processResources") {
dependsOn(syncRecipes)
}

// ── Publishing ──────────────────────────────────────────────────────────────
apply(from = rootProject.file("gradle/github-packages.gradle.kts"))
publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
artifactId = "fundamental-core"
}
}
}
23 changes: 23 additions & 0 deletions android/gradle/github-packages.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Shared GitHub Packages target. Applied by the modules we publish (core, compose).
// Credentials come from Gradle properties, android/gpr.key, or the environment so
// nothing secret is committed:
// gpr.user/gpr.key, GITHUB_ACTOR (defaults to repo owner), GITHUB_TOKEN.
// Uses configure<PublishingExtension> rather than the `publishing { }` accessor,
// which is not generated for scripts applied via apply(from = …).
val gprKeyFromFile = rootProject.rootDir.resolve("gpr.key")
.takeIf { it.exists() }
?.readText()
?.trim()
?.takeIf { it.isNotEmpty() }
configure<org.gradle.api.publish.PublishingExtension> {
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/zachshallbetter/fundamental-engine")
credentials {
username = (findProperty("gpr.user") as String?) ?: System.getenv("GITHUB_ACTOR") ?: "zachshallbetter"
password = (findProperty("gpr.key") as String?) ?: gprKeyFromFile ?: System.getenv("GITHUB_TOKEN")
}
}
}
}
Loading