mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Derive the version from the Cargo/pubspec manifests
The version string was duplicated across six places. Collapse it to two ecosystem sources of truth and derive the rest: - backend/src/web_server.rs: omit the OpenAPI info.version so utoipa fills it from CARGO_PKG_VERSION (backend/Cargo.toml); add a test pinning this. - nix/package.nix: read the version from backend/Cargo.toml via fromTOML. - nix/frontend.nix: read the version from frontend/pubspec.yaml by splitting into lines (a whole-file regex triggers catastrophic backtracking in Nix's regex engine). - frontend/lib/about/about.dart: read the version at runtime via package_info_plus instead of a hardcoded constant. Also drop frontend/pubspec.lock.json: it is unreferenced (Nix's autoPubspecLock generates its own JSON from pubspec.lock) and was going stale. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
dd089a9cbc
commit
4a1fe60ec3
@@ -40,7 +40,8 @@ pub mod utils;
|
|||||||
#[openapi(
|
#[openapi(
|
||||||
info(
|
info(
|
||||||
title = "OOTT API",
|
title = "OOTT API",
|
||||||
version = "0.1.0",
|
// version is intentionally omitted: utoipa fills it from the crate
|
||||||
|
// version (CARGO_PKG_VERSION, i.e. backend/Cargo.toml) automatically.
|
||||||
description = "Network monitoring and alert system API"
|
description = "Network monitoring and alert system API"
|
||||||
),
|
),
|
||||||
paths(
|
paths(
|
||||||
@@ -244,4 +245,12 @@ mod tests {
|
|||||||
fn web_root_falls_back_to_local_dir_without_an_executable() {
|
fn web_root_falls_back_to_local_dir_without_an_executable() {
|
||||||
assert_eq!(resolve_web_root(None), PathBuf::from("./web"));
|
assert_eq!(resolve_web_root(None), PathBuf::from("./web"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn openapi_version_tracks_the_crate_version() {
|
||||||
|
// The OpenAPI spec must report the crate version (backend/Cargo.toml)
|
||||||
|
// rather than a separately maintained literal.
|
||||||
|
let openapi = <ApiDoc as OpenApi>::openapi();
|
||||||
|
assert_eq!(openapi.info.version, env!("CARGO_PKG_VERSION"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
const _version = '0.1.0';
|
// The version is read at runtime from the bundled package metadata
|
||||||
|
// (frontend/pubspec.yaml), so it never needs to be hand-edited here.
|
||||||
const _releaseDate = 'May 28, 2026';
|
const _releaseDate = 'May 28, 2026';
|
||||||
const _repoUrl = 'https://github.com/rzuasti/oott';
|
const _repoUrl = 'https://github.com/rzuasti/oott';
|
||||||
const _licenseUrl = 'https://www.gnu.org/licenses/agpl-3.0.html';
|
const _licenseUrl = 'https://www.gnu.org/licenses/agpl-3.0.html';
|
||||||
@@ -28,11 +30,20 @@ class About extends StatelessWidget {
|
|||||||
style: textTheme.bodyLarge,
|
style: textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
FutureBuilder<PackageInfo>(
|
||||||
'v$_version - released $_releaseDate',
|
future: PackageInfo.fromPlatform(),
|
||||||
style: textTheme.bodyMedium?.copyWith(
|
builder: (context, snapshot) {
|
||||||
color: colorScheme.onSurfaceVariant,
|
final version = snapshot.data?.version;
|
||||||
),
|
final label = version == null
|
||||||
|
? 'Released $_releaseDate'
|
||||||
|
: 'v$version - released $_releaseDate';
|
||||||
|
return Text(
|
||||||
|
label,
|
||||||
|
style: textTheme.bodyMedium?.copyWith(
|
||||||
|
color: colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
_SurfaceContainer(
|
_SurfaceContainer(
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import Foundation
|
|||||||
|
|
||||||
import connectivity_plus
|
import connectivity_plus
|
||||||
import encrypter
|
import encrypter
|
||||||
|
import package_info_plus
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||||
EncrypterPlugin.register(with: registry.registrar(forPlugin: "EncrypterPlugin"))
|
EncrypterPlugin.register(with: registry.registrar(forPlugin: "EncrypterPlugin"))
|
||||||
|
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -384,6 +384,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
|
package_info_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: package_info_plus
|
||||||
|
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.3.1"
|
||||||
|
package_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_info_plus_platform_interface
|
||||||
|
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -701,6 +717,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.15.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -20,6 +20,7 @@ dependencies:
|
|||||||
fl_chart: ^1.2.0
|
fl_chart: ^1.2.0
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.2.1
|
||||||
url_launcher: ^6.3.0
|
url_launcher: ^6.3.0
|
||||||
|
package_info_plus: ^8.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
+19
-10
@@ -1,12 +1,21 @@
|
|||||||
{flutter}:
|
{flutter}: let
|
||||||
flutter.buildFlutterApplication {
|
# Single source of truth: extract the version from frontend/pubspec.yaml.
|
||||||
pname = "oott-frontend";
|
# Nix has no YAML parser, so split into lines and read the `version:` line.
|
||||||
version = "0.1.0";
|
# (Matching the whole file with a single regex is avoided on purpose: nested
|
||||||
src = ./../frontend;
|
# quantifiers over the full text trigger catastrophic backtracking in Nix's
|
||||||
|
# regex engine.)
|
||||||
|
lines = builtins.filter builtins.isString (builtins.split "\n" (builtins.readFile ./../frontend/pubspec.yaml));
|
||||||
|
versionLine = builtins.head (builtins.filter (line: builtins.match "version:.*" line != null) lines);
|
||||||
|
version = builtins.head (builtins.match "version: *([^ ]+) *" versionLine);
|
||||||
|
in
|
||||||
|
flutter.buildFlutterApplication {
|
||||||
|
pname = "oott-frontend";
|
||||||
|
inherit version;
|
||||||
|
src = ./../frontend;
|
||||||
|
|
||||||
# Fetches pub dependencies from the committed pubspec.lock (all hosted, no git deps).
|
# Fetches pub dependencies from the committed pubspec.lock (all hosted, no git deps).
|
||||||
autoPubspecLock = ./../frontend/pubspec.lock;
|
autoPubspecLock = ./../frontend/pubspec.lock;
|
||||||
|
|
||||||
# Build the web bundle (the backend serves these assets).
|
# Build the web bundle (the backend serves these assets).
|
||||||
targetFlutterPlatform = "web";
|
targetFlutterPlatform = "web";
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -12,7 +12,8 @@
|
|||||||
in
|
in
|
||||||
pkgs.rustPlatform.buildRustPackage rec {
|
pkgs.rustPlatform.buildRustPackage rec {
|
||||||
pname = "oott";
|
pname = "oott";
|
||||||
version = "0.1.0";
|
# Single source of truth: read the version straight from backend/Cargo.toml.
|
||||||
|
version = (builtins.fromTOML (builtins.readFile ./../backend/Cargo.toml)).package.version;
|
||||||
src = ./../backend;
|
src = ./../backend;
|
||||||
cargoLock = {
|
cargoLock = {
|
||||||
lockFile = ./../backend/Cargo.lock;
|
lockFile = ./../backend/Cargo.lock;
|
||||||
|
|||||||
Reference in New Issue
Block a user