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
14 changes: 14 additions & 0 deletions .github/workflows/developer-guide-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ jobs:
echo "REV_HUMAN_DATE=$REV_HUMAN_DATE"
} >> "$GITHUB_ENV"

- name: Determine Codename One release version
run: |
set -euo pipefail
VERSION="$(python3 scripts/developer-guide/determine_release_version.py)"
if [ -z "$VERSION" ]; then
echo "Unable to determine Codename One release version" >&2
exit 1
fi
echo "Using Codename One release version: $VERSION" >&2
{
echo "CN1_RELEASE_VERSION=$VERSION"
echo "CN1_PLUGIN_RELEASE_VERSION=$VERSION"
} >> "$GITHUB_ENV"

- name: Render publication cover artwork
run: |
set -euo pipefail
Expand Down
2 changes: 1 addition & 1 deletion docs/developer-guide/About-This-Guide.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ While this guide focuses on tutorial and conceptual material, the complete API r

This document includes content from multiple authors and community wiki edits. If you edit pages within the guide feel free to add your name here alphabetized by surname:

- https://github.com/codenameone/[Shai Almog]
- https://github.com/shai-almog[Shai Almog]
- https://github.com/Isborg[Ismael Baum]
- https://twitter.com/ericcoolmandev[Eric Coolman]
- http://github.com/chen-fishbein/[Chen Fishbein]
Expand Down
2 changes: 2 additions & 0 deletions docs/developer-guide/Index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ IMPORTANT: Codename One doesn't send source code to the build cloud, only compil

The build servers allow building native iOS Apps without a Mac and native Windows apps without a Windows machine. They remove the need to install/update complex toolchains and simplify the process of building a native app to a right click.

Even though the build servers streamline delivery, Codename One also supports fully local builds. You can install the toolchain on your own hardware and follow the workflows in <<maven-project-workflow>> and <<working-with-codename-one-sources>> to compile, package, and test apps without leaving your desktop environment.

E.g.: Since building native iOS applications requires a Mac OS X machine with a recent version of xcode Codename One maintains such machines in the cloud. When developers send an iOS build such a Mac will be used to generate C source code using https://github.com/codenameone/CodenameOne/tree/master/vm[ParparVM] and it will then compile the C source code using xcode & sign the resulting binary using xcode. You can install the binary to your device or build a distribution binary for the appstore. Since C code is generated it also means that your app will be "future proof" in a case of changes from Apple. You can also inject Objective-C native code into the app while keeping it 100% portable thanks to the "native interfaces" capability of Codename One.

Subscribers can receive the C source code back using the include sources feature of Codename One and use those sources for benchmarking, debugging on devices etc.
Expand Down
16 changes: 8 additions & 8 deletions docs/developer-guide/Maven-Getting-Started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ The https://shannah.github.io/cn1app-archetype-kotlin-template/getting-started.h

Here is an example which generates a project based on the bare-bones kotlin template:

[source,bash]
[source,bash,subs="+attributes"]
----
mvn com.codenameone:codenameone-maven-plugin:7.0.19:generate-app-project \
mvn com.codenameone:codenameone-maven-plugin:{cn1-plugin-release-version}:generate-app-project \
-DarchetypeGroupId=$archetypeGroupId \
-DarchetypeArtifactId=$archetypeArtifactId \
-DarchetypeVersion=$archetypeVersion \
Expand All @@ -96,7 +96,7 @@ Like the `archetype:generate` goal, this will create the project in a directory

Some notes here:

. The `com.codenameone:codenameone-maven-plugin:7.0.19:generate-app-project` argument is the fully-qualified goal name for the `generate-app-project`. This is necessary since we aren't running this goal in the context of any existing project. You should adjust the version number (`7.0.19`) to reflect the https://search.maven.org/search?q=a:codenameone-maven-plugin[latest available Codename One version on Maven Central].
. The `com.codenameone:codenameone-maven-plugin:{cn1-plugin-release-version}:generate-app-project` argument is the fully-qualified goal name for the `generate-app-project`. This is necessary since we aren't running this goal in the context of any existing project. You should adjust the version number (`{cn1-plugin-release-version}`) to reflect the https://search.maven.org/search?q=a:codenameone-maven-plugin[latest available Codename One version on Maven Central].
. The `archetypeGroupId`, `archetypeArtifactId`, and `archetypeVersion` parameters are the same as when using the `archetype:generate` goal, and they will (almost) always refer to the <<cn1app-archetype>>.
. The `groupId`, `artifactId`, and `version` work the same as for the `archetype:generate` goal. That is, that they specify the coordinates for your newly created project.
. The `mainName` specifies the Main class name for your app. This is just the class name, and should not include the full package. E.g. "MyApp", not "com.example.MyApp"
Expand All @@ -116,12 +116,12 @@ If you have an existing Codename One application project that uses the old Ant p

A minimal invocation of this goal would look like:

[source,bash]
[source,bash,subs="+attributes"]
----
# Specify your the version of the codenameone-maven-plugin.
# Find the latest version at
# https://search.maven.org/search?q=a:codenameone-maven-plugin
CN1VERSION=7.0.19
CN1VERSION={cn1-plugin-release-version}
mvn com.codenameone:codenameone-maven-plugin:$CN1VERSION:generate-app-project \
-DgroupId=YOUR_GROUP_ID \
-DartifactId=YOUR_ARTIFACT_ID \
Expand All @@ -137,7 +137,7 @@ After building the project, try running it to make sure that the migration worke

==== Command Line

[source,bash]
[source,bash,subs="+attributes"]
----
cd myapp
./run.sh
Expand Down Expand Up @@ -210,9 +210,9 @@ Let's consider a concrete example, now. Download the KitchenSink Ant project fr

The following is a bash script that uses curl to download this project as a zip file, and then converts it to a fully-functional Maven project.

[source,bash]
[source,bash,subs="+attributes"]
----
CN1_VERSION=7.0.19
CN1_VERSION={cn1-plugin-release-version}
curl -L https://github.com/codenameone/KitchenSink/archive/v1.0-cn7.0.11.zip > master.zip
unzip master.zip
rm master.zip
Expand Down
7 changes: 2 additions & 5 deletions docs/developer-guide/Maven-Project-Workflow.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,5 @@ include::Maven-Getting-Started.adoc[leveloffset=+1]
include::Maven-Updating-Codename-One.adoc[leveloffset=+1]
include::Maven-Project-Templates.adoc[leveloffset=+1]
include::Maven-Creating-CN1Libs.adoc[leveloffset=+1]
include::Maven-Appendix-Archetypes.adoc[leveloffset=+1]
include::Maven-Appendix-Goals.adoc[leveloffset=+1]
include::Maven-Appendix-API.adoc[leveloffset=+1]
include::Maven-Appendix-Control-Center.adoc[leveloffset=+1]
include::Maven-Appendix-Rich-Properties.adoc[leveloffset=+1]

// The detailed Maven appendices now live alongside the other appendices at the end of the guide.
6 changes: 3 additions & 3 deletions docs/developer-guide/Maven-Updating-Codename-One.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ You can also update your Codename One dependencies manually by modifying the `cn

E.g. Open the `pom.xml` file, and look for the following:

[source,xml]
[source,xml,subs="+attributes"]
----
<cn1.plugin.version>7.0.19</cn1.plugin.version>
<cn1.version>7.0.19</cn1.version>
<cn1.plugin.version>{cn1-plugin-release-version}</cn1.plugin.version>
<cn1.version>{cn1-release-version}</cn1.version>
----

Change these values to reflect the latest version of the `codenameone-maven-plugin` found https://search.maven.org/artifact/com.codenameone/codenameone-maven-plugin[here].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ project), adjust the `pom.xml` properties to reference your snapshot version:
----
<properties>
<!-- Replace with the snapshot printed during mvn install -->
<cn1.version>7.0.21-SNAPSHOT</cn1.version>
<cn1.plugin.version>7.0.21-SNAPSHOT</cn1.plugin.version>
<cn1.version>{cn1-snapshot-version}</cn1.version>
<cn1.plugin.version>{cn1-snapshot-version}</cn1.plugin.version>
</properties>
----

Expand Down
30 changes: 17 additions & 13 deletions docs/developer-guide/developer-guide.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@
:copyright: Codename One, all rights reserved
:publication-type: book
:producer: Codename One Ltd.
:partnums:
:cn1-release-version: 7.0.210
ifdef::env-CN1_RELEASE_VERSION[:cn1-release-version: {env:CN1_RELEASE_VERSION}]

:cn1-plugin-release-version: {cn1-release-version}
ifdef::env-CN1_PLUGIN_RELEASE_VERSION[:cn1-plugin-release-version: {env:CN1_PLUGIN_RELEASE_VERSION}]

:cn1-snapshot-version: {cn1-release-version}-SNAPSHOT

= {doctitle}
{author}
Expand All @@ -37,12 +43,8 @@ toc::[]

include::About-This-Guide.asciidoc[]

= Part I. Project Setup

include::Maven-Project-Workflow.asciidoc[]

= Part II. Foundations

include::Index.asciidoc[]

include::basics.asciidoc[]
Expand All @@ -53,8 +55,6 @@ include::Advanced-Theming.asciidoc[]

include::css.asciidoc[]

= Part III. User Interface and Experience

include::The-Components-Of-Codename-One.asciidoc[]

include::Animations.asciidoc[]
Expand All @@ -63,8 +63,6 @@ include::The-EDT---Event-Dispatch-Thread.asciidoc[]

include::graphics.asciidoc[]

= Part IV. Application Services

include::Events.asciidoc[]

include::io.asciidoc[]
Expand All @@ -77,8 +75,6 @@ include::performance.asciidoc[]

include::Monetization.asciidoc[]

= Part V. Platform and Deployment

include::Advanced-Topics-Under-The-Hood.asciidoc[]

include::security.asciidoc[]
Expand All @@ -91,10 +87,18 @@ include::Working-With-Javascript.asciidoc[]

include::Working-with-Mac-OS-X.asciidoc[]

= Part VI. Contributing and Appendices

include::Working-With-CodenameOne-Sources.asciidoc[]

include::Maven-Appendix-Archetypes.adoc[]

include::Maven-Appendix-Goals.adoc[]

include::Maven-Appendix-API.adoc[]

include::Maven-Appendix-Control-Center.adoc[]

include::Maven-Appendix-Rich-Properties.adoc[]

= Historical Reference

include::Working-with-UWP.asciidoc[]
Expand Down
159 changes: 159 additions & 0 deletions scripts/developer-guide/determine_release_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#!/usr/bin/env python3
"""Determine the current Codename One release version for documentation builds."""
from __future__ import annotations

import json
import os
import re
import subprocess
import sys
import xml.etree.ElementTree as ET
from pathlib import Path
from typing import Iterable, List
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen


VERSION_PATTERN = re.compile(r"\d+(?:\.\d+)*$")


def _sanitize_tag(value: str) -> str:
value = value.strip()
if value.lower().startswith("refs/tags/"):
value = value[10:]
if value.lower().startswith("tags/"):
value = value[5:]
if value and value[0] in {"v", "V"} and value[1:2].isdigit():
value = value[1:]
return value.strip()


def _looks_like_version(tag: str) -> bool:
return bool(tag and VERSION_PATTERN.fullmatch(tag))


def _parse_version_components(version: str) -> List[int]:
return [int(part) for part in version.split(".")]


def release_tag_from_event() -> str:
event_path = os.environ.get("GITHUB_EVENT_PATH")
if event_path:
event_file = Path(event_path)
if event_file.is_file():
try:
data = json.loads(event_file.read_text())
except json.JSONDecodeError:
data = {}
release = data.get("release") or {}
tag = release.get("tag_name") or release.get("target_commitish") or ""
if tag:
sanitized = _sanitize_tag(tag)
if _looks_like_version(sanitized):
return sanitized
for key in ("GITHUB_REF_NAME", "GITHUB_REF"):
value = os.environ.get(key)
if value:
sanitized = _sanitize_tag(value)
if _looks_like_version(sanitized):
return sanitized
return ""


def latest_release_from_api() -> str:
repository = os.environ.get("GITHUB_REPOSITORY")
if not repository:
return ""
api_base = os.environ.get("GITHUB_API_URL", "https://api.github.com")
url = f"{api_base.rstrip('/')}/repos/{repository}/releases/latest"
headers = {
"Accept": "application/vnd.github+json",
"User-Agent": "codenameone-docs-release-version",
}
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
if token:
headers["Authorization"] = f"Bearer {token}"
request = Request(url, headers=headers)
try:
with urlopen(request, timeout=10) as response:
if response.status != 200:
return ""
try:
payload = json.load(response)
except json.JSONDecodeError:
return ""
except (HTTPError, URLError, TimeoutError):
return ""
tag = payload.get("tag_name")
if not tag:
return ""
return _sanitize_tag(str(tag))


def latest_git_tag() -> str:
try:
subprocess.run(
["git", "fetch", "--tags", "--force"],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
except (subprocess.CalledProcessError, FileNotFoundError):
pass
try:
result = subprocess.run(
["git", "tag", "--list", "v*"],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
except (subprocess.CalledProcessError, FileNotFoundError):
return ""
tags: Iterable[str] = (_sanitize_tag(line) for line in result.stdout.splitlines())
numeric_tags = [tag for tag in tags if re.fullmatch(r"\d+(?:\.\d+)*", tag)]
if not numeric_tags:
return ""
numeric_tags.sort(key=_parse_version_components)
return numeric_tags[-1]


def version_from_pom(root: Path) -> str:
pom_path = root / "maven" / "pom.xml"
if not pom_path.is_file():
return ""
try:
tree = ET.parse(pom_path)
except ET.ParseError:
return ""
namespace = {"mvn": "http://maven.apache.org/POM/4.0.0"}
version_element = tree.getroot().find("mvn:version", namespace)
if version_element is None:
return ""
version = (version_element.text or "").strip()
if not version:
return ""
if version.endswith("-SNAPSHOT"):
version = version[: -len("-SNAPSHOT")]
return version


def main() -> int:
repo_root = Path(__file__).resolve().parents[2]

for candidate in (release_tag_from_event, latest_release_from_api, latest_git_tag):
version = candidate()
if version:
print(version)
return 0

version = version_from_pom(repo_root)
if version:
print(version)
return 0

return 1


if __name__ == "__main__":
sys.exit(main())