Phase 6: Gitea-Cross-Builds, Paketprüfung und gesperrten Releasepfad implementieren
Some checks failed
Vierziel-Build und Pflichtabnahme / checks (push) Has been cancelled
Vierziel-Build und Pflichtabnahme / build (ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b, aarch64-apple-darwin) (push) Has been cancelled
Vierziel-Build und Pflichtabnahme / build (ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b, aarch64-unknown-linux-gnu) (push) Has been cancelled
Vierziel-Build und Pflichtabnahme / build (ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b, x86_64-unknown-linux-gnu) (push) Has been cancelled
Vierziel-Build und Pflichtabnahme / build (messense/cargo-xwin@sha256:4696dd4e79edf8569fa99c4b06bd99273e0501c7adc983aa61d57945f795bef0, x86_64-pc-windows-msvc) (push) Has been cancelled
Vierziel-Build und Pflichtabnahme / stage (push) Has been cancelled

This commit is contained in:
2026-09-07 21:50:05 +02:00
parent 796564795a
commit 32d3838002
40 changed files with 3134 additions and 11 deletions

23
.gitea/INSTALL.txt Normal file
View File

@@ -0,0 +1,23 @@
Terminal Basic — Terminalanwendung
Archiv in ein eigenes Verzeichnis entpacken. tb und tbc (Windows: .exe)
bleiben neben dem Verzeichnis runtimes/<Target-Triple>/ mit tbrt und tbrt.meta
(Windows: tbrt.exe bzw. tbrt.exe.meta). Diese Struktur zusammen aufbewahren.
IDE: ./tb
Windows: .\tb.exe
Ein interaktives Terminal mit RGB-Farben und mindestens 80x25 Zellen ist nötig.
Beispiel hello.bas: PRINT "Hallo" : END
./tbc check hello.bas
./tbc build hello.bas --exe --target <Target-Triple> -o hello
./hello
Windows: tbc.exe und hello.exe verwenden. Die Vorlage wird automatisch gefunden.
Target-Triple steht in manifest.json. BASIC-Erzeugung/Linken benötigt keinen
C-/Rust-Compiler oder nativen Linker. Auf macOS muss /usr/bin/codesign für die
lokale Finalisierung verfügbar sein. Das exportierte Executable enthält die
Runtime; benötigte eigene Datendateien liefert das Anwenderprogramm separat.
Die Pakete sind nicht Developer-ID-/Authenticode-signiert. OS-Vertrauens-
prüfungen bei heruntergeladenen Dateien und Terminalfunktionen bleiben Teil
der Zielabnahme. Build-Baselines sind keine gemessenen minimalen OS-Versionen;
verifizierte Systeme und Einschränkungen stehen im beigefügten Releasenachweis.

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python3
"""Pflichtabnahme mit fixiertem Fremdbestand und zugeordneter Runner-Messung."""
import json
import os
from pathlib import Path
import platform
import subprocess
import sys
import tempfile
import distribution as dist
output = Path('acceptance')
output.mkdir()
revision = subprocess.check_output(['git', 'rev-parse', 'HEAD'], text=True).strip()
report = dict(revision=revision, passed=False, buildhost=platform.platform(),
run_url=os.environ.get('TB_RUN_URL', ''), foreign=False, inventory=False,
workspace=False, benchmarks=False, native_ide=False)
try:
repo = Path(os.environ['TB_VBDOS_REPO'])
with (output / 'acceptance.log').open('wb') as log:
dist.run([sys.executable, dist.ROOT / 'tests/support/release-abnahme.py', '--vbdos-repo', repo],
stdout=log, stderr=subprocess.STDOUT)
with tempfile.TemporaryDirectory(prefix='tb-ci-runtime-') as temporary:
runtime = Path(temporary) / 'runtime'
with (output / 'native-ide.log').open('wb') as log:
dist.run([sys.executable, dist.ROOT / 'tests/support/build-runtime.py',
'--target', dist.HOSTS[(platform.system(), platform.machine())],
'--output', runtime / dist.HOSTS[(platform.system(), platform.machine())]],
stdout=log, stderr=subprocess.STDOUT)
dist.run(['cargo', 'test', '--locked', '-p', 'tb-cli', '--bin', 'tbc',
'ide_acceptance::real_native_ide_exports_and_source_free_cli_library_consumer',
'--', '--exact', '--ignored', '--nocapture'],
env=dict(os.environ, TB_IDE_RUNTIME_DIR=str(runtime)), stdout=log, stderr=subprocess.STDOUT)
report.update(passed=True, native_ide=True, foreign=True, inventory=True, workspace=True, benchmarks=True)
finally:
report['log_sha256'] = dist.digest(output / 'acceptance.log') if (output / 'acceptance.log').exists() else None
(output / 'acceptance.json').write_text(json.dumps(report, indent=2) + '\n')

View File

@@ -0,0 +1,13 @@
#!/bin/sh
set -eu
[ "$(uname -sm)" = "Linux aarch64" ] || { echo 'Linux-arm64-Buildhost erforderlich' >&2; exit 1; }
rustup toolchain install 1.97.1 --profile minimal --component clippy --component rustfmt
# Beide per Digest fixierten Cross-Images enthalten Python, Curl, Git und SDK/Clang.
# Separater fester 7-Zip-Download, kein stiller Ersatz durch ZIP oder tar.
curl --fail --location --silent --show-error https://www.7-zip.org/a/7z2501-linux-arm64.tar.xz -o /tmp/tb-7zip.tar.xz
printf '%s %s\n' 39c5140f02ce4436599303c59a149f654cb1bbc47cdc105a942120d747ae040d /tmp/tb-7zip.tar.xz | sha256sum -c -
mkdir -p /tmp/tb-7zip
tar -xJf /tmp/tb-7zip.tar.xz -C /tmp/tb-7zip
install /tmp/tb-7zip/7zz /usr/local/bin/7zz
rustc --version
7zz | head -4

62
.gitea/scripts/build.py Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""Ein Cross-Ziel auf dem Linux-arm64-Runner bauen und mit Hostwerkzeug paketieren."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import platform
import subprocess
import distribution as dist
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--target', choices=dist.TARGETS, required=True)
parser.add_argument('--output', type=Path, required=True)
args = parser.parse_args()
dist.require(platform.system() == 'Linux' and platform.machine() == 'aarch64', 'Buildhost muss Linux arm64 sein')
target = args.target
env = dict(os.environ, CARGO_BUILD_JOBS='2', MACOSX_DEPLOYMENT_TARGET='11.0',
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS='-C target-feature=+crt-static',
XWIN_VERSION='17', XWIN_SDK_VERSION='10.0.26100', XWIN_CRT_VERSION='14.44.17.14')
if target.endswith('msvc'):
builder = ['cargo', 'xwin', 'build']
build_target = target
else:
builder = ['cargo', 'zigbuild']
build_target = target + ('.2.28' if target.endswith('linux-gnu') else '')
dist.run(['rustup', 'target', 'add', target])
dist.run(builder + ['--locked', '--release', '--target', build_target,
'-p', 'tb-ide', '-p', 'tb-cli', '-p', 'tb-runner', '--bins'], cwd=dist.ROOT, env=env)
dist.run(['cargo', 'build', '--locked', '--release', '-p', 'tb-export', '--bin', 'tb-template'], cwd=dist.ROOT, env=env)
cargo_target = Path(os.environ.get('CARGO_TARGET_DIR', dist.ROOT / 'target')).resolve()
metadata = dict(builder=builder[1], build_target=build_target, macos_deployment='11.0')
if target.endswith('msvc'):
# Exakte Header/Library-Bytes pinnen; Microsoft-Kanäle können ihre
# Pakete auch unter derselben SDK-/CRT-Bezeichnung aktualisieren.
cache = Path.home() / '.cache/cargo-xwin/xwin'
checksum = hashlib.sha256()
for path in sorted(cache.rglob('*')):
if path.relative_to(cache).parts[0] not in ('crt', 'sdk'):
continue
if path.is_file() or path.is_symlink():
checksum.update(path.relative_to(cache).as_posix().encode() + b'\0')
checksum.update((str(path.readlink()).encode() if path.is_symlink() else
hashlib.sha256(path.read_bytes()).digest()) + b'\0')
dist.require(checksum.hexdigest() == '622fb2c2e3560514bfd59b87114c2aea72c15514614e95d01ddae7def96de047',
'SDK-/CRT-Inhalt weicht vom geprüften Build ab; Pin bewusst aktualisieren')
metadata.update(sdk='10.0.26100', crt='14.44.17.14', sdk_tree_sha256=checksum.hexdigest(), crt_static=True)
os.environ['TB_BUILD_METADATA'] = json.dumps(metadata)
dist.pack(cargo_target / target / 'release', target, args.output.resolve(), cargo_target / 'release/tb-template')
# Abhängigkeiten und Build-Baselines offen ausweisen; das sind keine gemessenen Mindest-OS-Versionen.
with (args.output / (dist.TARGETS[target][0] + '-build.txt')).open('w') as log:
for command in (['uname', '-a'], ['rustc', '-vV'], ['cargo', '--version']):
subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, check=True)
log.write(f'image={os.environ.get("TB_BUILD_IMAGE", "local")}\n'
f'build_target={build_target}\nMACOSX_DEPLOYMENT_TARGET=11.0\n'
'XWIN_VERSION=17\nXWIN_SDK_VERSION=10.0.26100\nXWIN_CRT_VERSION=14.44.17.14\n')
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,249 @@
#!/usr/bin/env python3
"""Vierzielpakete bauen, entpackt prüfen und vollständige Freigaben validieren."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import platform
import re
import shutil
import subprocess
import sys
import tarfile
import tempfile
import tomllib
ROOT = Path(__file__).resolve().parents[2]
TARGETS = {
'x86_64-pc-windows-msvc': ('windows-amd64', '.7z'),
'aarch64-apple-darwin': ('macos-arm64', '.tar.gz'),
'x86_64-unknown-linux-gnu': ('linux-amd64', '.tar.gz'),
'aarch64-unknown-linux-gnu': ('linux-arm64', '.tar.gz'),
}
HOSTS = {('Windows', 'AMD64'): list(TARGETS)[0], ('Darwin', 'arm64'): list(TARGETS)[1],
('Linux', 'x86_64'): list(TARGETS)[2], ('Linux', 'aarch64'): list(TARGETS)[3]}
TBL_SHA = '5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df'
def require(condition, message):
if not condition:
raise ValueError(message)
def digest(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def run(command, **kwargs):
print('+', ' '.join(map(str, command)), flush=True)
return subprocess.run(list(map(str, command)), check=True, timeout=3600, **kwargs)
def name(version, target):
require(re.fullmatch(r'[0-9]+\.[0-9]+\.[0-9]+(?:-[A-Za-z0-9.-]+)?', version), 'Ungültige Paketversion')
label, extension = TARGETS[target]
return f'terminalbasic-{version}-{label}{extension}'
def sevenzip():
tool = shutil.which('7zz') or shutil.which('7z')
require(tool, '7-Zip fehlt; Windows erfordert echte .7z-Archive')
return tool
def programs(target):
suffix = '.exe' if target == list(TARGETS)[0] else ''
return ['tb' + suffix, 'tbc' + suffix, f'runtimes/{target}/tbrt' + suffix]
def files(target):
return set(programs(target) + [programs(target)[2] + '.meta', 'LICENSE', 'INSTALL.txt', 'manifest.json'])
def unpack(archive, dest, target):
"""Nur bekannte reguläre Dateien; keine Symlinks, Unterverzeichnisse oder Traversierung."""
if archive.name.endswith('.7z'):
listing = subprocess.check_output([sevenzip(), 'l', '-slt', '--', str(archive)], text=True)
members = listing.split('----------\n', 1)[-1].strip().split('\n\n')
found = set()
for member in members:
fields = dict(line.split(' = ', 1) for line in member.splitlines() if ' = ' in line)
path = fields.get('Path')
require(path in files(target) and path not in found, f'Unerlaubter Archiveintrag: {path}')
require(fields.get('Folder', '-') == '-' and not fields.get('Symbolic Link') and
not fields.get('Hard Link') and not fields.get('Attributes', '').startswith('D'), 'Archivlink/-verzeichnis')
found.add(path)
require(found == files(target), 'Unvollständiges 7z-Archiv')
run([sevenzip(), 'x', '-y', '-o' + str(dest), '--', archive], stdout=subprocess.DEVNULL)
else:
with tarfile.open(archive, 'r:gz') as tar:
members = tar.getmembers()
require(len(members) == len(files(target)) and {m.name for m in members} == files(target), 'Falscher Archivinhalt')
require(all(m.isfile() for m in members), 'Nur reguläre Dateien erlaubt')
for member in members:
data = tar.extractfile(member).read()
path = dest / member.name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(data)
path.chmod(member.mode & 0o777)
require({p.relative_to(dest).as_posix() for p in dest.rglob('*') if p.is_file()} == files(target), 'Falscher entpackter Inhalt')
require(all(not p.is_symlink() and (p.is_file() or p.is_dir()) for p in dest.rglob('*')), 'Unerlaubter Dateityp')
def verify(archive, target, inspector=None):
with tempfile.TemporaryDirectory(prefix='tb-package-') as temp:
dest = Path(temp)
unpack(archive, dest, target)
manifest = json.loads((dest / 'manifest.json').read_text())
require(manifest['target'] == target and archive.name == name(manifest['version'], target), 'Falsches Paketziel/-version')
require(set(manifest['files']) == files(target) - {'manifest.json'}, 'Falsches Dateimanifest')
for path, sha in manifest['files'].items():
require(digest(dest / path) == sha, f'Beschädigte Datei: {path}')
for binary in programs(target):
if inspector:
run([inspector, '--inspect', dest / binary, target], stdout=subprocess.DEVNULL)
if target != list(TARGETS)[0]:
require((dest / binary).stat().st_mode & 0o111 == 0o111, 'Executable-Rechte fehlen')
metadata = (dest / (programs(target)[2] + '.meta')).read_text()
require(f'target={target}\n' in metadata and f'package={manifest["version"]}\n' in metadata, 'Vorlagenversion/-ziel falsch')
return manifest
def pack(binary_dir, target, output, inspector):
version = tomllib.loads((ROOT / 'Cargo.toml').read_text())['workspace']['package']['version']
revision = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=ROOT, text=True).strip()
output.mkdir(parents=True, exist_ok=True)
archive = output / name(version, target)
require(not archive.exists(), f'Paket existiert bereits: {archive}')
with tempfile.TemporaryDirectory(prefix='tb-pack-') as temp:
stage = Path(temp)
for binary in programs(target):
run([inspector, '--inspect', binary_dir / Path(binary).name, target], stdout=subprocess.DEVNULL)
(stage / binary).parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(binary_dir / Path(binary).name, stage / binary)
(stage / binary).chmod(0o755)
run([inspector, stage / programs(target)[2], target])
shutil.copyfile(ROOT / 'LICENSE', stage / 'LICENSE')
shutil.copyfile(ROOT / '.gitea/INSTALL.txt', stage / 'INSTALL.txt')
manifest = dict(version=version, revision=revision, target=target,
buildhost=platform.platform(), rustc=subprocess.check_output(['rustc', '--version'], text=True).strip(),
build_image=os.environ.get('TB_BUILD_IMAGE', 'local'),
cross_toolchain=json.loads(os.environ.get('TB_BUILD_METADATA', '{}')),
source_dirty=bool(subprocess.check_output(['git', 'status', '--porcelain'], cwd=ROOT)),
files={p.relative_to(stage).as_posix(): digest(p) for p in stage.rglob('*') if p.is_file()})
(stage / 'manifest.json').write_text(json.dumps(manifest, indent=2) + '\n')
if target == list(TARGETS)[0]:
run([sevenzip(), 'a', '-t7z', archive, *sorted(files(target))], cwd=stage, stdout=subprocess.DEVNULL)
else:
with tarfile.open(archive, 'w:gz') as tar:
for filename in sorted(files(target)):
tar.add(stage / filename, arcname=filename)
verify(archive, target, inspector)
(output / (archive.name + '.sha256')).write_text(f'{digest(archive)} {archive.name}\n')
print(archive)
def target_check(archive, target, output, windows_console_test=None):
require(HOSTS.get((platform.system(), platform.machine())) == target, 'Echte Zielausführung erfordert passendes Hostsystem')
require(not output.exists(), 'Nachweis existiert bereits')
manifest = verify(archive, target)
report = dict(target=target, revision=manifest['revision'], package=archive.name,
package_sha256=digest(archive), tbl_sha256=TBL_SHA, host=platform.platform(),
automated_passed=False, manual_terminal_passed=False, checks={})
output.mkdir(parents=True)
try:
with tempfile.TemporaryDirectory(prefix='tb-unpacked-') as temp:
dest = Path(temp)
unpack(archive, dest, target)
env = dict(os.environ, PATH='')
run([dest / programs(target)[0], '--help'], cwd=dest, env=env, stdout=subprocess.DEVNULL)
source = dest / 'hello.bas'; source.write_text('PRINT 42\nEND\n')
executable = dest / ('hello.exe' if os.name == 'nt' else 'hello')
run([dest / programs(target)[1], 'build', source, '--exe', '--target', target, '-o', executable], cwd=dest, env=env)
source.unlink()
actual = subprocess.check_output([str(executable)], cwd=dest, env=env, timeout=30)
require(actual.replace(b'\r\n', b'\n') == b' 42 \n', 'Standard-Vorlagenpfad funktioniert nicht')
report['checks']['default-template'] = 'passed'
commands = {
'native': [sys.executable, ROOT / 'tests/support/native-abnahme.py', '--bin-dir', dest, '--target', target],
'library': [sys.executable, ROOT / 'tests/support/library-abnahme.py', '--bin-dir', dest],
}
if os.name == 'posix':
commands['ide-pty'] = [sys.executable, ROOT / 'tests/support/ide-execution-pty.py', '--binary', dest / 'tb']
if os.name == 'nt':
require(windows_console_test and windows_console_test.is_file(), 'Windows-Konsolentest fehlt')
report['windows_console_test_sha256'] = digest(windows_console_test)
commands['windows-console'] = [windows_console_test, '--exact',
'terminal::tests::windows_console_restores_modes', '--ignored', '--nocapture']
for check, command in commands.items():
with (output / (check + '.log')).open('wb') as log:
run(command, cwd=dest, stdout=log, stderr=subprocess.STDOUT)
report['checks'][check] = 'passed'
report['automated_passed'] = True
finally:
require(digest(archive) == report['package_sha256'], 'Paket während Zielprüfung verändert')
(output / 'report.json').write_text(json.dumps(report, indent=2) + '\n')
def gate(directory, evidence, revision, version):
"""Fail closed: vier exakte Pakete und unabhängige, passende Zielnachweise."""
require(re.fullmatch('[0-9a-f]{40}', revision), 'Ungültige Revision')
require(digest(ROOT / 'tests/libraries/portable.tbl') == TBL_SHA, 'TBL-Probe verändert')
assets = []
for target in TARGETS:
archive = directory / name(version, target)
require(archive.is_file(), f'Pflichtpaket fehlt: {archive.name}')
sha = digest(archive)
checksum = archive.with_name(archive.name + '.sha256')
require(checksum.read_text() == f'{sha} {archive.name}\n', 'Paketprüfsumme falsch')
manifest = verify(archive, target, ROOT / 'target/release/tb-template')
require(manifest['revision'] == revision and not manifest['source_dirty'], 'Paket aus falschem/uncommittetem Stand')
proof = json.loads((evidence / target / 'report.json').read_text())
require(proof.get('target') == target and proof.get('revision') == revision and proof.get('package') == archive.name and
proof.get('package_sha256') == sha and proof.get('tbl_sha256') == TBL_SHA, 'Zielnachweis passt nicht zum Paket')
required = {'native', 'library', 'default-template', 'windows-console' if target == list(TARGETS)[0] else 'ide-pty'}
require(proof.get('automated_passed') is True and all(proof.get('checks', {}).get(k) == 'passed' for k in required), 'Automatisierte Zielprüfung fehlt')
manual = json.loads((evidence / target / 'manual.json').read_text())
require(manual.get('revision') == revision and manual.get('package_sha256') == sha and
manual.get('target') == target and manual.get('passed') is True and
manual.get('tester') and manual.get('terminal_versions') and manual.get('evidence'), 'Manueller Terminalnachweis fehlt')
terminals = {'windows-terminal'} if target == list(TARGETS)[0] else {'terminal.app'} if target == list(TARGETS)[1] else {'xterm', 'vte'}
require(isinstance(manual['terminal_versions'], dict) and
all(manual['terminal_versions'].get(t) for t in terminals), 'Pflichtemulator/Version fehlt')
require(all(manual.get('cases', {}).get(k) is True for k in
('f1_f12', 'modifiers', 'mouse', 'unicode_colors', 'resize', 'input_break', 'shell')), 'Manuelle Pflichtfolge unvollständig')
for reference in manual['evidence']:
relative = Path(reference)
require(not relative.is_absolute() and '..' not in relative.parts, 'Ungültiger manueller Nachweispfad')
path = evidence / target / relative
require(path.is_file() and path.stat().st_size > 0, 'Manueller Beleg fehlt')
assets.extend([archive, checksum])
acceptance = json.loads((evidence / 'acceptance.json').read_text())
require(acceptance.get('revision') == revision and acceptance.get('passed') is True and
all(acceptance.get(k) for k in ('foreign', 'inventory', 'workspace', 'benchmarks', 'native_ide', 'run_url', 'buildhost')), 'Pflichtabnahme/Benchmarks fehlen')
return assets
def main():
parser = argparse.ArgumentParser(description=__doc__)
sub = parser.add_subparsers(dest='command', required=True)
p = sub.add_parser('pack'); p.add_argument('--bin-dir', type=Path, required=True); p.add_argument('--output', type=Path, required=True)
p.add_argument('--inspector', type=Path, required=True); p.add_argument('--target', choices=TARGETS, required=True)
for command in ('verify', 'target-check'):
p = sub.add_parser(command); p.add_argument('--archive', type=Path, required=True); p.add_argument('--target', choices=TARGETS, required=True)
if command == 'verify': p.add_argument('--inspector', type=Path)
else:
p.add_argument('--output', type=Path, required=True)
p.add_argument('--windows-console-test', type=Path)
p = sub.add_parser('gate'); p.add_argument('--packages', type=Path, required=True); p.add_argument('--evidence', type=Path, required=True)
p.add_argument('--revision', required=True); p.add_argument('--version', required=True)
args = parser.parse_args()
if args.command == 'pack': pack(args.bin_dir.resolve(), args.target, args.output.resolve(), args.inspector.resolve())
elif args.command == 'verify': verify(args.archive.resolve(), args.target, args.inspector.resolve() if args.inspector else None)
elif args.command == 'target-check': target_check(args.archive.resolve(), args.target, args.output.resolve(), args.windows_console_test.resolve() if args.windows_console_test else None)
else: gate(args.packages, args.evidence, args.revision, args.version)
if __name__ == '__main__':
main()

37
.gitea/scripts/publish.py Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python3
"""Nur einen bestehenden Tag und Nachweise aus einer Origin-Revision verwenden."""
import os
from pathlib import Path
import re
import subprocess
import tempfile
import distribution as dist
import release
tag, evidence_revision = os.environ['TB_TAG'], os.environ['TB_EVIDENCE_REVISION']
dist.require(re.fullmatch(r'v[0-9]+\.[0-9]+\.[0-9]+(?:-[A-Za-z0-9.-]+)?', tag), 'Ungültiger Tag')
dist.require(re.fullmatch('[0-9a-f]{40}', evidence_revision), 'Ungültige Nachweisrevision')
revision = subprocess.check_output(['git', 'rev-parse', '--verify', tag + '^{commit}'], text=True).strip()
api = release.Gitea()
info = api.request('GET', '/git/commits/' + evidence_revision)
dist.require(info['sha'] == evidence_revision, 'Nachweise nicht am Origin')
# Checkout enthält alle Origin-Branches. Ein nicht vorhandener Commit scheitert hier.
base = f'release-evidence/{tag}'
names = subprocess.check_output(['git', 'ls-tree', '-r', '--name-only', evidence_revision, base], text=True).splitlines()
with tempfile.TemporaryDirectory(prefix='tb-release-') as tmp:
evidence = Path(tmp) / 'evidence'; evidence.mkdir()
for name in names:
relative = Path(name).relative_to(base)
dist.require('..' not in relative.parts and not relative.is_absolute(), 'Ungültiger Nachweispfad')
path = evidence / relative; path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(subprocess.check_output(['git', 'show', evidence_revision + ':' + name]))
packages = Path(tmp) / 'packages'; packages.mkdir()
draft = api.request('GET', '/releases/tags/' + tag)
wanted = release.expected(tag[1:])
dist.require(draft['draft'] and len(draft.get('assets', [])) == len(wanted) and
{a['name'] for a in draft['assets']} == set(wanted), 'Unvollständiger Entwurf')
for asset in draft['assets']:
(packages / asset['name']).write_bytes(api.download(asset))
# Grundabnahme kommt aus dem ursprünglichen Taglauf, nicht aus manuell ersetzten Angaben.
(evidence / 'acceptance.json').write_bytes((packages / 'acceptance.json').read_bytes())
release.publish(api, packages, evidence, tag, revision)

130
.gitea/scripts/release.py Normal file
View File

@@ -0,0 +1,130 @@
#!/usr/bin/env python3
"""Gitea-Entwurf befüllen; erst nach exakten Paket-/Zielnachweisen freigeben."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import re
from urllib.error import HTTPError
from urllib.parse import quote, urlparse
from urllib.request import Request, HTTPRedirectHandler, build_opener
import distribution as dist
class SafeRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
redirected = super().redirect_request(req, fp, code, msg, headers, newurl)
if redirected and urlparse(newurl).netloc != urlparse(req.full_url).netloc:
redirected.remove_header('Authorization')
return redirected
class Gitea:
def __init__(self):
self.base = os.environ['GITEA_SERVER_URL'].rstrip('/')
dist.require(self.base == 'https://git.rfc1437.de', 'Release nur am bestehenden Origin')
dist.require(os.environ['GITEA_REPOSITORY'] == 'hugo/TerminalBasic', 'Falsches Release-Repository')
self.api = self.base + '/api/v1/repos/hugo/TerminalBasic'
self.token = os.environ['TB_RELEASE_TOKEN']
self.open = build_opener(SafeRedirect()).open
def request(self, method, path, data=None):
raw = isinstance(data, bytes)
headers = {'Authorization': 'token ' + self.token,
'Content-Type': 'application/octet-stream' if raw else 'application/json'}
payload = data if raw or data is None else json.dumps(data).encode()
with self.open(Request(self.api + path, data=payload, headers=headers, method=method), timeout=120) as response:
return json.load(response)
def download(self, asset):
url = asset['browser_download_url']
dist.require(urlparse(url).netloc == urlparse(self.base).netloc, 'Fremder Assetserver')
with self.open(Request(url, headers={'Authorization': 'token ' + self.token}), timeout=120) as response:
return response.read()
def expected(version):
return [n for t in dist.TARGETS for n in (dist.name(version, t), dist.name(version, t) + '.sha256')] + ['acceptance.json']
def stage(api, directory, tag, revision):
version = tag.removeprefix('v')
dist.require(tag == 'v' + version and re.fullmatch('[0-9a-f]{40}', revision), 'Tag/Revision ungültig')
dist.require(api.request('GET', '/tags/' + quote(tag, safe=''))['commit']['sha'] == revision, 'Tag zeigt auf andere Revision')
names = expected(version)
for target in dist.TARGETS:
path = directory / dist.name(version, target)
manifest = dist.verify(path, target, dist.ROOT / 'target/release/tb-template')
dist.require(manifest['revision'] == revision and not manifest['source_dirty'], 'Paketrevision falsch/uncommitted')
dist.require(path.with_name(path.name + '.sha256').read_text() == f'{dist.digest(path)} {path.name}\n', 'Paketprüfsumme falsch')
acceptance = json.loads((directory / 'acceptance.json').read_text())
dist.require(acceptance.get('revision') == revision and acceptance.get('passed') is True, 'Grundabnahme fehlt')
try:
release = api.request('GET', '/releases/tags/' + quote(tag, safe=''))
except HTTPError as error:
if error.code != 404:
raise
release = api.request('POST', '/releases', dict(tag_name=tag, target_commitish=revision,
name='Terminal Basic ' + version, draft=True,
body='Vierzielpakete im Entwurf. Zielnachweise fehlen noch; keine Freigabe.'))
dist.require(release['draft'], 'Bereits veröffentlichten Release nicht verändern')
# Wiederholungen dürfen identische Uploads ergänzen, keine vorhandenen Assets ersetzen.
existing = {a['name']: a for a in release.get('assets', [])}
dist.require(set(existing) <= set(names), 'Unerwartete Assets im Entwurf')
for name in names:
data = (directory / name).read_bytes()
if name in existing:
dist.require(api.download(existing[name]) == data, f'Abweichendes vorhandenes Asset: {name}')
else:
api.request('POST', f'/releases/{release["id"]}/assets?name=' + quote(name), data)
verify_uploads(api, release['id'], directory, names)
return release['id']
def verify_uploads(api, release_id, directory, names):
release = api.request('GET', f'/releases/{release_id}')
assets = release.get('assets', [])
dist.require(len(assets) == len(names) and {a['name'] for a in assets} == set(names), 'Unvollständiger Asset-Upload')
for asset in assets:
dist.require(hashlib.sha256(api.download(asset)).hexdigest() == dist.digest(directory / asset['name']), 'Uploadprüfsumme falsch')
return release
def publish(api, directory, evidence, tag, revision):
version = tag.removeprefix('v')
dist.require(tag == 'v' + version, 'Versionstag erforderlich')
dist.require(api.request('GET', '/tags/' + quote(tag, safe=''))['commit']['sha'] == revision, 'Tag zeigt auf andere Revision')
dist.gate(directory, evidence, revision, version)
release = api.request('GET', '/releases/tags/' + quote(tag, safe=''))
verify_uploads(api, release['id'], directory, expected(version))
dist.require(release['draft'], 'Bereits freigegebenen Release nicht verändern')
api.request('PATCH', f'/releases/{release["id"]}', dict(draft=False,
body=f'Geprüfte Vierzielpakete für Revision {revision}. Zugehörige Zielnachweise: {os.environ.get("TB_EVIDENCE_REVISION", "lokaler Nachweissatz")}.'))
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('command', choices=['stage', 'download', 'publish'])
parser.add_argument('--packages', type=Path, required=True)
parser.add_argument('--tag', required=True); parser.add_argument('--revision', required=True)
parser.add_argument('--evidence', type=Path)
args = parser.parse_args()
api = Gitea()
if args.command == 'stage': stage(api, args.packages, args.tag, args.revision)
elif args.command == 'publish':
dist.require(args.evidence, '--evidence erforderlich')
publish(api, args.packages, args.evidence, args.tag, args.revision)
else:
args.packages.mkdir(parents=True) # Nie lokale Kandidaten überschreiben.
release = api.request('GET', '/releases/tags/' + quote(args.tag, safe=''))
names = expected(args.tag.removeprefix('v'))
dist.require(release['draft'], 'Nur bestehende Entwürfe freigeben')
assets = release.get('assets', [])
dist.require(len(assets) == len(names) and {a['name'] for a in assets} == set(names), 'Pflichtassets fehlen')
for asset in assets:
(args.packages / asset['name']).write_bytes(api.download(asset))
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,122 @@
import copy
import hashlib
import json
from pathlib import Path
import tarfile
import tempfile
import unittest
from unittest.mock import patch
import distribution as d
import release as r
class DistributionTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
self.packages = self.root / 'packages'; self.packages.mkdir()
self.evidence = self.root / 'evidence'; self.evidence.mkdir()
self.revision = 'a' * 40
self.version = '0.1.0'
self.manifests = {}
for target in d.TARGETS:
path = self.packages / d.name(self.version, target)
path.write_bytes(target.encode())
path.with_name(path.name + '.sha256').write_text(f'{d.digest(path)} {path.name}\n')
self.manifests[target] = dict(revision=self.revision, version=self.version, source_dirty=False)
proof = self.evidence / target; proof.mkdir()
report = dict(target=target, revision=self.revision, package=path.name,
package_sha256=d.digest(path), tbl_sha256=d.TBL_SHA, automated_passed=True,
checks={k:'passed' for k in ('native','library','ide-pty','windows-console','default-template')})
(proof / 'report.json').write_text(json.dumps(report))
(proof / 'manual.json').write_text(json.dumps(dict(target=target, revision=self.revision,
package_sha256=d.digest(path), passed=True, tester='Prüfer',
terminal_versions={k:'Version 1' for k in ('windows-terminal','terminal.app','xterm','vte')},
cases={k:True for k in ('f1_f12','modifiers','mouse','unicode_colors','resize','input_break','shell')}, evidence=['terminal.txt'])))
(proof / 'terminal.txt').write_text('Bedienprotokoll')
acceptance = dict(revision=self.revision, passed=True, foreign=True, inventory=True,
workspace=True, benchmarks=True, native_ide=True, run_url='https://git.rfc1437.de/run/1', buildhost='Linux arm64')
for directory in (self.packages, self.evidence):
(directory / 'acceptance.json').write_text(json.dumps(acceptance))
self.mock_verify = patch.object(d, 'verify', side_effect=lambda archive, target, *args: self.manifests[target])
self.mock_verify.start(); self.addCleanup(self.mock_verify.stop)
def gate(self):
return d.gate(self.packages, self.evidence, self.revision, self.version)
def test_complete_gate_and_missing_or_wrong_evidence(self):
self.assertEqual(len(self.gate()), 8)
target = list(d.TARGETS)[0]
path = self.evidence / target / 'report.json'
valid = json.loads(path.read_text())
for key, value in [('revision','b'*40), ('target',list(d.TARGETS)[1]), ('package_sha256','0'*64),
('tbl_sha256','0'*64), ('automated_passed',False), ('checks',{'native':'passed'})]:
broken = dict(valid, **{key:value}); path.write_text(json.dumps(broken))
with self.assertRaises(ValueError, msg=key): self.gate()
path.write_text(json.dumps(valid))
(self.evidence / target / 'manual.json').unlink()
with self.assertRaises(FileNotFoundError): self.gate()
def test_missing_corrupt_dirty_and_mismatched_packages(self):
first = next(iter(d.TARGETS))
self.manifests[first]['source_dirty'] = True
with self.assertRaises(ValueError): self.gate()
self.manifests[first]['source_dirty'] = False
path = self.packages / d.name(self.version, first)
path.write_bytes(b'broken')
with self.assertRaises(ValueError): self.gate()
path.unlink()
with self.assertRaises(ValueError): self.gate()
def test_archive_traversal_rejected_before_extract(self):
path = self.root / 'evil.tar.gz'
with tarfile.open(path, 'w:gz') as tar:
entry = tarfile.TarInfo('../escape'); tar.addfile(entry)
dest = self.root / 'unpack'; dest.mkdir()
with self.assertRaises(ValueError): d.unpack(path, dest, list(d.TARGETS)[1])
self.assertFalse((self.root / 'escape').exists())
def test_upload_failure_never_publishes_or_overwrites(self):
class API:
def __init__(self):
self.release = dict(id=1, draft=True, assets=[])
self.data = {}; self.fail_at = None; self.writes = []
def request(self, method, path, data=None):
if path.startswith('/tags/'): return {'commit': {'sha': 'a'*40}}
if method == 'GET': return copy.deepcopy(self.release)
self.writes.append((method,path))
if method == 'POST':
name = path.split('name=')[1]
if name == self.fail_at: raise OSError('simulierter Uploadfehler')
self.data[name] = data
self.release['assets'].append(dict(name=name, browser_download_url=name))
return {}
if method == 'PATCH': self.release.update(data)
def download(self, asset): return self.data[asset['name']]
api = API(); api.fail_at = r.expected(self.version)[2]
with self.assertRaises(OSError): r.stage(api, self.packages, 'v'+self.version, self.revision)
self.assertTrue(api.release['draft'])
self.assertFalse(any(method=='PATCH' for method,_ in api.writes))
api.fail_at = None
r.stage(api, self.packages, 'v'+self.version, self.revision)
r.publish(api, self.packages, self.evidence, 'v'+self.version, self.revision)
self.assertFalse(api.release['draft'])
before = list(api.writes)
with self.assertRaises(ValueError): r.stage(api, self.packages, 'v'+self.version, self.revision)
self.assertEqual(before, api.writes)
def test_incomplete_remote_upload_blocks_publish(self):
class API:
def request(self, method, path, data=None):
self.assert_get(method)
if path.startswith('/tags/'): return {'commit': {'sha': 'a'*40}}
return dict(id=1, draft=True, assets=[])
@staticmethod
def assert_get(method):
if method != 'GET': raise AssertionError('Unerwartete Mutation')
with self.assertRaises(ValueError): r.publish(API(), self.packages, self.evidence, 'v'+self.version, self.revision)
if __name__ == '__main__':
unittest.main()

102
.gitea/workflows/build.yml Normal file
View File

@@ -0,0 +1,102 @@
name: Vierziel-Build und Pflichtabnahme
on:
push:
branches: ['main', 'ci/**']
tags: ['v*']
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
checks:
if: gitea.event_name != 'pull_request' || gitea.event.pull_request.head.repo.full_name == gitea.repository
runs-on: linux-arm64
container: ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b
timeout-minutes: 60
env:
CARGO_BUILD_JOBS: '2'
TB_VBDOS_REPOSITORY: ${{ vars.TB_VBDOS_REPOSITORY }}
TB_VBDOS_REPO: /tmp/tb-vbdos
TB_RUN_URL: ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }}
steps:
- uses: https://gitea.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
persist-credentials: false
- name: Gepinnte Werkzeuge
run: sh .gitea/scripts/bootstrap.sh
- name: Fixierten Fremdbestand bereitstellen
run: |
set -eu
test -n "$TB_VBDOS_REPOSITORY" || { echo 'TB_VBDOS_REPOSITORY für Pflichtabnahme fehlt'; exit 1; }
git init "$TB_VBDOS_REPO"
git -C "$TB_VBDOS_REPO" fetch --depth=1 "$TB_VBDOS_REPOSITORY" 1cdd2b32b829fe1721d0b6aecc433abc47a96fb6
git -C "$TB_VBDOS_REPO" checkout --detach FETCH_HEAD
- name: Paket- und Release-Regressionen
run: python3 -m unittest discover -s .gitea/scripts -p 'test_*.py'
- name: Workspace, Inventar, Fremdprogramme und Referenzbenchmarks
run: python3 .gitea/scripts/acceptance.py
- uses: https://gitea.com/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
if: always()
with:
name: acceptance
path: acceptance/
if-no-files-found: error
build:
if: gitea.event_name != 'pull_request' || gitea.event.pull_request.head.repo.full_name == gitea.repository
runs-on: linux-arm64
timeout-minutes: 90
strategy:
fail-fast: false
max-parallel: 1
matrix:
include:
- target: x86_64-pc-windows-msvc
image: messense/cargo-xwin@sha256:4696dd4e79edf8569fa99c4b06bd99273e0501c7adc983aa61d57945f795bef0
- target: aarch64-apple-darwin
image: ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b
- target: x86_64-unknown-linux-gnu
image: ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b
- target: aarch64-unknown-linux-gnu
image: ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b
container: ${{ matrix.image }}
env:
TB_BUILD_IMAGE: ${{ matrix.image }}
TB_TARGET: ${{ matrix.target }}
steps:
- uses: https://gitea.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
persist-credentials: false
- run: sh .gitea/scripts/bootstrap.sh
- name: Bauen, Format prüfen und paketieren
run: python3 .gitea/scripts/build.py --target "$TB_TARGET" --output dist
- uses: https://gitea.com/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
with:
name: packages-${{ matrix.target }}
path: dist/
if-no-files-found: error
stage:
if: startsWith(gitea.ref, 'refs/tags/v') && gitea.event_name == 'push'
needs: [checks, build]
runs-on: linux-arm64
container: ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b
steps:
- uses: https://gitea.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
persist-credentials: false
- run: sh .gitea/scripts/bootstrap.sh
- uses: https://gitea.com/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a
with:
path: artifacts
- run: cargo build --locked --release -p tb-export --bin tb-template
- name: Vollständigen Releaseentwurf erstellen
env:
GITEA_SERVER_URL: ${{ gitea.server_url }}
GITEA_REPOSITORY: ${{ gitea.repository }}
TB_RELEASE_TOKEN: ${{ secrets.TB_RELEASE_TOKEN }}
TB_TAG: ${{ gitea.ref_name }}
TB_REVISION: ${{ gitea.sha }}
run: |
mkdir packages
cp artifacts/packages-*/*.7z artifacts/packages-*/*.tar.gz artifacts/packages-*/*.sha256 packages/
cp artifacts/acceptance/acceptance.json packages/
python3 .gitea/scripts/release.py stage --packages packages --tag "$TB_TAG" --revision "$TB_REVISION"

View File

@@ -0,0 +1,32 @@
name: Geprüften Gitea-Entwurf freigeben
on:
workflow_dispatch:
inputs:
tag:
description: 'Vorhandener Versionstag, z.B. v0.1.0'
required: true
evidence_commit:
description: '40-stellige Origin-Revision mit release-evidence/<tag>/'
required: true
permissions:
contents: read
jobs:
publish:
if: gitea.ref == 'refs/heads/main'
runs-on: linux-arm64
container: ghcr.io/rust-cross/cargo-zigbuild@sha256:82af75c41958c2af2787e8bedd912da7678a9438937e223e9d83d006d747b38b
steps:
- uses: https://gitea.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
fetch-depth: 0
persist-credentials: false
- run: sh .gitea/scripts/bootstrap.sh
- run: cargo build --locked --release -p tb-export --bin tb-template
- name: Originalpakete und revisionsgebundene Zielnachweise prüfen
env:
GITEA_SERVER_URL: ${{ gitea.server_url }}
GITEA_REPOSITORY: ${{ gitea.repository }}
TB_RELEASE_TOKEN: ${{ secrets.TB_RELEASE_TOKEN }}
TB_TAG: ${{ inputs.tag }}
TB_EVIDENCE_REVISION: ${{ inputs.evidence_commit }}
run: python3 .gitea/scripts/publish.py

5
.gitignore vendored
View File

@@ -1,3 +1,8 @@
/target /target
**/*.rs.bk **/*.rs.bk
*.pdb *.pdb
/dist
/acceptance
/artifacts
/packages
**/__pycache__

View File

@@ -1,10 +1,23 @@
//! Builder-Hilfe: geprüfte Metadaten für eine frisch gebaute Runtime schreiben. //! Builder-Hilfe: geprüfte Metadaten für eine frisch gebaute Runtime schreiben.
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let args: Vec<_> = std::env::args().skip(1).collect(); let mut args: Vec<_> = std::env::args().skip(1).collect();
let inspect = args.first().is_some_and(|s| s == "--inspect");
if inspect {
args.remove(0);
}
anyhow::ensure!( anyhow::ensure!(
args.len() == 2, args.len() == 2,
"Aufruf: tb-template <tbrt-Pfad> <Target-Triple>" "Aufruf: tb-template [--inspect] <Executable-Pfad> <Target-Triple>"
); );
if inspect {
let found = tb_export::native_target(&std::fs::read(&args[0])?)?;
anyhow::ensure!(
found == tb_export::Target::parse(&args[1])?,
"Executable hat falsches Ziel"
);
println!("{}", found.triple());
return Ok(());
}
tb_export::prepare_template( tb_export::prepare_template(
std::path::Path::new(&args[0]), std::path::Path::new(&args[0]),
tb_export::Target::parse(&args[1])?, tb_export::Target::parse(&args[1])?,

145
docs/distribution.md Normal file
View File

@@ -0,0 +1,145 @@
# Gitea-Build und Distribution
Change 06 baut ausschließlich am Origin `git.rfc1437.de/hugo/TerminalBasic`.
Die Actions verwenden das bestätigte Label `linux-arm64` und vier Zieltriple.
Kein Cross-Build ist ein Windows-/macOS-/Linux-Emulatornachweis.
## Buildumgebung
| Ziel | Builder | Fixierte Baseline |
|---|---|---|
| Windows amd64 | cargo-xwin 0.23.0 | VS-Kanal 17 mit festen SDK-/CRT-Versionen: SDK 10.0.26100, CRT 14.44.17.14; statische CRT |
| macOS arm64 | cargo-zigbuild 0.23.0, Zig 0.16.0 | enthaltenes MacOSX11.3.sdk; Deployment Target 11.0 |
| Linux amd64/arm64 | cargo-zigbuild 0.23.0, Zig 0.16.0 | glibc 2.28 |
Rust 1.97.1 ist in `rust-toolchain.toml` fixiert. Die Images stehen mit Digest
in `.gitea/workflows/build.yml`; SDK/Clang/Zig stammen aus diesen Images.
7-Zip 25.01 wird mit fester SHA-256 in `bootstrap.sh` bereitgestellt.
Zusätzlich prüft der Windows-Build einen festen Hash aller SDK-/CRT-Dateien
und Symlinks. Änderungen unter derselben Microsoft-Versionsbezeichnung
werden damit abgelehnt; der Pin muss dann ausdrücklich aktualisiert werden.
Die Tabelle nennt Buildvorgaben, keine gemessenen minimalen OS-Versionen.
Die tatsächliche Cross-Matrix und OS-Läufe sind im Changebericht auszuweisen.
Der Builder erfordert Linux aarch64. Zwei Cargo-Buildjobs und eine sequenzielle
Zielmatrix begrenzen die Last. Host-`tb-template` prüft über denselben Parser
wie der Exportdienst PE32+/amd64/Console, Mach-O/arm64 oder ELF/Linux/64-Bit;
fremde Executables werden beim Paketieren nicht ausgeführt.
Lokaler Aufruf innerhalb des betreffenden gepinnten Containers:
```sh
sh .gitea/scripts/bootstrap.sh
python3 .gitea/scripts/build.py --target x86_64-pc-windows-msvc --output dist
```
Eigene native Testpakete lassen sich mit `distribution.py pack --bin-dir ...
--target ... --output ... --inspector .../tb-template` erstellen. Uncommittete
Quellen bleiben in `manifest.json` markiert und sind nicht freigabefähig.
## Origin-Konfiguration und Rechte
Actions sind am Repository aktiviert. Der gemeinsame Runner heißt
`gitea-arm64-01`. Sein Neustartfehler wurde separat gemeldet; der Aufbau der
Repository-Workflows ändert keine globale Docker-/AppArmor-Konfiguration.
Erforderliche Konfiguration:
- Variable `TB_VBDOS_REPOSITORY`: erreichbarer Git-Bestand des in
`foreign.rs` fixierten Referenzprojekts. Der Checkout muss exakt
`1cdd2b32b829fe1721d0b6aecc433abc47a96fb6` liefern. Fehlende Konfiguration
lässt den Pflichtjob scheitern; Fremdprogramme werden nicht übersprungen.
- Secret `TB_RELEASE_TOKEN`: Gitea-Zugang nur für dieses Repository und die
Releaseverwaltung. Nur der Tag-Entwurfsjob und der manuelle Freigabeworkflow
referenzieren es. Es wird weder im Checkout gespeichert noch geloggt.
- PRs aus fremden Repositories führen keinen unkontrollierten Code auf dem
gemeinsamen persönlichen Runner aus. Interne PRs/Pushes erhalten keine
Veröffentlichungsschritte. Die tatsächliche Gitea-/Runner-Kompatibilität
einschließlich Jobrechten muss der erste Origin-Lauf bestätigen.
Die Actions-URLs sind explizite Gitea-URLs mit festen Commit-IDs.
[Absolute Action-URLs](https://docs.gitea.com/usage/actions/comparison/)
und [Runnerlabels](https://docs.gitea.com/runner/) entsprechen dem Gitea-Modell.
## Pakete und Zielprüfungen
`terminalbasic-<version>-windows-amd64.7z` sowie `...-macos-arm64.tar.gz`,
`...-linux-amd64.tar.gz`, `...-linux-arm64.tar.gz` enthalten `tb`/`tbc` im Hauptverzeichnis und
`runtimes/<Target-Triple>/tbrt` samt `tbrt.meta` (Windows jeweils `.exe`
bzw. `tbrt.exe.meta`),
`LICENSE`, `INSTALL.txt` und `manifest.json`. Unix-Executables besitzen 0755.
Das Manifest bindet Version, Revision, Rust, Buildhost/Image, Target und
SHA-256 jeder Datei. Jedes Paket erhält zusätzlich eine `.sha256`-Datei.
Auf dem passenden Prüfsystem das unveränderte Paket herunterladen und ausführen:
```sh
python3 .gitea/scripts/distribution.py target-check \
--archive /pakete/terminalbasic-0.1.0-macos-arm64.tar.gz \
--target aarch64-apple-darwin --output /nachweise/aarch64-apple-darwin
```
Das Prüfsystem braucht Python und den Prüfharness dieser Revision; die
Produkte selbst laufen aus einem neu entpackten temporären Verzeichnis.
Native-/TBL-Prüfungen verwenden einen leeren PATH, separate Verbraucher,
keine Library-Quellen und die vorhandenen paketierten Metadaten. Auf macOS
bleibt `/usr/bin/codesign` als Systemhilfe zulässig. Erzeugte Executables
laufen nach Entfernen von Quellen, TBL/TBC und Vorlagen weiter.
Die gemeinsame `portable.tbl` wird auf allen Zielen unverändert verwendet,
SHA-256 `5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df`.
Windows erfordert zusätzlich `--windows-console-test <tb-ui-Testexecutable>`
derselben Revision. Dieses Testexecutable kann der Linux-Builder mit
`cargo xwin test --locked --target x86_64-pc-windows-msvc -p tb-ui
--features terminal --no-run` erzeugen; es gehört zum Prüfharness, nicht zum
Anwenderpaket. DOSBox kann diese Windows-PE-Programme nicht ausführen.
Windows bleibt auf Benutzerentscheidung vorerst offen.
Der automatisch erzeugte `report.json` lässt die manuelle Terminalabnahme
offen. Die Bedienfolge steht in `docs/plattformmatrix.md`. Je Target sind
zusätzlich `manual.json` und die referenzierten nichtleeren Belegdateien nötig:
```json
{
"target": "aarch64-apple-darwin",
"revision": "<40-stellige Revision>",
"package_sha256": "<SHA-256 des Originalpakets>",
"passed": true,
"tester": "<Prüfer>",
"terminal_versions": {"terminal.app": "<gemessene Version>"},
"cases": {"f1_f12": true, "modifiers": true, "mouse": true,
"unicode_colors": true, "resize": true, "input_break": true, "shell": true},
"evidence": ["terminal-protokoll.txt"]
}
```
Windows verlangt `windows-terminal`, beide Linux-Ziele jeweils `xterm` und
`vte` mit Versionen. Nur tatsächlich bestandene Schritte auf true setzen.
Die Felder dienen einer verantworteten manuellen Bestätigung; sie ersetzen
keine Durchführung. Herkunft wird über den geprüften Origin-Commit gebunden.
## Entwurf und Veröffentlichung
Ein Push des passenden Tags `v<version>` baut/testet alle vier Ziele und lädt
erst danach neun Assets in einen Gitea-Entwurf: vier Pakete, vier SHA-Dateien,
`acceptance.json`. Dessen Referenzlauf enthält Fremdprogramme, Inventar,
Workspace/Clippy/Format, Compile-/VM-Benchmarks und die ausdrücklich gestartete
native IDE-Abnahme. Golden-Erzeugung bleibt bewusst ignoriert. Echte native
Paket-/Terminalprüfungen sind eine zusätzliche Freigabebedingung.
Nachweise auf separaten Systemen beziehen sich auf diese Originalpakete.
Unter `release-evidence/v<version>/<target>/` werden `report.json`, Logs,
`manual.json` und dessen Belege in einem Origin-Commit bereitgestellt.
Der manuell auf main gestartete Workflow „Geprüften Gitea-Entwurf freigeben“
erhält Tag und vollständige Nachweisrevision. Er lädt die ursprünglichen
Entwurfsassets, prüft vier exakte Paketbindungen, Ziel-/Terminalresultate,
gemeinsame TBL-Prüfsumme und die Grundabnahme aus dem ursprünglichen Taglauf.
Er baut die Pakete dabei nicht erneut. Fehlende oder abweichende Daten sperren
Freigabe. Der Tag muss zur Paketversion und zur geprüften Revision passen.
Uploads werden zurückgelesen und bytegenau geprüft. Wiederholungen ergänzen
nur fehlende identische Assets eines Entwurfs. Abweichende Assets oder ein
bereits veröffentlichter Release werden nicht überschrieben. Erst der letzte
API-Aufruf ändert `draft` auf false. Die Regressionen simulieren insbesondere
fehlende Uploads, falsche Nachweise, korrupte Pakete und bestehende Releases;
sie erzeugen keine öffentlichen Testreleases.

View File

@@ -12,7 +12,7 @@ Origin ist `https://git.rfc1437.de/hugo/TerminalBasic.git`; die read-only Versio
1. `.gitea/workflows/` nutzt den vorhandenen Linux-arm64-Runner für alle vier Build-/Paketziele. Vorhandene Workflowmuster der anderen Origin-Projekte wiederverwenden: cargo-zigbuild für Linux amd64 und macOS arm64, cargo-xwin für Windows amd64/MSVC; Linux arm64 nativ oder mit derselben festgelegten Linux-Zielbaseline. Container/Tools und benötigte SDKs/Sysroots reproduzierbar pinnen; konkrete Rust-/OS-/glibc-Versionen mit TerminalBasic prüfen. Das Runnerlabel `linux-arm64` bei Anbindung bestätigen. Vier native Buildrunner sind nicht erforderlich. `build-runtime.py` erzeugt Vorlagenmetadaten mit dem Hostwerkzeug für das jeweilige Target; fremde Executables werden auf dem Buildhost nicht nativ ausgeführt. 1. `.gitea/workflows/` nutzt den vorhandenen Linux-arm64-Runner für alle vier Build-/Paketziele. Vorhandene Workflowmuster der anderen Origin-Projekte wiederverwenden: cargo-zigbuild für Linux amd64 und macOS arm64, cargo-xwin für Windows amd64/MSVC; Linux arm64 nativ oder mit derselben festgelegten Linux-Zielbaseline. Container/Tools und benötigte SDKs/Sysroots reproduzierbar pinnen; konkrete Rust-/OS-/glibc-Versionen mit TerminalBasic prüfen. Das Runnerlabel `linux-arm64` bei Anbindung bestätigen. Vier native Buildrunner sind nicht erforderlich. `build-runtime.py` erzeugt Vorlagenmetadaten mit dem Hostwerkzeug für das jeweilige Target; fremde Executables werden auf dem Buildhost nicht nativ ausgeführt.
2. Wiederverwendbare Repository-Skripte erledigen Build, Tests, Paketierung und Prüfung auch lokal. Source-Checkout vom Gitea-Origin, alle zusätzlichen Actions nur über explizite Gitea-URLs und feste Revisionen, soweit überhaupt nötig; keine implizite fremde Action-Auflösung. Rust und benötigte Systemwerkzeuge versioniert bereitstellen. Server-/Runner-Kompatibilität praktisch prüfen, statt lediglich YAML zu validieren. 2. Wiederverwendbare Repository-Skripte erledigen Build, Tests, Paketierung und Prüfung auch lokal. Source-Checkout vom Gitea-Origin, alle zusätzlichen Actions nur über explizite Gitea-URLs und feste Revisionen, soweit überhaupt nötig; keine implizite fremde Action-Auflösung. Rust und benötigte Systemwerkzeuge versioniert bereitstellen. Server-/Runner-Kompatibilität praktisch prüfen, statt lediglich YAML zu validieren.
3. Matrixprodukte: `terminalbasic-<version>-windows-amd64.7z`, `terminalbasic-<version>-macos-arm64.tar.gz`, `terminalbasic-<version>-linux-amd64.tar.gz`, `terminalbasic-<version>-linux-arm64.tar.gz`. Windows enthält `tb.exe`/`tbc.exe`/`tbrt.exe`, übrige `tb`/`tbc`/`tbrt`; tbrt ist die native Exportvorlage, dazu deren Metadaten, Lizenz, Kurzinstallation. Archive dürfen keine Buildverzeichnis-/Quellbaumabhängigkeiten haben. Exportierte Anwenderprogramme bleiben normale native Einzelartefakte; die Archivformate betreffen die Distribution. 3. Matrixprodukte: `terminalbasic-<version>-windows-amd64.7z`, `terminalbasic-<version>-macos-arm64.tar.gz`, `terminalbasic-<version>-linux-amd64.tar.gz`, `terminalbasic-<version>-linux-arm64.tar.gz`. Windows enthält `tb.exe`/`tbc.exe`/`tbrt.exe`, übrige `tb`/`tbc`/`tbrt`; tbrt ist die native Exportvorlage unter `runtimes/<Target-Triple>/`, dazu deren Metadaten, Lizenz, Kurzinstallation. Das vorhandene CLI-/IDE-Suchschema bleibt erhalten. Archive dürfen keine Buildverzeichnis-/Quellbaumabhängigkeiten haben. Exportierte Anwenderprogramme bleiben normale native Einzelartefakte; die Archivformate betreffen die Distribution.
4. Der Linux-Buildhost erzeugt/prüft Windows-Archive mit 7-Zip und Unix-Archive mit tar+gzip unter Erhalt der Executable-Bits. Inhalts-/Formatprüfungen laufen dort; tatsächliche Start-/Exportprüfungen verwenden neu entpackte Pakete auf passenden Zielsystemen aus 05, automatisiert oder dokumentiert manuell. Externe Nachweise müssen an Revision und exakte Paketprüfsumme gebunden und vor Freigabe geprüft sein. Ein gemeinsames TBL-Testartefakt wird einmal erzeugt und mit nachgewiesen identischen Bytes auf allen vier Zielsystemen verwendet. Separate BASIC-Verbraucher werden mit den entpackten TB-Tools verknüpft, als TBC ausgeführt und mit tbrt als EXE exportiert. Library-Quellen sind dabei nicht verfügbar. Erzeugung/Linken werden in einer Umgebung ohne erreichbaren C-/Rust-Compiler oder nativen Linker geprüft; Systemhilfen zur EXE-Finalisierung dürfen verfügbar bleiben. Fertige EXEs laufen anschließend ohne externe TBL/TBC oder TB-Installation. 4. Der Linux-Buildhost erzeugt/prüft Windows-Archive mit 7-Zip und Unix-Archive mit tar+gzip unter Erhalt der Executable-Bits. Inhalts-/Formatprüfungen laufen dort; tatsächliche Start-/Exportprüfungen verwenden neu entpackte Pakete auf passenden Zielsystemen aus 05, automatisiert oder dokumentiert manuell. Externe Nachweise müssen an Revision und exakte Paketprüfsumme gebunden und vor Freigabe geprüft sein. Ein gemeinsames TBL-Testartefakt wird einmal erzeugt und mit nachgewiesen identischen Bytes auf allen vier Zielsystemen verwendet. Separate BASIC-Verbraucher werden mit den entpackten TB-Tools verknüpft, als TBC ausgeführt und mit tbrt als EXE exportiert. Library-Quellen sind dabei nicht verfügbar. Erzeugung/Linken werden in einer Umgebung ohne erreichbaren C-/Rust-Compiler oder nativen Linker geprüft; Systemhilfen zur EXE-Finalisierung dürfen verfügbar bleiben. Fertige EXEs laufen anschließend ohne externe TBL/TBC oder TB-Installation.
5. `cargo test --locked --workspace`, Clippy und Formatprüfung zentral auf dem Linux-arm64-Host; zielabhängige Rust-Testprogramme bei Bedarf cross-kompilieren und auf passenden Prüfsystemen ausführen. Native Tests aus 02/03/04 und automatisierbare Plattformtests aus 05 auf ihren tatsächlichen Zielen ausführen. Buildstatus und Ausführungsnachweise getrennt ausweisen; macOS-EXE-Finalisierung mit codesign erfolgt auf macOS. Den fixierten Fremdprogrammbestand ausdrücklich im erforderlichen Abnahmelauf bereitstellen. Compile-/VM-Messungen auf dokumentiertem Referenzrunner statt instabiler Debug-Zeitlimits in allen Jobs. 5. `cargo test --locked --workspace`, Clippy und Formatprüfung zentral auf dem Linux-arm64-Host; zielabhängige Rust-Testprogramme bei Bedarf cross-kompilieren und auf passenden Prüfsystemen ausführen. Native Tests aus 02/03/04 und automatisierbare Plattformtests aus 05 auf ihren tatsächlichen Zielen ausführen. Buildstatus und Ausführungsnachweise getrennt ausweisen; macOS-EXE-Finalisierung mit codesign erfolgt auf macOS. Den fixierten Fremdprogrammbestand ausdrücklich im erforderlichen Abnahmelauf bereitstellen. Compile-/VM-Messungen auf dokumentiertem Referenzrunner statt instabiler Debug-Zeitlimits in allen Jobs.
6. Gitea-Release erst nach allen Pflichtjobs, zugeordneten echten Zielnachweisen und Vollständigkeits-/Prüfsummenprüfung freigeben. Upload zunächst zu einem als Entwurf erkennbaren Release oder gleichwertigem nicht freigegebenen Staging; anschließend atomare Freigabe im Rahmen der verfügbaren API. PR-Jobs ohne Veröffentlichungsrechte und ohne Release-Secrets; fremder PR-Code darf nicht mit solchen Rechten auf persönlichen Runnern laufen. Zugangswerte werden als Gitea-Secrets konfiguriert, nicht committed. Tests erzeugen keine öffentlichen Testreleases. 6. Gitea-Release erst nach allen Pflichtjobs, zugeordneten echten Zielnachweisen und Vollständigkeits-/Prüfsummenprüfung freigeben. Upload zunächst zu einem als Entwurf erkennbaren Release oder gleichwertigem nicht freigegebenen Staging; anschließend atomare Freigabe im Rahmen der verfügbaren API. PR-Jobs ohne Veröffentlichungsrechte und ohne Release-Secrets; fremder PR-Code darf nicht mit solchen Rechten auf persönlichen Runnern laufen. Zugangswerte werden als Gitea-Secrets konfiguriert, nicht committed. Tests erzeugen keine öffentlichen Testreleases.
@@ -28,3 +28,20 @@ Origin ist `https://git.rfc1437.de/hugo/TerminalBasic.git`; die read-only Versio
## Migration Plan ## Migration Plan
Lokale Skripte zuerst lauffähig machen, dann Gitea-Runner und Workflows anbinden. PR-/Push-Lauf ohne Veröffentlichung prüfen; kontrollierter Tag-/Release-Lauf nach erfolgreicher Matrix. Bisherige lokale Cargo-Nutzung erhalten. Rollback über vorheriges vollständiges Release und Rücknahme der Workflowänderung; keine Server-/Runnerinstallation durch bloße Proposal-Erstellung. Lokale Skripte zuerst lauffähig machen, dann Gitea-Runner und Workflows anbinden. PR-/Push-Lauf ohne Veröffentlichung prüfen; kontrollierter Tag-/Release-Lauf nach erfolgreicher Matrix. Bisherige lokale Cargo-Nutzung erhalten. Rollback über vorheriges vollständiges Release und Rücknahme der Workflowänderung; keine Server-/Runnerinstallation durch bloße Proposal-Erstellung.
## Konkretisierung während der Umsetzung
- Rust 1.97.1, vorhandene Cross-Images per Digest, 7-Zip 25.01 per SHA-256.
SDK-/CRT-Versionen und ein Hash ihrer exakten Header-/Library-Bytes sind
für Windows fixiert; macOS-SDK/Zig stammen aus dem gepinnten Image.
- `tb-template --inspect` nutzt den vorhandenen PE/ELF/Mach-O-Parser auch
für tb/tbc. Build und Paketprüfung laufen auf dem Host ohne fremde Programme
auszuführen. Die Anwenderpakete benötigen tb-template nicht.
- Taglauf erzeugt erst nach Build/Grundabnahme einen überprüften Entwurf.
Originalpakete werden auf separaten Systemen geprüft. Ein manueller Workflow
auf main bindet deren Nachweise aus einem Origin-Commit an Tag, Revision und
Paket-SHA-256 und gibt erst dann denselben Entwurf frei; kein erneuter Bau.
- Die Benutzerentscheidung aus 05, Windows-Ausführung vorerst offen zu lassen,
bleibt erhalten. Sie macht Windows-Builds zulässig, aber keinen Release mit
fehlender Windows-Abnahme erfolgreich. Fehlende Nachweise werden nicht auf
Basis der gemeinsamen ANSI-Technik von macOS/Linux pauschal abgehakt.

View File

@@ -0,0 +1,6 @@
Checking tb-frontend v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-frontend)
Checking tb-runtime v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-runtime)
Checking tb-ui v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ui)
Checking tb-vm v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-vm)
Checking tb-export v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-export)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.74s

View File

@@ -0,0 +1,3 @@
PASS {'shell_exit': 7}
PASS {'abort': True}
PASS {'file_shell': True}

View File

@@ -0,0 +1 @@
{"target": "aarch64-apple-darwin", "tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df", "native_execution": true, "source_free": true, "run_reset": true, "output": " 1 \n 7 3 9 1 \nTB \n"}

View File

@@ -0,0 +1,13 @@
PASS native console
PASS native restart
PASS native stop
PASS native error
PASS native project
PASS native form
PASS native external
PASS PTY Eingabe, Abbruch und Wiederherstellung (CLI/native)
PASS Exportabbruch SIGINT/SIGTERM, Original und Bereinigung
PASS corrupted length
PASS corrupted version
PASS corrupted truncated
Native Abnahme bestanden: aarch64-apple-darwin

View File

@@ -0,0 +1,16 @@
{
"target": "aarch64-apple-darwin",
"revision": "796564795a6607651c366c6b0de74560af55e71a",
"package": "terminalbasic-0.1.0-macos-arm64.tar.gz",
"package_sha256": "369882d9962f0264f41a7dfc0e352acb826c43d84a3c8babd028636a24aeaf4d",
"tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df",
"host": "macOS-26.6.2-arm64-arm-64bit-Mach-O",
"automated_passed": true,
"manual_terminal_passed": false,
"checks": {
"default-template": "passed",
"native": "passed",
"library": "passed",
"ide-pty": "passed"
}
}

View File

@@ -0,0 +1,270 @@
info: syncing channel updates for '1.97.1-aarch64-unknown-linux-gnu'
info: latest update on 2026-07-16, rust version 1.97.1 (8bab26f4f 2026-07-14)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'rustfmt'
1.97.1-aarch64-unknown-linux-gnu installed - rustc 1.97.1 (8bab26f4f 2026-07-14)
info: default toolchain set to '1.97.1-aarch64-unknown-linux-gnu'
info: checking for self-update
info: downloading self-update
/tmp/tb-7zip.tar.xz: OK
rustc 1.97.1 (8bab26f4f 2026-07-14)
7-Zip (z) 25.01 (arm64) : Copyright (c) 1999-2025 Igor Pavlov : 2025-08-03
64-bit arm_v:8-A locale=C.UTF-8 Threads:4 OPEN_MAX:1024, ASM
+ rustup target add aarch64-unknown-linux-gnu
info: component rust-std is up to date
+ cargo zigbuild --locked --release --target aarch64-unknown-linux-gnu.2.28 -p tb-ide -p tb-cli -p tb-runner --bins
Updating crates.io index
Downloading crates ...
Downloaded bitflags v1.3.2
Downloaded cassowary v0.3.0
Downloaded anyhow v1.0.104
Downloaded bitflags v2.13.1
Downloaded equivalent v1.0.2
Downloaded allocator-api2 v0.2.21
Downloaded cfg-if v1.0.4
Downloaded darling_core v0.24.1
Downloaded indoc v2.0.7
Downloaded scopeguard v1.2.0
Downloaded defmt v1.1.1
Downloaded either v1.18.0
Downloaded signal-hook-mio v0.2.5
Downloaded compact_str v0.8.2
Downloaded static_assertions v1.1.0
Downloaded strsim v0.11.1
Downloaded unicode-ident v1.0.24
Downloaded jiff-core v0.1.0
Downloaded syn v2.0.119
Downloaded defmt-macros v1.1.1
Downloaded defmt-parser v1.0.0
Downloaded foldhash v0.1.5
Downloaded parking_lot v0.12.5
Downloaded rustix v0.38.44
Downloaded darling_macro v0.24.1
Downloaded thiserror v2.0.20
Downloaded unicase v2.9.0
Downloaded itoa v1.0.18
Downloaded paste v1.0.15
Downloaded serde_core v1.0.229
Downloaded quote v1.0.47
Downloaded mio v1.2.2
Downloaded ryu v1.0.23
Downloaded strum_macros v0.26.4
Downloaded jiff-static v0.2.35
Downloaded unicode-width v0.1.14
Downloaded log v0.4.34
Downloaded signal-hook v0.3.18
Downloaded crossterm v0.28.1
Downloaded hashbrown v0.15.5
Downloaded strum v0.26.3
Downloaded itertools v0.13.0
Downloaded heck v0.5.0
Downloaded redb v4.2.0
Downloaded syn v3.0.4
Downloaded jiff v0.2.35
Downloaded castaway v0.2.4
Downloaded rustversion v1.0.23
Downloaded instability v0.3.13
Downloaded errno v0.3.14
Downloaded lru v0.12.5
Downloaded smallvec v1.15.2
Downloaded parking_lot_core v0.9.12
Downloaded proc-macro2 v1.0.107
Downloaded ident_case v1.0.1
Downloaded thiserror-impl v2.0.20
Downloaded unicode-segmentation v1.13.3
Downloaded unicode-truncate v1.1.0
Downloaded darling v0.24.1
Downloaded pulldown-cmark v0.13.4
Downloaded unicode-width v0.2.0
Downloaded memchr v2.8.3
Downloaded linux-raw-sys v0.4.15
Downloaded signal-hook-registry v1.4.8
Downloaded ratatui v0.29.0
Downloaded libc v0.2.189
Downloaded lock_api v0.4.14
warning: linker stderr: ignoring deprecated linker optimization setting '1'
|
= note: `#[warn(linker_messages)]` on by default
warning: `tb-cli` (bin "tbc") generated 1 warning
warning: `tb-runner` (bin "tbrt") generated 1 warning (1 duplicate)
warning: `tb-ide` (bin "tb") generated 1 warning (1 duplicate)
Finished `release` profile [optimized] target(s) in 1.55s
+ cargo build --locked --release -p tb-export --bin tb-template
Finished `release` profile [optimized] target(s) in 0.04s
+ /work/target/release/tb-template --inspect /work/target/aarch64-unknown-linux-gnu/release/tb aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/aarch64-unknown-linux-gnu/release/tbc aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/aarch64-unknown-linux-gnu/release/tbrt aarch64-unknown-linux-gnu
+ /work/target/release/tb-template /tmp/tb-pack-3ccs00ug/tbrt aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-27ro6ib_/tb aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-27ro6ib_/tbc aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-27ro6ib_/tbrt aarch64-unknown-linux-gnu
/work/dist/terminalbasic-0.1.0-linux-arm64.tar.gz
+ /tmp/tb-unpacked-c072ix0x/tb --help
+ /usr/bin/python3 /work/tests/support/native-abnahme.py --bin-dir /tmp/tb-unpacked-c072ix0x --target aarch64-unknown-linux-gnu
+ /usr/bin/python3 /work/tests/support/library-abnahme.py --bin-dir /tmp/tb-unpacked-c072ix0x
+ /usr/bin/python3 /work/tests/support/ide-execution-pty.py --binary /tmp/tb-unpacked-c072ix0x/tb
+ rustup target add x86_64-unknown-linux-gnu
info: downloading component rust-std
+ cargo zigbuild --locked --release --target x86_64-unknown-linux-gnu.2.28 -p tb-ide -p tb-cli -p tb-runner --bins
Compiling libc v0.2.189
Compiling syn v3.0.4
Compiling rustversion v1.0.23
Compiling log v0.4.34
Compiling errno v0.3.14
Compiling ident_case v1.0.1
Compiling signal-hook v0.3.18
Compiling cfg-if v1.0.4
Compiling strsim v0.11.1
Compiling parking_lot_core v0.9.12
Compiling darling_core v0.24.1
Compiling signal-hook-registry v1.4.8
Compiling scopeguard v1.2.0
Compiling smallvec v1.15.2
Compiling bitflags v2.13.1
Compiling rustix v0.38.44
Compiling thiserror v2.0.20
Compiling lock_api v0.4.14
Compiling darling_macro v0.24.1
Compiling thiserror-impl v2.0.20
Compiling mio v1.2.2
Compiling syn v2.0.119
Compiling allocator-api2 v0.2.21
Compiling either v1.18.0
Compiling instability v0.3.13
Compiling equivalent v1.0.2
Compiling paste v1.0.15
Compiling foldhash v0.1.5
Compiling heck v0.5.0
Compiling linux-raw-sys v0.4.15
Compiling strum_macros v0.26.4
Compiling hashbrown v0.15.5
Compiling itertools v0.13.0
Compiling redb v4.2.0
Compiling signal-hook-mio v0.2.5
Compiling darling v0.24.1
Compiling parking_lot v0.12.5
Compiling castaway v0.2.4
Compiling itoa v1.0.18
Compiling ryu v1.0.23
Compiling unicode-width v0.2.0
Compiling static_assertions v1.1.0
Compiling unicode-segmentation v1.13.3
Compiling indoc v2.0.7
Compiling jiff-core v0.1.0
Compiling unicode-width v0.1.14
Compiling unicode-truncate v1.1.0
Compiling jiff v0.2.35
Compiling compact_str v0.8.2
Compiling crossterm v0.28.1
Compiling strum v0.26.3
Compiling lru v0.12.5
Compiling cassowary v0.3.0
Compiling ratatui v0.29.0
Compiling tb-runtime v0.1.0 (/work/crates/tb-runtime)
Compiling tb-frontend v0.1.0 (/work/crates/tb-frontend)
Compiling anyhow v1.0.104
Compiling tb-ui v0.1.0 (/work/crates/tb-ui)
Compiling tb-vm v0.1.0 (/work/crates/tb-vm)
Compiling tb-export v0.1.0 (/work/crates/tb-export)
Compiling pulldown-cmark v0.13.4
Compiling memchr v2.8.3
Compiling unicase v2.9.0
Compiling tb-runner v0.1.0 (/work/crates/tb-runner)
Compiling tb-ide v0.1.0 (/work/crates/tb-ide)
warning: linker stderr: ignoring deprecated linker optimization setting '1'
|
= note: `#[warn(linker_messages)]` on by default
warning: `tb-runner` (bin "tbrt") generated 1 warning
Compiling tb-cli v0.1.0 (/work/crates/tb-cli)
warning: `tb-ide` (bin "tb") generated 1 warning (1 duplicate)
warning: `tb-cli` (bin "tbc") generated 1 warning (1 duplicate)
Finished `release` profile [optimized] target(s) in 2m 23s
+ cargo build --locked --release -p tb-export --bin tb-template
Finished `release` profile [optimized] target(s) in 0.06s
+ /work/target/release/tb-template --inspect /work/target/x86_64-unknown-linux-gnu/release/tb x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/x86_64-unknown-linux-gnu/release/tbc x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/x86_64-unknown-linux-gnu/release/tbrt x86_64-unknown-linux-gnu
+ /work/target/release/tb-template /tmp/tb-pack-3e1u_9my/tbrt x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-lwy0qi08/tb x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-lwy0qi08/tbc x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-lwy0qi08/tbrt x86_64-unknown-linux-gnu
/work/dist/terminalbasic-0.1.0-linux-amd64.tar.gz
+ rustup target add aarch64-apple-darwin
info: downloading component rust-std
+ cargo zigbuild --locked --release --target aarch64-apple-darwin -p tb-ide -p tb-cli -p tb-runner --bins
Compiling libc v0.2.189
Compiling log v0.4.34
Compiling cfg-if v1.0.4
Compiling signal-hook v0.3.18
Compiling parking_lot_core v0.9.12
Compiling smallvec v1.15.2
Compiling bitflags v2.13.1
Compiling scopeguard v1.2.0
Compiling lock_api v0.4.14
Compiling rustix v0.38.44
Compiling thiserror v2.0.20
Compiling equivalent v1.0.2
Compiling allocator-api2 v0.2.21
Compiling errno v0.3.14
Compiling signal-hook-registry v1.4.8
Compiling mio v1.2.2
Compiling foldhash v0.1.5
Compiling either v1.18.0
Compiling itertools v0.13.0
Compiling signal-hook-mio v0.2.5
Compiling hashbrown v0.15.5
Compiling redb v4.2.0
Compiling parking_lot v0.12.5
Compiling castaway v0.2.4
Compiling ryu v1.0.23
Compiling static_assertions v1.1.0
Compiling unicode-width v0.2.0
Compiling unicode-segmentation v1.13.3
Compiling unicode-width v0.1.14
Compiling itoa v1.0.18
Compiling jiff-core v0.1.0
Compiling unicode-truncate v1.1.0
Compiling compact_str v0.8.2
Compiling jiff v0.2.35
Compiling crossterm v0.28.1
Compiling strum v0.26.3
Compiling lru v0.12.5
Compiling cassowary v0.3.0
Compiling ratatui v0.29.0
Compiling tb-runtime v0.1.0 (/work/crates/tb-runtime)
Compiling tb-frontend v0.1.0 (/work/crates/tb-frontend)
Compiling anyhow v1.0.104
Compiling tb-ui v0.1.0 (/work/crates/tb-ui)
Compiling tb-vm v0.1.0 (/work/crates/tb-vm)
Compiling tb-export v0.1.0 (/work/crates/tb-export)
Compiling pulldown-cmark v0.13.4
Compiling unicase v2.9.0
Compiling memchr v2.8.3
Compiling tb-runner v0.1.0 (/work/crates/tb-runner)
Compiling tb-ide v0.1.0 (/work/crates/tb-ide)
Compiling tb-cli v0.1.0 (/work/crates/tb-cli)
Finished `release` profile [optimized] target(s) in 2m 16s
+ cargo build --locked --release -p tb-export --bin tb-template
Finished `release` profile [optimized] target(s) in 0.06s
+ /work/target/release/tb-template --inspect /work/target/aarch64-apple-darwin/release/tb aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /work/target/aarch64-apple-darwin/release/tbc aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /work/target/aarch64-apple-darwin/release/tbrt aarch64-apple-darwin
+ /work/target/release/tb-template /tmp/tb-pack-ymsier7a/tbrt aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /tmp/tb-package-e391lcwl/tb aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /tmp/tb-package-e391lcwl/tbc aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /tmp/tb-package-e391lcwl/tbrt aarch64-apple-darwin
/work/dist/terminalbasic-0.1.0-macos-arm64.tar.gz

View File

@@ -0,0 +1,279 @@
info: syncing channel updates for '1.97.1-aarch64-unknown-linux-gnu'
info: latest update on 2026-07-16, rust version 1.97.1 (8bab26f4f 2026-07-14)
info: component 'clippy' for target 'aarch64-unknown-linux-gnu' is up to date
info: component 'rustfmt' for target 'aarch64-unknown-linux-gnu' is up to date
1.97.1-aarch64-unknown-linux-gnu unchanged - rustc 1.97.1 (8bab26f4f 2026-07-14)
info: checking for self-update
info: downloading self-update
/tmp/tb-7zip.tar.xz: OK
rustc 1.97.1 (8bab26f4f 2026-07-14)
7-Zip (z) 25.01 (arm64) : Copyright (c) 1999-2025 Igor Pavlov : 2025-08-03
64-bit arm_v:8-A locale=C.UTF-8 Threads:4 OPEN_MAX:1024, ASM
+ rustup target add x86_64-pc-windows-msvc
info: component rust-std for target x86_64-pc-windows-msvc is up to date
+ cargo xwin build --locked --release --target x86_64-pc-windows-msvc -p tb-ide -p tb-cli -p tb-runner --bins
Updating crates.io index
Downloading crates ...
Downloaded indoc v2.0.7
Downloaded bitflags v2.13.1
Downloaded heck v0.5.0
Downloaded paste v1.0.15
Downloaded bitflags v1.3.2
Downloaded strum_macros v0.26.4
Downloaded anyhow v1.0.104
Downloaded syn v3.0.4
Downloaded allocator-api2 v0.2.21
Downloaded cassowary v0.3.0
Downloaded windows-sys v0.59.0
Downloaded unicode-segmentation v1.13.3
Downloaded defmt-parser v1.0.0
Downloaded parking_lot v0.12.5
Downloaded thiserror v2.0.20
Downloaded thiserror-impl v2.0.20
Downloaded castaway v0.2.4
Downloaded jiff-tzdb v0.1.8
Downloaded static_assertions v1.1.0
Downloaded windows-link v0.2.1
Downloaded darling_macro v0.24.1
Downloaded errno v0.3.14
Downloaded defmt-macros v1.1.1
Downloaded jiff-static v0.2.35
Downloaded cfg-if v1.0.4
Downloaded log v0.4.34
Downloaded lru v0.12.5
Downloaded serde_core v1.0.229
Downloaded rustversion v1.0.23
Downloaded unicode-truncate v1.1.0
Downloaded signal-hook v0.3.18
Downloaded signal-hook-mio v0.2.5
Downloaded unicase v2.9.0
Downloaded scopeguard v1.2.0
Downloaded windows-targets v0.52.6
Downloaded defmt v1.1.1
Downloaded ident_case v1.0.1
Downloaded jiff-tzdb-platform v0.1.3
Downloaded quote v1.0.47
Downloaded strsim v0.11.1
Downloaded strum v0.26.3
Downloaded itoa v1.0.18
Downloaded equivalent v1.0.2
Downloaded instability v0.3.13
Downloaded foldhash v0.1.5
Downloaded smallvec v1.15.2
Downloaded crossterm_winapi v0.9.1
Downloaded signal-hook-registry v1.4.8
Downloaded either v1.18.0
Downloaded parking_lot_core v0.9.12
Downloaded ryu v1.0.23
Downloaded compact_str v0.8.2
Downloaded darling_core v0.24.1
Downloaded lock_api v0.4.14
Downloaded proc-macro2 v1.0.107
Downloaded unicode-ident v1.0.24
Downloaded darling v0.24.1
Downloaded memchr v2.8.3
Downloaded mio v1.2.2
Downloaded crossterm v0.28.1
Downloaded jiff-core v0.1.0
Downloaded itertools v0.13.0
Downloaded hashbrown v0.15.5
Downloaded pulldown-cmark v0.13.4
Downloaded unicode-width v0.2.0
Downloaded redb v4.2.0
Downloaded unicode-width v0.1.14
Downloaded rustix v0.38.44
Downloaded syn v2.0.119
Downloaded ratatui v0.29.0
Downloaded jiff v0.2.35
Downloaded libc v0.2.189
Downloaded windows_x86_64_msvc v0.52.6
Downloaded winapi v0.3.9
Downloaded linux-raw-sys v0.4.15
Downloaded windows-sys v0.61.2
warning: linker stderr: lld-link: Cannot use debug info for 'libcmt.lib(std_type_info_static.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(fltused.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(tlssup.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(delete_scalar_size.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(gs_cookie.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(guard_support.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(delete_scalar.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(initializers.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(utility_desktop.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(gshandler.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(gs_report.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(throw.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(riscchandler.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(risctrnsctrl.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(ehhelpers.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(cpu_disp.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(pesect.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(jbcxrval.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(per_thread_data.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(ehstate.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(frame.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(wcschr.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(winapi_downlevel.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(std_exception.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(std_type_info.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(gshandlerseh.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(undname.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(purevirt.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(locks.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(purevirt_data.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(strrchr.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(jmpuwind.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(exe_main.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(loadcfg.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(utility.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(gs_support.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(matherr.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(argv_mode.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(commit_mode.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(file_mode.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(new_mode.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(thread_locale.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(tncleanup.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(env_mode.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(invalid_parameter_handler.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(denormal_control.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(default_local_stdio_options.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(matherr_detection.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(dyn_tls_init.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(dyn_tls_dtor.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(initsect.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(softmemtag.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(initialization.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libcmt.lib(ucrt_detection.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libcmt.amd64.pdb': No such file or directory
lld-link: Cannot use debug info for 'libvcruntime.lib(strchr.obj)' [LNK4099]
>>> failed to load reference 'D:\a\_work\1\s\binaries\amd64ret\lib\amd64\libvcruntime.amd64.pdb': No such file or directory
|
= note: `#[warn(linker_messages)]` on by default
warning: `tb-runner` (bin "tbrt") generated 1 warning
warning: `tb-ide` (bin "tb") generated 1 warning (1 duplicate)
warning: `tb-cli` (bin "tbc") generated 1 warning (1 duplicate)
Finished `release` profile [optimized] target(s) in 1.75s
+ cargo build --locked --release -p tb-export --bin tb-template
Finished `release` profile [optimized] target(s) in 0.04s
+ /work/target/release/tb-template --inspect /work/target/x86_64-pc-windows-msvc/release/tb.exe x86_64-pc-windows-msvc
+ /work/target/release/tb-template --inspect /work/target/x86_64-pc-windows-msvc/release/tbc.exe x86_64-pc-windows-msvc
+ /work/target/release/tb-template --inspect /work/target/x86_64-pc-windows-msvc/release/tbrt.exe x86_64-pc-windows-msvc
+ /work/target/release/tb-template /tmp/tb-pack-am6i0jvn/runtimes/x86_64-pc-windows-msvc/tbrt.exe x86_64-pc-windows-msvc
+ /usr/local/bin/7zz a -t7z /work/dist-pinned/terminalbasic-0.1.0-windows-amd64.7z INSTALL.txt LICENSE manifest.json runtimes/x86_64-pc-windows-msvc/tbrt.exe runtimes/x86_64-pc-windows-msvc/tbrt.exe.meta tb.exe tbc.exe
+ /usr/local/bin/7zz x -y -o/tmp/tb-package-5j84dd93 -- /work/dist-pinned/terminalbasic-0.1.0-windows-amd64.7z
+ /work/target/release/tb-template --inspect /tmp/tb-package-5j84dd93/tb.exe x86_64-pc-windows-msvc
+ /work/target/release/tb-template --inspect /tmp/tb-package-5j84dd93/tbc.exe x86_64-pc-windows-msvc
+ /work/target/release/tb-template --inspect /tmp/tb-package-5j84dd93/runtimes/x86_64-pc-windows-msvc/tbrt.exe x86_64-pc-windows-msvc
/work/dist-pinned/terminalbasic-0.1.0-windows-amd64.7z

View File

@@ -0,0 +1,24 @@
Compiling tb-vm v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-vm)
Compiling tb-export v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-export)
Finished `test` profile [unoptimized + debuginfo] target(s) in 3.69s
Running unittests src/lib.rs (target/debug/deps/tb_export-25aa117d19f46d7a)
running 3 tests
test tests::publication_preserves_originals_on_conflict_failure_race_and_cancel ... ok
test tests::fehlgeschlagene_native_finalisierung_erhaelt_das_ziel ... ok
test tests::targets_versions_integrity_and_payload_bounds_are_enforced ... ok
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.07s
Running unittests src/bin/tb-template.rs (target/debug/deps/tb_template-ef8c38310b67cef7)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests tb_export
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

View File

@@ -0,0 +1,12 @@
{
".gitea/INSTALL.txt": "8dedd68d8c03e56a6f322bad6451a0403eca3abf2fffb3260dd07a8c6a5ba98f",
".gitea/scripts/acceptance.py": "89d84d678095be7cd3ffb8bd8ea40cb2312f77f4776ecec4544bcc1cbc24b51a",
".gitea/scripts/bootstrap.sh": "ac6d7d605fcb314c2a267fbe549ce54a5bce562d4c4a173f5e1f25eeeebba2a3",
".gitea/scripts/build.py": "71f00d0fc41b998a168e7599b6c619ebfcc80f61695ff25d5c5233ee98111644",
".gitea/scripts/distribution.py": "de9b1ec3cd189102952372937daa72e0566cb342286b7c3b2f8fd8a72ccb28f6",
".gitea/scripts/publish.py": "e5598cd5399dca58c01a118d2ecf044126f0de5226be05d1e64edbc51c955804",
".gitea/scripts/release.py": "fe0e3fc55e22de10bfc244623f0df3395cececc474834a844fe850bc70468c93",
".gitea/scripts/test_distribution.py": "f09463bb8528dedc5df7dd98f85c4d04e2231a5821f528a6e32400231f4f5c4b",
".gitea/workflows/build.yml": "60842092d3ce09dcf7e303a1186dfdd3f409a47c314c18bcde90eb644930322f",
".gitea/workflows/publish.yml": "30dff7b2045b80d5961407bc501334c3c9fa154133fa3d8eb925e5e87d0d3592"
}

View File

@@ -0,0 +1,3 @@
PASS {'shell_exit': 7}
PASS {'abort': True}
PASS {'file_shell': True}

View File

@@ -0,0 +1 @@
{"target": "aarch64-unknown-linux-gnu", "tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df", "native_execution": true, "source_free": true, "run_reset": true, "output": " 1 \n 7 3 9 1 \nTB \n"}

View File

@@ -0,0 +1,13 @@
PASS native console
PASS native restart
PASS native stop
PASS native error
PASS native project
PASS native form
PASS native external
PASS PTY Eingabe, Abbruch und Wiederherstellung (CLI/native)
PASS Exportabbruch SIGINT/SIGTERM, Original und Bereinigung
PASS corrupted length
PASS corrupted version
PASS corrupted truncated
Native Abnahme bestanden: aarch64-unknown-linux-gnu

View File

@@ -0,0 +1,16 @@
{
"target": "aarch64-unknown-linux-gnu",
"revision": "796564795a6607651c366c6b0de74560af55e71a",
"package": "terminalbasic-0.1.0-linux-arm64.tar.gz",
"package_sha256": "e1eff42146202fe4694b8812a17acfc9337a454a27c0ef36d53a3fc776088b81",
"tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df",
"host": "Linux-6.8.0-139-generic-aarch64-with-glibc2.41",
"automated_passed": true,
"manual_terminal_passed": false,
"checks": {
"default-template": "passed",
"native": "passed",
"library": "passed",
"ide-pty": "passed"
}
}

View File

@@ -0,0 +1,12 @@
{
"revision": "796564795a6607651c366c6b0de74560af55e71a",
"passed": true,
"buildhost": "macOS-26.6.2-arm64-arm-64bit-Mach-O",
"run_url": "local-verification",
"foreign": true,
"inventory": true,
"workspace": true,
"benchmarks": true,
"native_ide": true,
"log_sha256": "f3b51d1f0155b0d8f33435f23206073d2dd19c7bad56c23ac7e4c32abe50af30"
}

View File

@@ -0,0 +1,12 @@
Finished `release` profile [optimized] target(s) in 0.06s
Finished `release` profile [optimized] target(s) in 0.01s
Running `target/release/tb-template /private/var/folders/qv/bccsf2nd15lgm71zrpylrc_80000gn/T/tb-ci-runtime-w6n0ip1v/runtime/aarch64-apple-darwin/tbrt aarch64-apple-darwin`
/private/var/folders/qv/bccsf2nd15lgm71zrpylrc_80000gn/T/tb-ci-runtime-w6n0ip1v/runtime/aarch64-apple-darwin
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.03s
Running unittests src/main.rs (target/debug/deps/tbc-a3652d07eb423d84)
running 1 test
test ide_acceptance::real_native_ide_exports_and_source_free_cli_library_consumer ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 6 filtered out; finished in 0.68s

View File

@@ -0,0 +1,112 @@
- Validating...
✓ spec/bytecode-kompilat
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/datei-eio
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/ereignissteuerung
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/forms-dateiformat
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/forms-objektmodell
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/forms-steuerelemente
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/ide-ausfuehrung
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/ide-debugger
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/ide-editor
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/ide-formulardesigner
✓ spec/ide-hilfe
✓ spec/ide-native-exporte
✓ spec/ide-oberflaeche
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/ide-phasenabnahme
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/ide-projekte
✓ spec/isam-datenbank
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/kompat-testkorpus
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/konsolen-basisbibliothek
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[9]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[11]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/laufzeitfehler
✓ spec/native-executables
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/pcode-bibliotheken
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ change/phase-6-06-gitea-actions-und-releases
✓ change/phase-6-07-dokumentation-und-phasenabnahme
✓ spec/release-kompatibilitaet
✓ spec/sprach-frontend
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[11]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[13]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/sprachinventar
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/terminal-plattformmatrix
[INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/textbildschirm
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[9]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/vm-ausfuehrung
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
[INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
✓ spec/vm-fehlerbehandlung
[INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
Totals: 30 passed, 0 failed (30 items)

View File

@@ -0,0 +1,6 @@
{
"terminalbasic-0.1.0-linux-amd64.tar.gz": "2ced064df0d1c8b041f23df1a668787d22933b2f6be646e01f73061cc20a4e04",
"terminalbasic-0.1.0-linux-arm64.tar.gz": "e1eff42146202fe4694b8812a17acfc9337a454a27c0ef36d53a3fc776088b81",
"terminalbasic-0.1.0-macos-arm64.tar.gz": "369882d9962f0264f41a7dfc0e352acb826c43d84a3c8babd028636a24aeaf4d",
"terminalbasic-0.1.0-windows-amd64.7z": "8fb79b0e34f2a496a93e90f87c70d9bff2d5b38b77087a123518491d0964e092"
}

View File

@@ -0,0 +1,5 @@
.....
----------------------------------------------------------------------
Ran 5 tests in 0.017s
OK

View File

@@ -0,0 +1,30 @@
+ /work/target/release/tb-template --inspect /work/target/aarch64-unknown-linux-gnu/release/tb aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/aarch64-unknown-linux-gnu/release/tbc aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/aarch64-unknown-linux-gnu/release/tbrt aarch64-unknown-linux-gnu
+ /work/target/release/tb-template /tmp/tb-pack-o13p5pm9/runtimes/aarch64-unknown-linux-gnu/tbrt aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-g7jby_v7/tb aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-g7jby_v7/tbc aarch64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-g7jby_v7/runtimes/aarch64-unknown-linux-gnu/tbrt aarch64-unknown-linux-gnu
/work/dist-final/terminalbasic-0.1.0-linux-arm64.tar.gz
+ /tmp/tb-unpacked-akoqbup6/tb --help
+ /tmp/tb-unpacked-akoqbup6/tbc build /tmp/tb-unpacked-akoqbup6/hello.bas --exe --target aarch64-unknown-linux-gnu -o /tmp/tb-unpacked-akoqbup6/hello
/tmp/tb-unpacked-akoqbup6/hello
+ /usr/bin/python3 /work/tests/support/native-abnahme.py --bin-dir /tmp/tb-unpacked-akoqbup6 --target aarch64-unknown-linux-gnu
+ /usr/bin/python3 /work/tests/support/library-abnahme.py --bin-dir /tmp/tb-unpacked-akoqbup6
+ /usr/bin/python3 /work/tests/support/ide-execution-pty.py --binary /tmp/tb-unpacked-akoqbup6/tb
+ /work/target/release/tb-template --inspect /work/target/x86_64-unknown-linux-gnu/release/tb x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/x86_64-unknown-linux-gnu/release/tbc x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /work/target/x86_64-unknown-linux-gnu/release/tbrt x86_64-unknown-linux-gnu
+ /work/target/release/tb-template /tmp/tb-pack-lrb4e1pp/runtimes/x86_64-unknown-linux-gnu/tbrt x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-1agxs6xy/tb x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-1agxs6xy/tbc x86_64-unknown-linux-gnu
+ /work/target/release/tb-template --inspect /tmp/tb-package-1agxs6xy/runtimes/x86_64-unknown-linux-gnu/tbrt x86_64-unknown-linux-gnu
/work/dist-final/terminalbasic-0.1.0-linux-amd64.tar.gz
+ /work/target/release/tb-template --inspect /work/target/aarch64-apple-darwin/release/tb aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /work/target/aarch64-apple-darwin/release/tbc aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /work/target/aarch64-apple-darwin/release/tbrt aarch64-apple-darwin
+ /work/target/release/tb-template /tmp/tb-pack-dlq0c_7h/runtimes/aarch64-apple-darwin/tbrt aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /tmp/tb-package-w9maj5ky/tb aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /tmp/tb-package-w9maj5ky/tbc aarch64-apple-darwin
+ /work/target/release/tb-template --inspect /tmp/tb-package-w9maj5ky/runtimes/aarch64-apple-darwin/tbrt aarch64-apple-darwin
/work/dist-final/terminalbasic-0.1.0-macos-arm64.tar.gz

View File

@@ -0,0 +1,161 @@
diff --git a/.gitignore b/.gitignore
index b7141ea..15c6f97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,8 @@
/target
**/*.rs.bk
*.pdb
+/dist
+/acceptance
+/artifacts
+/packages
+**/__pycache__
diff --git a/crates/tb-export/src/bin/tb-template.rs b/crates/tb-export/src/bin/tb-template.rs
index 7776b1a..c1ed101 100644
--- a/crates/tb-export/src/bin/tb-template.rs
+++ b/crates/tb-export/src/bin/tb-template.rs
@@ -1,10 +1,23 @@
//! Builder-Hilfe: geprüfte Metadaten für eine frisch gebaute Runtime schreiben.
fn main() -> anyhow::Result<()> {
- let args: Vec<_> = std::env::args().skip(1).collect();
+ let mut args: Vec<_> = std::env::args().skip(1).collect();
+ let inspect = args.first().is_some_and(|s| s == "--inspect");
+ if inspect {
+ args.remove(0);
+ }
anyhow::ensure!(
args.len() == 2,
- "Aufruf: tb-template <tbrt-Pfad> <Target-Triple>"
+ "Aufruf: tb-template [--inspect] <Executable-Pfad> <Target-Triple>"
);
+ if inspect {
+ let found = tb_export::native_target(&std::fs::read(&args[0])?)?;
+ anyhow::ensure!(
+ found == tb_export::Target::parse(&args[1])?,
+ "Executable hat falsches Ziel"
+ );
+ println!("{}", found.triple());
+ return Ok(());
+ }
tb_export::prepare_template(
std::path::Path::new(&args[0]),
tb_export::Target::parse(&args[1])?,
diff --git a/openspec/changes/phase-6-06-gitea-actions-und-releases/design.md b/openspec/changes/phase-6-06-gitea-actions-und-releases/design.md
index 9ed6dd3..8134698 100644
--- a/openspec/changes/phase-6-06-gitea-actions-und-releases/design.md
+++ b/openspec/changes/phase-6-06-gitea-actions-und-releases/design.md
@@ -12,7 +12,7 @@ Origin ist `https://git.rfc1437.de/hugo/TerminalBasic.git`; die read-only Versio
1. `.gitea/workflows/` nutzt den vorhandenen Linux-arm64-Runner für alle vier Build-/Paketziele. Vorhandene Workflowmuster der anderen Origin-Projekte wiederverwenden: cargo-zigbuild für Linux amd64 und macOS arm64, cargo-xwin für Windows amd64/MSVC; Linux arm64 nativ oder mit derselben festgelegten Linux-Zielbaseline. Container/Tools und benötigte SDKs/Sysroots reproduzierbar pinnen; konkrete Rust-/OS-/glibc-Versionen mit TerminalBasic prüfen. Das Runnerlabel `linux-arm64` bei Anbindung bestätigen. Vier native Buildrunner sind nicht erforderlich. `build-runtime.py` erzeugt Vorlagenmetadaten mit dem Hostwerkzeug für das jeweilige Target; fremde Executables werden auf dem Buildhost nicht nativ ausgeführt.
2. Wiederverwendbare Repository-Skripte erledigen Build, Tests, Paketierung und Prüfung auch lokal. Source-Checkout vom Gitea-Origin, alle zusätzlichen Actions nur über explizite Gitea-URLs und feste Revisionen, soweit überhaupt nötig; keine implizite fremde Action-Auflösung. Rust und benötigte Systemwerkzeuge versioniert bereitstellen. Server-/Runner-Kompatibilität praktisch prüfen, statt lediglich YAML zu validieren.
-3. Matrixprodukte: `terminalbasic-<version>-windows-amd64.7z`, `terminalbasic-<version>-macos-arm64.tar.gz`, `terminalbasic-<version>-linux-amd64.tar.gz`, `terminalbasic-<version>-linux-arm64.tar.gz`. Windows enthält `tb.exe`/`tbc.exe`/`tbrt.exe`, übrige `tb`/`tbc`/`tbrt`; tbrt ist die native Exportvorlage, dazu deren Metadaten, Lizenz, Kurzinstallation. Archive dürfen keine Buildverzeichnis-/Quellbaumabhängigkeiten haben. Exportierte Anwenderprogramme bleiben normale native Einzelartefakte; die Archivformate betreffen die Distribution.
+3. Matrixprodukte: `terminalbasic-<version>-windows-amd64.7z`, `terminalbasic-<version>-macos-arm64.tar.gz`, `terminalbasic-<version>-linux-amd64.tar.gz`, `terminalbasic-<version>-linux-arm64.tar.gz`. Windows enthält `tb.exe`/`tbc.exe`/`tbrt.exe`, übrige `tb`/`tbc`/`tbrt`; tbrt ist die native Exportvorlage unter `runtimes/<Target-Triple>/`, dazu deren Metadaten, Lizenz, Kurzinstallation. Das vorhandene CLI-/IDE-Suchschema bleibt erhalten. Archive dürfen keine Buildverzeichnis-/Quellbaumabhängigkeiten haben. Exportierte Anwenderprogramme bleiben normale native Einzelartefakte; die Archivformate betreffen die Distribution.
4. Der Linux-Buildhost erzeugt/prüft Windows-Archive mit 7-Zip und Unix-Archive mit tar+gzip unter Erhalt der Executable-Bits. Inhalts-/Formatprüfungen laufen dort; tatsächliche Start-/Exportprüfungen verwenden neu entpackte Pakete auf passenden Zielsystemen aus 05, automatisiert oder dokumentiert manuell. Externe Nachweise müssen an Revision und exakte Paketprüfsumme gebunden und vor Freigabe geprüft sein. Ein gemeinsames TBL-Testartefakt wird einmal erzeugt und mit nachgewiesen identischen Bytes auf allen vier Zielsystemen verwendet. Separate BASIC-Verbraucher werden mit den entpackten TB-Tools verknüpft, als TBC ausgeführt und mit tbrt als EXE exportiert. Library-Quellen sind dabei nicht verfügbar. Erzeugung/Linken werden in einer Umgebung ohne erreichbaren C-/Rust-Compiler oder nativen Linker geprüft; Systemhilfen zur EXE-Finalisierung dürfen verfügbar bleiben. Fertige EXEs laufen anschließend ohne externe TBL/TBC oder TB-Installation.
5. `cargo test --locked --workspace`, Clippy und Formatprüfung zentral auf dem Linux-arm64-Host; zielabhängige Rust-Testprogramme bei Bedarf cross-kompilieren und auf passenden Prüfsystemen ausführen. Native Tests aus 02/03/04 und automatisierbare Plattformtests aus 05 auf ihren tatsächlichen Zielen ausführen. Buildstatus und Ausführungsnachweise getrennt ausweisen; macOS-EXE-Finalisierung mit codesign erfolgt auf macOS. Den fixierten Fremdprogrammbestand ausdrücklich im erforderlichen Abnahmelauf bereitstellen. Compile-/VM-Messungen auf dokumentiertem Referenzrunner statt instabiler Debug-Zeitlimits in allen Jobs.
6. Gitea-Release erst nach allen Pflichtjobs, zugeordneten echten Zielnachweisen und Vollständigkeits-/Prüfsummenprüfung freigeben. Upload zunächst zu einem als Entwurf erkennbaren Release oder gleichwertigem nicht freigegebenen Staging; anschließend atomare Freigabe im Rahmen der verfügbaren API. PR-Jobs ohne Veröffentlichungsrechte und ohne Release-Secrets; fremder PR-Code darf nicht mit solchen Rechten auf persönlichen Runnern laufen. Zugangswerte werden als Gitea-Secrets konfiguriert, nicht committed. Tests erzeugen keine öffentlichen Testreleases.
@@ -28,3 +28,20 @@ Origin ist `https://git.rfc1437.de/hugo/TerminalBasic.git`; die read-only Versio
## Migration Plan
Lokale Skripte zuerst lauffähig machen, dann Gitea-Runner und Workflows anbinden. PR-/Push-Lauf ohne Veröffentlichung prüfen; kontrollierter Tag-/Release-Lauf nach erfolgreicher Matrix. Bisherige lokale Cargo-Nutzung erhalten. Rollback über vorheriges vollständiges Release und Rücknahme der Workflowänderung; keine Server-/Runnerinstallation durch bloße Proposal-Erstellung.
+
+## Konkretisierung während der Umsetzung
+
+- Rust 1.97.1, vorhandene Cross-Images per Digest, 7-Zip 25.01 per SHA-256.
+ SDK-/CRT-Versionen und ein Hash ihrer exakten Header-/Library-Bytes sind
+ für Windows fixiert; macOS-SDK/Zig stammen aus dem gepinnten Image.
+- `tb-template --inspect` nutzt den vorhandenen PE/ELF/Mach-O-Parser auch
+ für tb/tbc. Build und Paketprüfung laufen auf dem Host ohne fremde Programme
+ auszuführen. Die Anwenderpakete benötigen tb-template nicht.
+- Taglauf erzeugt erst nach Build/Grundabnahme einen überprüften Entwurf.
+ Originalpakete werden auf separaten Systemen geprüft. Ein manueller Workflow
+ auf main bindet deren Nachweise aus einem Origin-Commit an Tag, Revision und
+ Paket-SHA-256 und gibt erst dann denselben Entwurf frei; kein erneuter Bau.
+- Die Benutzerentscheidung aus 05, Windows-Ausführung vorerst offen zu lassen,
+ bleibt erhalten. Sie macht Windows-Builds zulässig, aber keinen Release mit
+ fehlender Windows-Abnahme erfolgreich. Fehlende Nachweise werden nicht auf
+ Basis der gemeinsamen ANSI-Technik von macOS/Linux pauschal abgehakt.
diff --git a/openspec/changes/phase-6-06-gitea-actions-und-releases/tasks.md b/openspec/changes/phase-6-06-gitea-actions-und-releases/tasks.md
index 3f1d0c2..a226e36 100644
--- a/openspec/changes/phase-6-06-gitea-actions-und-releases/tasks.md
+++ b/openspec/changes/phase-6-06-gitea-actions-und-releases/tasks.md
@@ -1,19 +1,27 @@
## 1. Gitea und Runner
- [ ] 1.1 Vorhandenen Linux-arm64-Gitea-Runner und tatsächliches Label bestätigen; Cross-Buildumgebungen mit cargo-zigbuild, cargo-xwin und benötigten SDKs/Sysroots reproduzierbar festlegen. Ein Gitea-Prüfjob muss den Buildhost nachweisen; separate echte Prüfsysteme aus 05 zuordnen, ohne vier native Buildrunner vorauszusetzen.
-- [ ] 1.2 Repositorylokale Build-/Testaufrufe und feste Toolchain-/Systemvoraussetzungen bereitstellen; alle vier Ziele müssen auf Linux arm64 mit --locked baubar sein. Zentrale Workspace-Regressionen und getrennte Aufrufe für echte Zielprüfungen bereitstellen; fremde Executables nicht als nativ auf dem Buildhost getestet ausweisen.
+- [x] 1.2 Repositorylokale Build-/Testaufrufe und feste Toolchain-/Systemvoraussetzungen bereitstellen; alle vier Ziele müssen auf Linux arm64 mit --locked baubar sein. Zentrale Workspace-Regressionen und getrennte Aufrufe für echte Zielprüfungen bereitstellen; fremde Executables nicht als nativ auf dem Buildhost getestet ausweisen.
- [ ] 1.3 Push-/PR-Workflow unter .gitea/workflows anbinden; ein tatsächlicher Origin-Lauf muss vier Zielergebnisse und Fehlerstatus liefern, ohne Release-Secrets im PR-Pfad.
## 2. Artefakte und Pakete
- [ ] 2.1 IDE, CLI und native `tbrt`-Exportvorlage je Ziel in Gitea Actions bauen; Format-/Architektur-/Versionsprüfungen müssen Windows amd64, macOS arm64 und beide Linux-Architekturen eindeutig bestätigen.
-- [ ] 2.2 Windows-Paket als .7z und macOS-/Linux-Pakete als .tar.gz erzeugen; Archivtests müssen Dateinamen, Paketinhalt, Executable-Rechte und notwendige Begleitdateien prüfen.
+- [x] 2.2 Windows-Paket als .7z und macOS-/Linux-Pakete als .tar.gz erzeugen; Archivtests müssen Dateinamen, Paketinhalt, Executable-Rechte und notwendige Begleitdateien prüfen.
- [ ] 2.3 Jedes fertige Paket auf dem tatsächlichen Ziel neu entpacken und die enthaltenen Programme starten; automatisierte oder dokumentiert manuelle Nachweise aus separaten Prüfsystemen an Revision und Paketprüfsumme binden; `tbc link` und EXE-/TBL-Beispiele müssen mit separaten BASIC-Verbrauchern ohne Library-Quellen/Entwicklungscheckout sowie ohne erreichbaren C-/Rust-Compiler oder nativen Linker funktionieren.
-- [ ] 2.4 Einmal erzeugte TBL-Probe mit identischen Bytes an alle vier Zielprüfungen verteilen sowie Artefaktmanifest und Prüfsummen erzeugen; absichtlich beschädigte oder vertauschte Zielartefakte müssen die Prüfung scheitern lassen.
+- [x] 2.4 Einmal erzeugte TBL-Probe mit identischen Bytes an alle vier Zielprüfungen verteilen sowie Artefaktmanifest und Prüfsummen erzeugen; absichtlich beschädigte oder vertauschte Zielartefakte müssen die Prüfung scheitern lassen.
## 3. Releasepfad
- [ ] 3.1 Taggebundenen Gitea-Releasepfad mit vollständiger Pflichtasset-Liste und getrennten Rechten einrichten; fehlgeschlagene/fehlende Zielbuilds oder zugeordnete echte Paket-/Zielprüfungen müssen die Freigabe verhindern.
-- [ ] 3.2 Upload zunächst als nicht freigegebenen Stand prüfen und erst vollständig freigeben; ein simulierter fehlender Upload darf keinen vollständigen bestehenden Release überschreiben.
-- [ ] 3.3 Fremdprogramm-, Inventar-, native und automatisierte Plattformnachweise sowie Referenzbenchmarks in den erforderlichen Abnahmelauf integrieren; ignorierte Pflichtfälle müssen als fehlend sichtbar bleiben.
+- [x] 3.2 Upload zunächst als nicht freigegebenen Stand prüfen und erst vollständig freigeben; ein simulierter fehlender Upload darf keinen vollständigen bestehenden Release überschreiben.
+- [x] 3.3 Fremdprogramm-, Inventar-, native und automatisierte Plattformnachweise sowie Referenzbenchmarks in den erforderlichen Abnahmelauf integrieren; ignorierte Pflichtfälle müssen als fehlend sichtbar bleiben.
- [ ] 3.4 Einen tatsächlichen vollständigen Gitea-Lauf mit vier Paketartefakten nachweisen; Run-/Commit-/Buildhost-/Targetdaten und paketprüfsummengebundene entpackte Prüfergebnisse an 07 übergeben, bevor der Change als fertig gilt.
+
+Stand 07.09.2026: Repository-Implementierung und lokale Prüfungen vorhanden.
+Alle vier Ziele wurden in den fixierten Containern auf Linux arm64 gebaut;
+Linux-arm64- und cross-kompilierte macOS-Pakete bestehen echte entpackte
+Automatikprüfungen. Das ist noch kein Actions-Lauf. 1.1/1.3/2.1/3.4 bleiben
+wegen des defekten gemeinsamen Runners offen; 2.3 wegen Windows/Linux-amd64
+und den restlichen visuellen Zielnachweisen. 3.1 bleibt bis zur Einrichtung
+des Releasezugangs und tatsächlichen Rechteprüfung offen. Details: verification.md.
diff --git a/tests/support/library-abnahme.py b/tests/support/library-abnahme.py
index c596219..003e064 100644
--- a/tests/support/library-abnahme.py
+++ b/tests/support/library-abnahme.py
@@ -63,8 +63,15 @@ def main():
library = root / 'library.tbl'
shutil.copyfile(args.library, library)
template = root / ('runtime' + suffix)
- shutil.copy2(binaries / ('tbrt' + suffix), template)
- run([template_tool, template, target], root, env)
+ runtime = binaries / ('tbrt' + suffix)
+ if not runtime.is_file():
+ runtime = binaries / 'runtimes' / target / ('tbrt' + suffix)
+ shutil.copy2(runtime, template)
+ metadata = Path(str(runtime) + '.meta')
+ if metadata.is_file():
+ shutil.copyfile(metadata, Path(str(template) + '.meta'))
+ else:
+ run([template_tool, template, target], root, env)
source = root / 'consumer.bas'
source.write_text(SOURCE, encoding='utf-8')
linked = root / 'consumer.tbc'
diff --git a/tests/support/native-abnahme.py b/tests/support/native-abnahme.py
index 78f4c2a..837d868 100644
--- a/tests/support/native-abnahme.py
+++ b/tests/support/native-abnahme.py
@@ -76,13 +76,19 @@ def main():
suffix = '.exe' if args.target == 'x86_64-pc-windows-msvc' else ''
tbc = binaries / ('tbc' + suffix)
rt = binaries / ('tbrt' + suffix)
+ if not rt.is_file():
+ rt = binaries / 'runtimes' / args.target / ('tbrt' + suffix)
prepare = binaries / ('tb-template' + suffix)
env = dict(os.environ, PATH='') # weder Cargo noch tbc/tbrt über PATH auflösbar
with tempfile.TemporaryDirectory(prefix='tb-native-') as work:
root = Path(work)
template = root / ('runtime' + suffix)
shutil.copy2(rt, template)
- must(run([prepare, template, args.target], root))
+ metadata = Path(str(rt) + '.meta')
+ if metadata.is_file():
+ shutil.copyfile(metadata, Path(str(template) + '.meta'))
+ else:
+ must(run([prepare, template, args.target], root))
empty = run([template], root, env=env)
assert empty.returncode == 1 and b'Nutzlast' in empty.stderr, empty
cases = {

View File

@@ -1,19 +1,27 @@
## 1. Gitea und Runner ## 1. Gitea und Runner
- [ ] 1.1 Vorhandenen Linux-arm64-Gitea-Runner und tatsächliches Label bestätigen; Cross-Buildumgebungen mit cargo-zigbuild, cargo-xwin und benötigten SDKs/Sysroots reproduzierbar festlegen. Ein Gitea-Prüfjob muss den Buildhost nachweisen; separate echte Prüfsysteme aus 05 zuordnen, ohne vier native Buildrunner vorauszusetzen. - [ ] 1.1 Vorhandenen Linux-arm64-Gitea-Runner und tatsächliches Label bestätigen; Cross-Buildumgebungen mit cargo-zigbuild, cargo-xwin und benötigten SDKs/Sysroots reproduzierbar festlegen. Ein Gitea-Prüfjob muss den Buildhost nachweisen; separate echte Prüfsysteme aus 05 zuordnen, ohne vier native Buildrunner vorauszusetzen.
- [ ] 1.2 Repositorylokale Build-/Testaufrufe und feste Toolchain-/Systemvoraussetzungen bereitstellen; alle vier Ziele müssen auf Linux arm64 mit --locked baubar sein. Zentrale Workspace-Regressionen und getrennte Aufrufe für echte Zielprüfungen bereitstellen; fremde Executables nicht als nativ auf dem Buildhost getestet ausweisen. - [x] 1.2 Repositorylokale Build-/Testaufrufe und feste Toolchain-/Systemvoraussetzungen bereitstellen; alle vier Ziele müssen auf Linux arm64 mit --locked baubar sein. Zentrale Workspace-Regressionen und getrennte Aufrufe für echte Zielprüfungen bereitstellen; fremde Executables nicht als nativ auf dem Buildhost getestet ausweisen.
- [ ] 1.3 Push-/PR-Workflow unter .gitea/workflows anbinden; ein tatsächlicher Origin-Lauf muss vier Zielergebnisse und Fehlerstatus liefern, ohne Release-Secrets im PR-Pfad. - [ ] 1.3 Push-/PR-Workflow unter .gitea/workflows anbinden; ein tatsächlicher Origin-Lauf muss vier Zielergebnisse und Fehlerstatus liefern, ohne Release-Secrets im PR-Pfad.
## 2. Artefakte und Pakete ## 2. Artefakte und Pakete
- [ ] 2.1 IDE, CLI und native `tbrt`-Exportvorlage je Ziel in Gitea Actions bauen; Format-/Architektur-/Versionsprüfungen müssen Windows amd64, macOS arm64 und beide Linux-Architekturen eindeutig bestätigen. - [ ] 2.1 IDE, CLI und native `tbrt`-Exportvorlage je Ziel in Gitea Actions bauen; Format-/Architektur-/Versionsprüfungen müssen Windows amd64, macOS arm64 und beide Linux-Architekturen eindeutig bestätigen.
- [ ] 2.2 Windows-Paket als .7z und macOS-/Linux-Pakete als .tar.gz erzeugen; Archivtests müssen Dateinamen, Paketinhalt, Executable-Rechte und notwendige Begleitdateien prüfen. - [x] 2.2 Windows-Paket als .7z und macOS-/Linux-Pakete als .tar.gz erzeugen; Archivtests müssen Dateinamen, Paketinhalt, Executable-Rechte und notwendige Begleitdateien prüfen.
- [ ] 2.3 Jedes fertige Paket auf dem tatsächlichen Ziel neu entpacken und die enthaltenen Programme starten; automatisierte oder dokumentiert manuelle Nachweise aus separaten Prüfsystemen an Revision und Paketprüfsumme binden; `tbc link` und EXE-/TBL-Beispiele müssen mit separaten BASIC-Verbrauchern ohne Library-Quellen/Entwicklungscheckout sowie ohne erreichbaren C-/Rust-Compiler oder nativen Linker funktionieren. - [ ] 2.3 Jedes fertige Paket auf dem tatsächlichen Ziel neu entpacken und die enthaltenen Programme starten; automatisierte oder dokumentiert manuelle Nachweise aus separaten Prüfsystemen an Revision und Paketprüfsumme binden; `tbc link` und EXE-/TBL-Beispiele müssen mit separaten BASIC-Verbrauchern ohne Library-Quellen/Entwicklungscheckout sowie ohne erreichbaren C-/Rust-Compiler oder nativen Linker funktionieren.
- [ ] 2.4 Einmal erzeugte TBL-Probe mit identischen Bytes an alle vier Zielprüfungen verteilen sowie Artefaktmanifest und Prüfsummen erzeugen; absichtlich beschädigte oder vertauschte Zielartefakte müssen die Prüfung scheitern lassen. - [x] 2.4 Einmal erzeugte TBL-Probe mit identischen Bytes an alle vier Zielprüfungen verteilen sowie Artefaktmanifest und Prüfsummen erzeugen; absichtlich beschädigte oder vertauschte Zielartefakte müssen die Prüfung scheitern lassen.
## 3. Releasepfad ## 3. Releasepfad
- [ ] 3.1 Taggebundenen Gitea-Releasepfad mit vollständiger Pflichtasset-Liste und getrennten Rechten einrichten; fehlgeschlagene/fehlende Zielbuilds oder zugeordnete echte Paket-/Zielprüfungen müssen die Freigabe verhindern. - [ ] 3.1 Taggebundenen Gitea-Releasepfad mit vollständiger Pflichtasset-Liste und getrennten Rechten einrichten; fehlgeschlagene/fehlende Zielbuilds oder zugeordnete echte Paket-/Zielprüfungen müssen die Freigabe verhindern.
- [ ] 3.2 Upload zunächst als nicht freigegebenen Stand prüfen und erst vollständig freigeben; ein simulierter fehlender Upload darf keinen vollständigen bestehenden Release überschreiben. - [x] 3.2 Upload zunächst als nicht freigegebenen Stand prüfen und erst vollständig freigeben; ein simulierter fehlender Upload darf keinen vollständigen bestehenden Release überschreiben.
- [ ] 3.3 Fremdprogramm-, Inventar-, native und automatisierte Plattformnachweise sowie Referenzbenchmarks in den erforderlichen Abnahmelauf integrieren; ignorierte Pflichtfälle müssen als fehlend sichtbar bleiben. - [x] 3.3 Fremdprogramm-, Inventar-, native und automatisierte Plattformnachweise sowie Referenzbenchmarks in den erforderlichen Abnahmelauf integrieren; ignorierte Pflichtfälle müssen als fehlend sichtbar bleiben.
- [ ] 3.4 Einen tatsächlichen vollständigen Gitea-Lauf mit vier Paketartefakten nachweisen; Run-/Commit-/Buildhost-/Targetdaten und paketprüfsummengebundene entpackte Prüfergebnisse an 07 übergeben, bevor der Change als fertig gilt. - [ ] 3.4 Einen tatsächlichen vollständigen Gitea-Lauf mit vier Paketartefakten nachweisen; Run-/Commit-/Buildhost-/Targetdaten und paketprüfsummengebundene entpackte Prüfergebnisse an 07 übergeben, bevor der Change als fertig gilt.
Stand 07.09.2026: Repository-Implementierung und lokale Prüfungen vorhanden.
Alle vier Ziele wurden in den fixierten Containern auf Linux arm64 gebaut;
Linux-arm64- und cross-kompilierte macOS-Pakete bestehen echte entpackte
Automatikprüfungen. Das ist noch kein Actions-Lauf. 1.1/1.3/2.1/3.4 bleiben
wegen des defekten gemeinsamen Runners offen; 2.3 wegen Windows/Linux-amd64
und den restlichen visuellen Zielnachweisen. 3.1 bleibt bis zur Einrichtung
des Releasezugangs und tatsächlichen Rechteprüfung offen. Details: verification.md.

View File

@@ -0,0 +1,111 @@
# Verifizierung: phase-6-06-gitea-actions-und-releases
Stand 07.09.2026. Basis: `796564795a6607651c366c6b0de74560af55e71a`
mit dem dokumentierten Change-06-Diff. Change 05 wurde zuvor synchronisiert,
auf Benutzeranweisung archiviert und dieser Commit auf Origin bestätigt.
## Ergebnis
| Dimension | Stand |
|---|---|
| Vollständigkeit | 5/11 Aufgaben abgeschlossen; sechs Aufgaben mit echten Origin-/Ziel-/Rechtenachweisen offen |
| Korrektheit | Vier echte Cross-/Native-Builds auf Linux arm64; native Paketprüfungen auf Linux arm64 und macOS arm64 bestanden; lokale Pflichtabnahme und negative Paket-/Releaseprüfungen bestanden |
| Kohärenz | Bestehende Exportvalidierung, Vorlagenpfade, TBL-/Native-/PTY-Prüfungen wiederverwendet; keine neue Produktabhängigkeit |
Keine aktuell bekannte unbehobene lokale Codeabweichung. Der Change ist
wegen der unten benannten fehlenden externen Nachweise **nicht vollständig
verifiziert oder archivierungsbereit**. Vier lokal orchestrierte Container-
builds auf dem Gitea-Host sind keine vier erfolgreichen Actions-Jobs.
## Umsetzung und Szenarioabdeckung
- `.gitea/workflows/build.yml`: Push/interner PR, vier Targets auf
`linux-arm64`, gepinnte Images/Action-Commits, getrennte Grundabnahme und
Paketartefakte. Fremde PRs laufen nicht auf dem persönlichen Runner.
- `.gitea/scripts/build.py`, `bootstrap.sh`, `rust-toolchain.toml`: feste
Toolchain, SDK-/CRT-Versionen und Inhaltsprüfung, statische Windows-CRT,
glibc-Buildbaseline 2.28, macOS-Deployment 11.0. Das sind Buildvorgaben,
keine nachgewiesenen minimalen OS-Versionen.
- `distribution.py`: richtige `.7z`-/`.tar.gz`-Formate, vollständige Inhalte,
0755 für Unix-Executables, Dateiprüfsummen, Versions-/Target-/Revision-
Manifest. Entpacken lehnt fremde Pfade, Links und unvollständige Archive ab.
`tb-template --inspect` verwendet den vorhandenen nativen Formatparser.
- `target-check`: Programme aus frisch entpackten Paketen starten; EXE-Export
ohne expliziten Vorlagenpfad, native Parität, identische portable.tbl,
quellfreie Verbraucher, leerer PATH ohne Compiler/Linker, Unix-PTY; Windows
verlangt zusätzlich das explizite Konsolentestexecutable. Manuelle
Emulatorfolgen bleiben getrennt und revisions-/paketgebunden.
- `release.py`, `publish.py`, `publish.yml`: Tag-/Commitbindung, vollständige
Pflichtassets, Entwurfsstatus, Zurücklesen mit Bytevergleich, keine Ersetzung
existierender abweichender Assets oder veröffentlichter Releases. Fehlende,
falsche oder unvollständige Ziel-/Terminal-/Grundnachweise verhindern den
letzten `draft=false`-Aufruf. Nachweise stammen aus einem Origin-Commit.
- `acceptance.py`: bestehende Fremdprogramm-/Inventar-/Workspace-/Clippy-/
Format-/Compile-/VM-Prüfung sowie explizite native IDE-Abnahme. Fehlende
Konfiguration, ignorierte Pflichtläufe und Fehler werden nicht grün.
- `docs/distribution.md`, `INSTALL.txt`: Aufrufe, Paketlayout, Rechte,
Systemgrenzen, manuelle Nachweisform und Freigabefolge.
## Gefundene und behobene Befunde
1. Die neuen Paketprüfungen verwendeten zunächst `tbc --help`, obwohl die
CLI diesen Aufruf nicht unterstützt. Prüfung/Installation verwenden jetzt
echte Compiler-/Exportbefehle; keine zusätzliche CLI-Funktion nötig.
2. Ein flaches tbrt neben tb/tbc erfüllte die bestehenden automatischen
Suchpfade nicht. Archive enthalten nun `runtimes/<Target>/tbrt[.exe]`
samt Metadaten. Der ausdrückliche Test ohne `--template` besteht.
3. Alte Abnahmeskripte setzten das Entwicklerwerkzeug tb-template voraus.
Sie verwenden vorhandene Paketmetadaten; der bisherige Entwicklerpfad
bleibt für nicht paketierte Builds verfügbar.
4. Die native IDE-Pflichtprobe erhielt zunächst den falschen Runtime-Basispfad.
`acceptance.py` legt die Vorlage im geforderten Target-Unterverzeichnis ab;
der vollständige Abnahmelauf besteht nach der Korrektur.
5. Der vorhandene cargo-xwin-Stand akzeptiert den VS-Kanal nur numerisch;
CRT-Auswahl benutzt die Manifest-ID `14.44.17.14`, nicht die Dateiversion.
Mit Kanal 17 und den tatsächlichen IDs bestehen Build und .7z-Prüfung.
Zusätzlich verhindert der SDK-Inhaltspin eine stille Änderung unter
unveränderten Versionsbezeichnungen.
## Nachweise
- Vier Targets auf dem tatsächlichen Linux-aarch64-Gitea-Host gebaut;
PE/amd64/Console, Mach-O/arm64 und beide ELF-Maschinen geprüft.
- Echte entpackte Linux-arm64-Paketprüfung auf Linux 6.8.0-139/glibc 2.41.
- Das auf Linux cross-kompilierte macOS-Paket auf macOS 26.6.2/arm64 gestartet:
Standard-Vorlagenpfad, native Fälle, TBL, IDE-Shell/Abbruch/Wiederherstellung
bestanden. Die Programme wurden dabei nicht lokal erneut gebaut.
- Fünf automatisierte Paket-/Release-Regressionen: vollständiger Satz,
fehlende/falsche Nachweise, Korruption, falsche Revision, schmutzige Quellen,
Archiv-Traversierung, fehlender Upload, sichere Wiederholung, Schutz bereits
veröffentlichter Releases. Keine öffentlichen Testreleases erzeugt.
- Zusätzlich echte negative Artefaktproben: Mach-O als Linux deklariert und
verändertes Executable innerhalb eines Archivs werden abgelehnt.
- Lokaler vollständiger Pflichtlauf mit fixiertem Fremdbestand einschließlich
Benchmarks und expliziter nativer IDE-Probe bestanden. Exporttests, Clippy,
Format, YAML-Parsing und OpenSpec-Validierung bestanden.
Die gebauten Testpakete tragen den uncommitteten Diffstand im Manifest und
sind absichtlich nicht releasefähig. Lokale Belege werden unter `evidence/`
aufbewahrt; Paketprüfsummen und tatsächliche Hostdaten stehen in den Berichten.
## Offene externe Befunde
- **1.1/1.3/2.1/3.4:** Gitea 1.25.4, Actions am Repository aktiviert,
registrierter Runner `gitea-arm64-01`, Label `linux-arm64` bestätigt.
Der Runner ist in einer Neustartschleife: `rootlesskit ... /proc/self/exe:
operation not permitted`. Eine Entscheidung zur Reparatur des gemeinsamen
Runners wurde angefragt. Keine Docker-/AppArmor-Konfiguration verändert.
Ein echter erfolgreicher Actions-Matrixlauf und dessen Rechteverhalten fehlen.
- **2.3:** Windows-Ausführung bleibt entsprechend Benutzerentscheidung offen;
Linux amd64 und die vollständigen manuellen Emulatorfolgen sind ebenfalls
nicht belegt. Cross-Build, lokale Mocktests und gemeinsame ANSI-Technik
ersetzen diese Prüfungen nicht.
- **3.1:** Der getrennte Releasezugang `TB_RELEASE_TOKEN` ist noch nicht
eingerichtet/verifiziert. Es wurde kein persönlicher Git-Zugang als
dauerhaftes Release-Secret übernommen. Die Referenzvariable für den
vorhandenen fixierten Fremdbestand wurde am Repository eingerichtet.
Diese Befunde lassen sich nicht durch Änderungen an Paketcode oder durch
Abhaken von Aufgaben schließen. Nach Runner-Reparatur den Origin-Lauf ausführen,
zugehörige Paket-/Zielnachweise ergänzen und kontrollierte Entwurfs-/Rechte-
prüfung durchführen. Bis dahin keine Freigabe und keine Behauptung „0 Befunde“.

4
rust-toolchain.toml Normal file
View File

@@ -0,0 +1,4 @@
[toolchain]
channel = "1.97.1"
profile = "minimal"
components = ["clippy", "rustfmt"]

View File

@@ -63,7 +63,14 @@ def main():
library = root / 'library.tbl' library = root / 'library.tbl'
shutil.copyfile(args.library, library) shutil.copyfile(args.library, library)
template = root / ('runtime' + suffix) template = root / ('runtime' + suffix)
shutil.copy2(binaries / ('tbrt' + suffix), template) runtime = binaries / ('tbrt' + suffix)
if not runtime.is_file():
runtime = binaries / 'runtimes' / target / ('tbrt' + suffix)
shutil.copy2(runtime, template)
metadata = Path(str(runtime) + '.meta')
if metadata.is_file():
shutil.copyfile(metadata, Path(str(template) + '.meta'))
else:
run([template_tool, template, target], root, env) run([template_tool, template, target], root, env)
source = root / 'consumer.bas' source = root / 'consumer.bas'
source.write_text(SOURCE, encoding='utf-8') source.write_text(SOURCE, encoding='utf-8')

View File

@@ -76,12 +76,18 @@ def main():
suffix = '.exe' if args.target == 'x86_64-pc-windows-msvc' else '' suffix = '.exe' if args.target == 'x86_64-pc-windows-msvc' else ''
tbc = binaries / ('tbc' + suffix) tbc = binaries / ('tbc' + suffix)
rt = binaries / ('tbrt' + suffix) rt = binaries / ('tbrt' + suffix)
if not rt.is_file():
rt = binaries / 'runtimes' / args.target / ('tbrt' + suffix)
prepare = binaries / ('tb-template' + suffix) prepare = binaries / ('tb-template' + suffix)
env = dict(os.environ, PATH='') # weder Cargo noch tbc/tbrt über PATH auflösbar env = dict(os.environ, PATH='') # weder Cargo noch tbc/tbrt über PATH auflösbar
with tempfile.TemporaryDirectory(prefix='tb-native-') as work: with tempfile.TemporaryDirectory(prefix='tb-native-') as work:
root = Path(work) root = Path(work)
template = root / ('runtime' + suffix) template = root / ('runtime' + suffix)
shutil.copy2(rt, template) shutil.copy2(rt, template)
metadata = Path(str(rt) + '.meta')
if metadata.is_file():
shutil.copyfile(metadata, Path(str(template) + '.meta'))
else:
must(run([prepare, template, args.target], root)) must(run([prepare, template, args.target], root))
empty = run([template], root, env=env) empty = run([template], root, env=env)
assert empty.returncode == 1 and b'Nutzlast' in empty.stderr, empty assert empty.returncode == 1 and b'Nutzlast' in empty.stderr, empty