diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..5cc074c --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,40 @@ +# Release-Matrix: bei Tag v* → Tests → Artefakte für alle Plattformen → +# Gitea-Release mit Assets talk__[.exe] + checksums.txt. +name: release + +on: + push: + tags: + - "v*" + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # git describe braucht die Tags + - name: Go einrichten + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Tests + run: go vet ./... && go test ./... + - name: Artefakte bauen + run: scripts/release.sh "${{ github.ref_name }}" + - name: Gitea-Release anlegen und Assets hochladen + uses: https://gitea.com/actions/gitea-release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ github.ref_name }} + name: talk ${{ github.ref_name }} + body: | + Statische Binaries (CGO_ENABLED=0), Prüfsummen in `checksums.txt`. + + Installation: passendes `talk__` laden, Prüfsumme vergleichen, + als `talk` in den PATH legen, `talk doctor`. Der Daemon startet beim ersten + Sprechbefehl von selbst. + files: |- + dist/talk_* + dist/checksums.txt diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..741ec6a --- /dev/null +++ b/flake.nix @@ -0,0 +1,70 @@ +{ + # talk — Sprach-Ausgaben für Skripte und KI-Agenten. + # + # Nutzung in einer NixOS-/Home-Manager-Konfiguration: + # inputs.talk.url = "git+https://code.m3ta.dev/m3tam3re/talk"; + # environment.systemPackages = [ inputs.talk.packages.${system}.talk ]; + # oder als Overlay: nixpkgs.overlays = [ inputs.talk.overlays.default ]; + # + # Dieses Flake ersetzt langfristig m3ta-nixpkgs talk/crunch (bash + mpv). + description = "talk — Voice-Notifications für Skripte und KI-Agenten (ein Binary, Daemon mit Queue)"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + outputs = { self, nixpkgs }: + let + systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + forAll = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system}); + version = if self ? shortRev then "0.0.0-${self.shortRev}" else "0.0.0-dirty"; + mkTalk = pkgs: pkgs.buildGoModule { + pname = "talk"; + inherit version; + src = self; + subPackages = [ "cmd/talk" ]; + # Nach Änderungen an go.mod/go.sum neu setzen: `nix build` nennt den + # erwarteten Hash. + vendorHash = "sha256-CbF3juTA7V05hh1ElKKACddsCn4bIPeLZxsz2EZxs9I="; + env.CGO_ENABLED = 0; + ldflags = [ "-s" "-w" "-X" "main.version=${version}" "-X" "main.commit=${self.shortRev or "dirty"}" ]; + # Prozessgrenzen-Tests starten Daemons und binden Ports — nicht in der Sandbox. + doCheck = false; + # Audio: oto spricht PulseAudio/PipeWire direkt (reines Go) und fällt auf + # ALSA zurück, das es zur Laufzeit per dlopen lädt — auf NixOS nur + # auffindbar, wenn wir es in den Pfad legen. OS-Stimme: espeak-ng. + nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.makeWrapper ]; + postInstall = pkgs.lib.optionalString pkgs.stdenv.isLinux '' + wrapProgram $out/bin/talk \ + --prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath [ pkgs.alsa-lib ]} \ + --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.espeak-ng pkgs.libnotify ]} + ''; + meta = with pkgs.lib; { + description = "Voice-Notifications für Skripte und KI-Agenten"; + homepage = "https://code.m3ta.dev/m3tam3re/talk"; + license = licenses.mit; + mainProgram = "talk"; + platforms = platforms.unix; + }; + }; + in + { + packages = forAll (pkgs: rec { + talk = mkTalk pkgs; + default = talk; + }); + + apps = forAll (pkgs: rec { + talk = { type = "app"; program = "${mkTalk pkgs}/bin/talk"; }; + default = talk; + }); + + overlays.default = final: prev: { talk = mkTalk final; }; + + devShells = forAll (pkgs: { + default = pkgs.mkShell { + packages = [ pkgs.go pkgs.gopls pkgs.gotools pkgs.espeak-ng pkgs.libnotify ]; + }; + }); + + formatter = forAll (pkgs: pkgs.nixfmt-rfc-style); + }; +} diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..2c99a13 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env sh +# Baut die Release-Artefakte von talk für alle Zielplattformen — reproduzierbar +# mit nichts als dem Go-Toolchain (kein GoReleaser nötig; so läuft derselbe +# Schritt lokal, in Gitea Actions und in nix identisch). +# +# Asset-Vertrag (agent-lib-Muster, Fleet-Rollout pinnt darauf): +# dist/talk__[.exe] statisches Binary, CGO_ENABLED=0 +# dist/checksums.txt sha256 je Asset (sha256sum-Format) +# +# Aufruf: scripts/release.sh [VERSION] (Default: git describe, sonst "dev") +# Env: TARGETS="linux/amd64 …" überschreibt die Matrix. +set -eu + +cd "$(dirname "$0")/.." +VERSION="${1:-$(git describe --tags --always --dirty 2>/dev/null || echo dev)}" +VERSION="${VERSION#v}" +COMMIT="$(git rev-parse --short HEAD 2>/dev/null || echo unknown)" +TARGETS="${TARGETS:-linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64}" +DIST=dist + +rm -rf "$DIST" +mkdir -p "$DIST" +for target in $TARGETS; do + os="${target%/*}" + arch="${target#*/}" + out="$DIST/talk_${os}_${arch}" + [ "$os" = windows ] && out="$out.exe" + echo "build $out" + CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" go build -trimpath \ + -ldflags "-s -w -X main.version=$VERSION -X main.commit=$COMMIT" \ + -o "$out" ./cmd/talk +done +(cd "$DIST" && sha256sum talk_* > checksums.txt) +echo +echo "Version $VERSION ($COMMIT):" +cat "$DIST/checksums.txt"