Updates to hello world.
This commit is contained in:
1 parent
6a02494ac8
commit
785569abdd
7 files changed
+177
-20
No files matched your search
@@ -1,4 +1,5 @@
|
||||
/hello-world/bin/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
/dist/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
GOCACHE ?= /tmp/cthulhu-go-cache
|
||||
export GOCACHE
|
||||
|
||||
.PHONY: build check
|
||||
.PHONY: build check package
|
||||
|
||||
build:
|
||||
go build -buildvcs=false -mod=readonly -o hello-world/bin/hello-world ./hello-world/src
|
||||
@@ -10,3 +10,6 @@ check: build
|
||||
go vet ./...
|
||||
python3 -B tools/check.py
|
||||
|
||||
package:
|
||||
python3 -B tools/package.py
|
||||
|
||||
@@ -7,10 +7,10 @@ Repository material and Hello World are licensed under GPL-3.0-or-later; see
|
||||
|
||||
`repository.toml` identifies this source. `catalog.toml` explicitly lists its
|
||||
Tentacles, each in a direct top-level folder with its own `tentacle.toml`.
|
||||
The catalog currently contains discovery metadata, with no release artifacts.
|
||||
The proposed source URL is
|
||||
`https://git.stormux.org/storm/cthulhu-tentacles`; it becomes usable after the
|
||||
maintainer creates and publishes the Git repository.
|
||||
The catalog lists verified native packages for Linux amd64 and arm64. Prepared
|
||||
release artifacts live in `dist/`; they become downloadable only after publication.
|
||||
The discovery source URL is
|
||||
`https://git.stormux.org/storm/cthulhu-tentacles`.
|
||||
|
||||
## Build and check
|
||||
|
||||
@@ -29,20 +29,63 @@ Checks validate the TOML metadata, registration and suggested bindings, and
|
||||
invoke Hello World through the actual Cthulhu-Go host. They produce no speech
|
||||
or Braille and leave the running reader alone.
|
||||
|
||||
## Discovery and the upcoming installation workflow
|
||||
## Repository installation
|
||||
|
||||
After publishing this repository, open global Cthulhu Preferences → Tentacles
|
||||
→ Add repository and enter its HTTPS Git URL. Its tab should list Hello World,
|
||||
version 0.1.0, with the description from its manifest.
|
||||
With the updated reader, open global Cthulhu Preferences → Tentacles → Add
|
||||
repository and enter the HTTPS Git URL above. Refresh an already added source.
|
||||
Select Hello World and press Space to review its source/version and requested
|
||||
speech/Braille access, then **Install and enable**. **Install** instead downloads
|
||||
and saves the package disabled. The reader verifies the catalog's SHA-256 digest,
|
||||
package identity and native architecture before saving a launch entry. Catalogs
|
||||
without a published compatible release show a clear message and remain unchecked.
|
||||
No source builds or install scripts run during this workflow. Resource limits
|
||||
do not make untrusted same-user programs safe.
|
||||
|
||||
The current reader validates and displays repository catalogs. It does not
|
||||
yet install or build a Tentacle from a catalog. Manifest launch/runtime/API
|
||||
fields document this package for the next installation slice; the current
|
||||
discovery parser does not interpret them. There is no invented download URL,
|
||||
release digest, or automatic installation step here.
|
||||
After installation, refresh status until Active and use Cthulhu+Alt+Shift+H.
|
||||
Disable retains the package; re-enabling and reader startup use installed files
|
||||
without network access. Removing the source retains installed Tentacles. Removing
|
||||
a managed Tentacle stops it and deletes its package files after shutdown.
|
||||
Package updates are not implemented in this slice. See the
|
||||
[Hello World live checks](hello-world/README.md#live-verification).
|
||||
|
||||
For local execution before installation is implemented, see the explicit
|
||||
[Hello World launch procedure](hello-world/README.md). Future publishing should
|
||||
add immutable artifacts and verified digests only once the reader has a defined
|
||||
installation contract.
|
||||
## Prepare and publish packages
|
||||
|
||||
```sh
|
||||
make check
|
||||
make package
|
||||
```
|
||||
|
||||
`tools/package.py` cross-builds statically linked native binaries for Linux amd64
|
||||
and arm64 from the matching adjacent SDK. It creates deterministic archives
|
||||
containing `tentacle.toml`, `bin/hello-world`, `README.md` and `LICENSE`, plus
|
||||
`dist/SHA256SUMS` and a generated `dist/catalog.toml`. Go builds use readonly
|
||||
module metadata, trim paths and omit VCS stamping. To build one architecture:
|
||||
|
||||
```sh
|
||||
python3 -B tools/package.py --architecture amd64
|
||||
```
|
||||
|
||||
Validate the actual host-architecture package through Cthulhu-Go's installer
|
||||
and command host, without changing the running reader:
|
||||
|
||||
```sh
|
||||
cd ../cthulhu-go
|
||||
CTHULHU_TENTACLE_RELEASE_ROOT=../cthulhu-tentacles GOCACHE=/tmp/cthulhu-go-cache go test ./internal/tentacle -run '^TestBuiltHelloWorldPackageThroughHost$' -count=1 -v
|
||||
```
|
||||
|
||||
Before publication, review both repositories' changes and contributing guides.
|
||||
Commit the reviewed source with the matching SDK available; select that source
|
||||
revision for the `hello-world-v0.1.0` release. In the Git hosting release page,
|
||||
upload `dist/hello-world-0.1.0-linux-amd64.tar.gz`,
|
||||
`dist/hello-world-0.1.0-linux-arm64.tar.gz` and `dist/SHA256SUMS`. Publish and verify
|
||||
the download URLs and digests **before** publishing the matching catalog change.
|
||||
Copy the reviewed `dist/catalog.toml` to `catalog.toml`, review the diff, and
|
||||
submit/push it explicitly. A release filename/version must never be reused for
|
||||
changed content; bump the version before preparing a later release.
|
||||
|
||||
The package command creates local artifacts only. It does not create commits,
|
||||
releases, tags, uploads or pushes. Prepared catalog changes are not evidence that
|
||||
the corresponding release is already available. Live shortcut, speech, Braille,
|
||||
lock/handoff and interruption checks remain necessary after publication and an
|
||||
explicit reader restart. For source-only local testing, the development launch
|
||||
procedure remains in [Hello World](hello-world/README.md#local-launch).
|
||||
@@ -4,3 +4,14 @@ format-version = 1
|
||||
id = "hello-world"
|
||||
manifest = "hello-world/tentacle.toml"
|
||||
|
||||
[[tentacles.releases]]
|
||||
platform = "linux"
|
||||
architecture = "amd64"
|
||||
url = "https://git.stormux.org/storm/cthulhu-tentacles/releases/download/hello-world-v0.1.0/hello-world-0.1.0-linux-amd64.tar.gz"
|
||||
sha256 = "2bad533bc217a5b1bd374115f6151da2a1f6e4ccdbdc93528a5a783f0518f8cd"
|
||||
|
||||
[[tentacles.releases]]
|
||||
platform = "linux"
|
||||
architecture = "arm64"
|
||||
url = "https://git.stormux.org/storm/cthulhu-tentacles/releases/download/hello-world-v0.1.0/hello-world-0.1.0-linux-arm64.tar.gz"
|
||||
sha256 = "9ef956a04fb1fa98ac01b04fadc122f92b77d708440e0438a7451da62078a9d4"
|
||||
@@ -20,6 +20,14 @@ Hello World requests presentation access only. It receives no focused text,
|
||||
uses no network services, and stores no settings. Source and distribution are
|
||||
licensed under GPL-3.0-or-later; see [LICENSE](LICENSE).
|
||||
|
||||
## Repository installation
|
||||
|
||||
Refresh the source in global Preferences → Tentacles. Space on Hello World
|
||||
opens first-use review and installs/enables the package after acceptance.
|
||||
**Install** saves it disabled instead. The release must be published at the
|
||||
catalog URL; building locally alone does not make it downloadable. Refresh
|
||||
status until Active before trying the shortcut.
|
||||
|
||||
## Local launch
|
||||
|
||||
Run `make build` from the repository root. Rebuild Cthulhu-Go with the matching
|
||||
@@ -72,7 +80,7 @@ Resource limits do not make untrusted same-user programs safe.
|
||||
5. Check speech off/beeps and disabled Braille settings. Hello World must respect
|
||||
them. Remap or occupy the suggested binding and check core/user precedence.
|
||||
|
||||
Audible speech, physical shortcuts, actual display output and the eventual
|
||||
Audible speech, physical shortcuts, actual display output and the
|
||||
repository-installation workflow require these live checks; protocol tests do
|
||||
not establish them.
|
||||
|
||||
+21
-1
@@ -3,11 +3,13 @@
|
||||
"""Check the repository and the built Tentacle without running a reader."""
|
||||
|
||||
import json
|
||||
import hashlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import select
|
||||
import subprocess
|
||||
import tomllib
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
@@ -27,7 +29,8 @@ def check_metadata(repoRoot):
|
||||
"Unsupported metadata format")
|
||||
require(repository["id"] == "storm.cthulhu-tentacles" and repository["name"],
|
||||
"Repository identity is missing")
|
||||
require(catalog["tentacles"] == [{"id": "hello-world", "manifest": "hello-world/tentacle.toml"}],
|
||||
require(len(catalog["tentacles"]) == 1 and catalog["tentacles"][0]["id"] == "hello-world"
|
||||
and catalog["tentacles"][0]["manifest"] == "hello-world/tentacle.toml",
|
||||
"Catalog must list exactly Hello World")
|
||||
manifest = read_toml(repoRoot / catalog["tentacles"][0]["manifest"])
|
||||
require(manifest["format-version"] == 1 and manifest["id"] == "hello-world"
|
||||
@@ -38,6 +41,23 @@ def check_metadata(repoRoot):
|
||||
require((repoRoot / "LICENSE").is_file() and (repoRoot / "hello-world/LICENSE").is_file(),
|
||||
"Repository and Tentacle licenses are required")
|
||||
|
||||
seen = set()
|
||||
for release in catalog["tentacles"][0].get("releases", []):
|
||||
key = (release["platform"], release["architecture"])
|
||||
require(key not in seen and key[0] == "linux" and key[1] in ("amd64", "arm64"),
|
||||
"Invalid or duplicate release target")
|
||||
seen.add(key)
|
||||
parsed = urlparse(release["url"])
|
||||
require(parsed.scheme == "https" and parsed.hostname and not parsed.username
|
||||
and not parsed.fragment, "Release URL must be HTTPS without credentials")
|
||||
digest = release["sha256"]
|
||||
require(len(digest) == 64 and all(character in "0123456789abcdef" for character in digest),
|
||||
"Invalid SHA-256 digest")
|
||||
artifactPath = repoRoot / "dist" / parsed.path.rsplit("/", 1)[-1]
|
||||
if artifactPath.exists():
|
||||
require(hashlib.sha256(artifactPath.read_bytes()).hexdigest() == digest,
|
||||
"Prepared package does not match its catalog digest")
|
||||
|
||||
|
||||
def check_registration(programPath):
|
||||
with subprocess.Popen([str(programPath)], stdin=subprocess.PIPE,
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# Copyright (c) 2026 Storm Dragon
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
"""Build reproducible Hello World release artifacts and a catalog for review."""
|
||||
|
||||
import argparse
|
||||
import gzip
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tarfile
|
||||
import tomllib
|
||||
|
||||
|
||||
def build_package(repoRoot, architecture, version):
|
||||
distRoot = repoRoot / "dist"
|
||||
distRoot.mkdir(exist_ok=True)
|
||||
programPath = distRoot / f"hello-world-linux-{architecture}"
|
||||
environment = dict(os.environ, CGO_ENABLED="0", GOOS="linux", GOARCH=architecture)
|
||||
environment.setdefault("GOCACHE", "/tmp/cthulhu-go-cache")
|
||||
subprocess.run(["go", "build", "-buildvcs=false", "-mod=readonly", "-trimpath",
|
||||
"-ldflags=-s -w", "-o", str(programPath), "./hello-world/src"],
|
||||
cwd=repoRoot, env=environment, check=True)
|
||||
artifactPath = distRoot / f"hello-world-{version}-linux-{architecture}.tar.gz"
|
||||
with artifactPath.open("wb") as output:
|
||||
with gzip.GzipFile(filename="", mode="wb", fileobj=output, mtime=0) as compressed:
|
||||
with tarfile.open(fileobj=compressed, mode="w", format=tarfile.USTAR_FORMAT) as archive:
|
||||
for name, data, mode in [
|
||||
("tentacle.toml", (repoRoot / "hello-world/tentacle.toml").read_bytes(), 0o644),
|
||||
("README.md", (repoRoot / "hello-world/README.md").read_bytes(), 0o644),
|
||||
("LICENSE", (repoRoot / "hello-world/LICENSE").read_bytes(), 0o644),
|
||||
("bin/hello-world", programPath.read_bytes(), 0o755),
|
||||
]:
|
||||
member = tarfile.TarInfo(name)
|
||||
member.size, member.mode, member.mtime = len(data), mode, 0
|
||||
archive.addfile(member, io.BytesIO(data))
|
||||
digest = hashlib.sha256(artifactPath.read_bytes()).hexdigest()
|
||||
return artifactPath, digest
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--architecture", nargs="+", choices=["amd64", "arm64"], default=["amd64", "arm64"])
|
||||
args = parser.parse_args()
|
||||
if len(set(args.architecture)) != len(args.architecture):
|
||||
parser.error("Architectures must not be repeated")
|
||||
repoRoot = Path(__file__).resolve().parents[1]
|
||||
manifest = tomllib.loads((repoRoot / "hello-world/tentacle.toml").read_text())
|
||||
version = manifest["version"]
|
||||
if not version or any(character not in "0123456789abcdefghijklmnopqrstuvwxyz.-" for character in version):
|
||||
raise ValueError("Version must be safe for release filenames")
|
||||
lines = ["format-version = 1", "", "[[tentacles]]", 'id = "hello-world"',
|
||||
'manifest = "hello-world/tentacle.toml"']
|
||||
checksums = []
|
||||
for architecture in args.architecture:
|
||||
artifactPath, digest = build_package(repoRoot, architecture, version)
|
||||
releaseURL = f"https://git.stormux.org/storm/cthulhu-tentacles/releases/download/hello-world-v{version}/{artifactPath.name}"
|
||||
lines += ["", "[[tentacles.releases]]", 'platform = "linux"',
|
||||
f"architecture = {json.dumps(architecture)}", f"url = {json.dumps(releaseURL)}",
|
||||
f"sha256 = {json.dumps(digest)}"]
|
||||
checksums.append(f"{digest} {artifactPath.name}")
|
||||
print(f"Prepared {artifactPath.name}: {digest}")
|
||||
(repoRoot / "dist/catalog.toml").write_text("\n".join(lines) + "\n")
|
||||
(repoRoot / "dist/SHA256SUMS").write_text("\n".join(checksums) + "\n")
|
||||
print("Prepared dist/catalog.toml and dist/SHA256SUMS for review. Nothing was published.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user