diff --git a/README.md b/README.md index 1bce8b5..d7836a7 100644 --- a/README.md +++ b/README.md @@ -107,9 +107,9 @@ dist/linux/pysentry-0.2.3-linux-amd64 Linux using Docker: ```bash -# Builds the Linux binary inside Docker using the image tag -# gitea.mixdep.ru/mix/pysentry-builder. Useful from hosts or CI jobs where the -# native Linux/Fyne packages are not installed locally. +# Builds the Linux binary inside Docker using the versioned image tag +# gitea.mixdep.ru/mix/pysentry-builder:. Useful from hosts or CI jobs +# where the native Linux/Fyne packages are not installed locally. chmod +x ./scripts/build-linux-docker.sh ./scripts/build-linux-docker.sh ``` diff --git a/scripts/build-linux-docker.sh b/scripts/build-linux-docker.sh index 72ad9a4..25060ff 100644 --- a/scripts/build-linux-docker.sh +++ b/scripts/build-linux-docker.sh @@ -6,6 +6,7 @@ set -euo pipefail # default includes the application version and target platform. version="$(sed -n 's/^var Version = "\(.*\)"/\1/p' src/core/version.go)" version="${version:-0.0.0-dev}" +tag="gitea.mixdep.ru/mix/pysentry-builder:${version}" output="${1:-dist/linux/pysentry-${version}-linux-amd64}" docker_user_args=() if command -v id >/dev/null 2>&1; then @@ -14,7 +15,7 @@ fi # Dockerfile contains the native packages required by Fyne. Keeping that # environment in Docker makes Linux builds repeatable from Windows hosts and CI. -docker build -f Dockerfile -t gitea.mixdep.ru/mix/pysentry-builder . +docker build -f Dockerfile -t "$tag" . mkdir -p "$(dirname "$output")" docker run --rm \ @@ -24,7 +25,7 @@ docker run --rm \ -e "GOCACHE=/tmp/go-build-cache" \ -v "$(pwd):/src" \ -w /src \ - gitea.mixdep.ru/mix/pysentry-builder \ + "$tag" \ bash -c 'CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -buildvcs=false -trimpath -ldflags "-s -w -X github.com/pysentry/pysentry/src/core.Version=${VERSION}" -o "${OUTPUT}" ./cmd/pysentry' # Icons are embedded in the Go binary, so there is no assets directory to copy diff --git a/scripts/build-release-linux.sh b/scripts/build-release-linux.sh index e264620..080a6f9 100644 --- a/scripts/build-release-linux.sh +++ b/scripts/build-release-linux.sh @@ -5,15 +5,13 @@ set -euo pipefail # image contains Linux/Fyne dependencies for amd64 and arm64, plus the MinGW # cross-compiler used for the Windows GUI executable. Actual build commands live # here rather than in Dockerfile so target selection does not require rebuilding -# the image. -tag="gitea.mixdep.ru/mix/pysentry-builder" - script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd "${script_dir}/.." && pwd)" cd "$repo_root" version="$(sed -n 's/^var Version = "\(.*\)"/\1/p' src/core/version.go)" version="${version:-0.0.0-dev}" +tag="gitea.mixdep.ru/mix/pysentry-builder:${version}" docker_user_args=() if command -v id >/dev/null 2>&1; then diff --git a/src/gui/app.go b/src/gui/app.go index 2f352a8..a6c98ef 100644 --- a/src/gui/app.go +++ b/src/gui/app.go @@ -2,6 +2,9 @@ package gui import ( "fmt" + "net/url" + "runtime" + "runtime/debug" "sort" "strconv" "strings" @@ -24,6 +27,7 @@ const appID = "io.github.pysentry.desktop" const allFolders = "All" const noFolder = "No folder" const minJobsSidebarWidth float32 = 480 +const projectRepositoryURL = "https://gitea.mixdep.ru/mix/gosentry" // The GUI package aliases core types to keep widget callbacks short. The actual // durable model still lives in src/core, so GUI code does not define a second @@ -836,11 +840,41 @@ func settingsView(w fyne.Window, store *core.Store, jobs *[]job) fyne.CanvasObje saveSettings, settingsStatus, widget.NewSeparator(), - widget.NewLabelWithStyle("Scheduler", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), - widget.NewLabel("Current core supports @every schedules and standard 5-field cron expressions."), + widget.NewLabelWithStyle("About", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), + detailRow("GoSentry", widget.NewLabel(core.Version)), + detailRow("Go", widget.NewLabel(runtime.Version())), + detailRow("Fyne", widget.NewLabel(fyneVersion())), + detailRow("Repository", widget.NewHyperlink(projectRepositoryURL, mustParseURL(projectRepositoryURL))), )) } +func fyneVersion() string { + info, ok := debug.ReadBuildInfo() + if !ok { + return "unknown" + } + for _, dependency := range info.Deps { + if dependency.Path == "fyne.io/fyne/v2" { + if dependency.Replace != nil && dependency.Replace.Version != "" { + return dependency.Replace.Version + } + if dependency.Version != "" { + return dependency.Version + } + return "local" + } + } + return "unknown" +} + +func mustParseURL(raw string) *url.URL { + parsed, err := url.Parse(raw) + if err != nil { + return &url.URL{} + } + return parsed +} + func chooseFolder(w fyne.Window, target *widget.Entry) { folderDialog := dialog.NewFolderOpen(func(uri fyne.ListableURI, err error) { if err != nil || uri == nil {