latest server code
Some checks failed
Build and Push Multi-Arch Docker Image / build-and-push (push) Failing after 38s

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2025-11-28 21:02:02 +01:00
parent 8f51ac8b24
commit 4defe266eb
10 changed files with 121 additions and 58 deletions

View File

@@ -23,6 +23,5 @@ jobs:
run: | run: |
docker buildx build \ docker buildx build \
--platform linux/amd64,linux/arm64 \ --platform linux/amd64,linux/arm64 \
--add-host=registry-1.docker.io:18.204.181.58 \
-t ${{ secrets.DOMAIN }}/${{ secrets.OWNER }}/${{ secrets.REPO }}/server:latest \ -t ${{ secrets.DOMAIN }}/${{ secrets.OWNER }}/${{ secrets.REPO }}/server:latest \
--push . --push .

View File

@@ -5,4 +5,4 @@
*.freezed.dart *.freezed.dart
*.config.dart *.config.dart
*.log *.log
assets/cache **/cache

View File

@@ -1,5 +1,5 @@
# Use latest stable channel SDK. # Use latest stable channel SDK.
FROM dart:3.10.1 AS build FROM dart:stable AS build
# Resolve app dependencies. # Resolve app dependencies.
WORKDIR /app WORKDIR /app
@@ -17,7 +17,7 @@ RUN APP_VERSION=$(awk '/^version:/{print $2}' pubspec.yaml) && \
FROM scratch FROM scratch
COPY --from=build /runtime/ / COPY --from=build /runtime/ /
COPY --from=build /app/bin/server /app/bin/ COPY --from=build /app/bin/server /app/bin/
COPY assets / COPY assets /assets
# Start server. # Start server.
EXPOSE 3000 EXPOSE 3000

View File

@@ -1,3 +1,7 @@
VERSION := $(shell grep 'version:' pubspec.yaml | sed 's/version: //')
MAJOR := $(shell echo $(VERSION) | cut -d. -f1)
MAJOR_MINOR := $(shell echo $(VERSION) | cut -d. -f1,2)
build: build:
dart run build_runner build --delete-conflicting-outputs dart run build_runner build --delete-conflicting-outputs
@@ -5,4 +9,18 @@ watch:
dart run build_runner watch --delete-conflicting-outputs dart run build_runner watch --delete-conflicting-outputs
docker: build docker: build
docker build -t cinema-display . docker build \
-t cr.mars3142.io/model-railway/cinema-display:latest \
-t cr.mars3142.io/model-railway/cinema-display:$(MAJOR) \
-t cr.mars3142.io/model-railway/cinema-display:$(MAJOR_MINOR) \
-t cr.mars3142.io/model-railway/cinema-display:$(VERSION) \
.
multi: build
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t cr.mars3142.io/model-railway/cinema-display:latest \
-t cr.mars3142.io/model-railway/cinema-display:$(MAJOR) \
-t cr.mars3142.io/model-railway/cinema-display:$(MAJOR_MINOR) \
-t cr.mars3142.io/model-railway/cinema-display:$(VERSION) \
.

View File

@@ -1,5 +1,7 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:cinema/common/env_not_found_exception.dart';
import 'package:cinema/feature/middlewares/cors.dart'; import 'package:cinema/feature/middlewares/cors.dart';
import 'package:cinema/feature/poster/data/repositories/image_loader.dart'; import 'package:cinema/feature/poster/data/repositories/image_loader.dart';
import 'package:cinema/feature/poster/data/services/poster.service.dart'; import 'package:cinema/feature/poster/data/services/poster.service.dart';
@@ -11,6 +13,8 @@ import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart'; import 'package:shelf_router/shelf_router.dart';
void main(List<String> args) async { void main(List<String> args) async {
runZonedGuarded(
() async {
final startTime = DateTime.now(); final startTime = DateTime.now();
configureDependencies(); configureDependencies();
@@ -25,7 +29,7 @@ void main(List<String> args) async {
// For running in containers, we respect the PORT environment variable. // For running in containers, we respect the PORT environment variable.
final port = int.parse(Platform.environment['PORT'] ?? '3000'); final port = int.parse(Platform.environment['PORT'] ?? '3000');
await io.serve(handler, InternetAddress.anyIPv4, port, poweredByHeader: null).then((server) async { await io.serve(handler, InternetAddress.anyIPv4, port, poweredByHeader: null).then((server) async {
final bannerFile = File('banner.txt'); final bannerFile = File('assets/banner.txt');
if (await bannerFile.exists()) { if (await bannerFile.exists()) {
final banner = await bannerFile.readAsString(); final banner = await bannerFile.readAsString();
print(banner); print(banner);
@@ -47,4 +51,12 @@ void main(List<String> args) async {
print('Server started at: $startTime'); print('Server started at: $startTime');
print('Startup time: $time\n'); print('Startup time: $time\n');
}); });
},
(error, stackTrace) {
stderr.writeln(error);
if (error is EnvNotFoundException) {
exit(1);
}
},
);
} }

View File

@@ -1,5 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:cinema/common/env_module.dart';
import 'package:cinema/feature/version/version.dart'; import 'package:cinema/feature/version/version.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart'; import 'package:injectable/injectable.dart';
@@ -11,25 +12,23 @@ const dioIMAGES = 'images';
abstract class DioModule { abstract class DioModule {
@Named(dioAPI) @Named(dioAPI)
@lazySingleton @lazySingleton
Dio get apiDio => Dio apiDio(@Named(apiKey) String apiKey) => Dio(
Dio( // Der Getter selbst wird annotiert und gibt die Instanz zurück
BaseOptions( BaseOptions(
baseUrl: 'https://api.themoviedb.org/3', baseUrl: 'https://api.themoviedb.org/3',
connectTimeout: const Duration(seconds: 10), connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 10), receiveTimeout: const Duration(seconds: 10),
headers: { headers: {
'Authorization': 'Bearer ${Platform.environment['TMDB_API_KEY']}', 'Authorization': 'Bearer $apiKey',
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json', 'Accept': 'application/json',
'User-Agent': 'Cinema Service (v${Version().appVersion})' 'User-Agent': 'Cinema Service (v${Version().appVersion})',
}, },
), ),
); );
@Named(dioIMAGES) @Named(dioIMAGES)
@lazySingleton @lazySingleton
Dio get imagesDio => Dio get imagesDio => Dio(
Dio( // Der Getter selbst wird annotiert und gibt die Instanz zurück
BaseOptions( BaseOptions(
baseUrl: 'https://image.tmdb.org/t/p/original', baseUrl: 'https://image.tmdb.org/t/p/original',
connectTimeout: const Duration(seconds: 10), connectTimeout: const Duration(seconds: 10),

View File

@@ -0,0 +1,18 @@
import 'dart:io';
import 'package:injectable/injectable.dart';
import 'package:cinema/common/env_not_found_exception.dart';
const apiKey = "apiKey";
@module
abstract class EnvModule {
@lazySingleton
@Named(apiKey)
String get api_key {
final key = Platform.environment['TMDB_API_KEY'];
if (key == null || key.isEmpty) {
throw EnvNotFoundException('TMDB_API_KEY environment variable is missing.');
}
return key;
}
}

View File

@@ -0,0 +1,8 @@
class EnvNotFoundException implements Exception {
final String message;
EnvNotFoundException([this.message = '']);
@override
String toString() => 'EnvNotFoundException: $message';
}

View File

@@ -26,8 +26,11 @@ class TmDBImageLoader implements ImageLoader {
(movie) => Movie( (movie) => Movie(
(b) => b (b) => b
..id = movie.id ..id = movie.id
..title = movie.title
..poster = movie.posterPath ..poster = movie.posterPath
..backdrop = movie.backdropPath, ..backdrop = movie.backdropPath
..release = movie.releaseDate
..video = movie.video,
), ),
) )
.toList() ?? .toList() ??
@@ -38,12 +41,12 @@ class TmDBImageLoader implements ImageLoader {
@override @override
Future<bool> downloadImages(Movie movie) async { Future<bool> downloadImages(Movie movie) async {
await downloadImage(movie.poster, "cache/movie/${movie.id}/poster.png"); await _downloadImage(movie.poster, "cache/movie/${movie.id}/poster.png");
await downloadImage(movie.backdrop, "cache/movie/${movie.id}/backdrop.png"); await _downloadImage(movie.backdrop, "cache/movie/${movie.id}/backdrop.png");
return true; return true;
} }
Future<bool> downloadImage(String url, String filename) async { Future<bool> _downloadImage(String url, String filename) async {
final file = File(filename); final file = File(filename);
if (await file.exists()) { if (await file.exists()) {
return false; return false;

View File

@@ -8,6 +8,12 @@ abstract class Movie implements Built<Movie, MovieBuilder> {
int get id; int get id;
String get title;
DateTime get release;
bool get video;
String get poster; String get poster;
String get backdrop; String get backdrop;