Compare commits

..

1 Commits

Author SHA1 Message Date
David Álvarez 3e6d8b93a8 Add Gitea Build & Deploy workflow
Build & Deploy / build-and-deploy (push) Successful in 13s
2026-06-11 17:37:39 +02:00
15 changed files with 60 additions and 29 deletions
+34 -1
View File
@@ -1,5 +1,7 @@
# This workflow builds DOStalgia whenever code is pushed to main. # This workflow builds and deploys DOStalgia whenever code is pushed to main.
# The runner has Docker socket access so it can manage containers on the host. # The runner has Docker socket access so it can manage containers on the host.
# Parameters match the docker-compose at:
# /appdata/dockhand/stacks/unraid/dostalgia/compose.yaml
# See: https://docs.gitea.com/usage/actions # See: https://docs.gitea.com/usage/actions
name: Build & Deploy name: Build & Deploy
@@ -11,6 +13,8 @@ on:
env: env:
IMAGE_NAME: dostalgia IMAGE_NAME: dostalgia
CONTAINER_NAME: dostalgia
DATA_VOLUME: /mnt/cache/appdata/dostalgia
jobs: jobs:
build-and-deploy: build-and-deploy:
@@ -25,5 +29,34 @@ jobs:
docker build -t ${{ env.IMAGE_NAME }}:${{ gitea.sha }} . docker build -t ${{ env.IMAGE_NAME }}:${{ gitea.sha }} .
docker tag ${{ env.IMAGE_NAME }}:${{ gitea.sha }} ${{ env.IMAGE_NAME }}:latest docker tag ${{ env.IMAGE_NAME }}:${{ gitea.sha }} ${{ env.IMAGE_NAME }}:latest
- name: Deploy container
run: |
docker stop ${{ env.CONTAINER_NAME }} 2>/dev/null || true
docker rm ${{ env.CONTAINER_NAME }} 2>/dev/null || true
docker run -d \
--name ${{ env.CONTAINER_NAME }} \
--restart unless-stopped \
--network dockernet \
-p 8765:8765/tcp \
-v ${{ env.DATA_VOLUME }}:/data \
-e TWITCH_CLIENT_ID='${{ secrets.TWITCH_CLIENT_ID }}' \
-e TWITCH_CLIENT_SECRET='${{ secrets.TWITCH_CLIENT_SECRET }}' \
${{ env.IMAGE_NAME }}:latest
- name: Verify container is running
run: |
sleep 5
STATUS=$(docker inspect -f '{{.State.Status}}' ${{ env.CONTAINER_NAME }})
if [ "$STATUS" = "running" ]; then
echo "✅ DOStalgia container is running"
echo "--- last logs ---"
docker logs ${{ env.CONTAINER_NAME }} --tail 5
echo "✅ DOStalgia deployed!"
else
echo "❌ Container status: $STATUS"
docker logs ${{ env.CONTAINER_NAME }} --tail 30
exit 1
fi
- name: Clean up old images - name: Clean up old images
run: docker image prune -f --filter "until=24h" run: docker image prune -f --filter "until=24h"
-3
View File
@@ -40,6 +40,3 @@ data/saves/*
# OS # OS
.DS_Store .DS_Store
Thumbs.db Thumbs.db
# Gitea
.gitea/
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "dostalgia-frontend", "name": "dostalgia-frontend",
"version": "0.1.1", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "dostalgia-frontend", "name": "dostalgia-frontend",
"version": "0.1.1", "version": "0.1.0",
"devDependencies": { "devDependencies": {
"@sveltejs/vite-plugin-svelte": "^4.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0",
"@testing-library/svelte": "^5.3.1", "@testing-library/svelte": "^5.3.1",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "dostalgia-frontend", "name": "dostalgia-frontend",
"private": true, "private": true,
"version": "0.1.1", "version": "0.1.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
+1 -1
View File
@@ -43,7 +43,7 @@
}); });
</script> </script>
<Header onUploadClick={() => uploadTriggered++} hideUpload={route !== "/"} /> <Header onUploadClick={() => uploadTriggered++} />
<main class="container"> <main class="container">
{#if route === "/"} {#if route === "/"}
+8 -13
View File
@@ -98,8 +98,7 @@ h3 { font-size: 1.2rem; }
/* ═══════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════
BUTTONS BUTTONS
═══════════════════════════════════════════════════════════════ */ ═══════════════════════════════════════════════════════════════ */
/* Only targets DOStalgia buttons, not js-dos emulator buttons inside .dos-container */ .btn {
.btn.btn:not(.dos-container .btn) {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
@@ -112,36 +111,32 @@ h3 { font-size: 1.2rem; }
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
text-transform: none;
height: auto;
min-height: 0;
line-height: normal;
transition: all 0.15s ease; transition: all 0.15s ease;
} }
.btn.btn:not(.dos-container .btn):hover { .btn:hover {
background: var(--phosphor-burn); background: var(--phosphor-burn);
border-color: var(--phosphor); border-color: var(--phosphor);
box-shadow: 0 0 12px var(--phosphor-dark); box-shadow: 0 0 12px var(--phosphor-dark);
} }
.btn.btn:not(.dos-container .btn):active { .btn:active {
transform: scale(0.97); transform: scale(0.97);
} }
.btn-primary.btn-primary:not(.dos-container .btn) { .btn-primary {
background: var(--phosphor-dark); background: var(--phosphor-dark);
border-color: var(--phosphor); border-color: var(--phosphor);
color: var(--phosphor-glow); color: var(--phosphor-glow);
} }
.btn-primary.btn-primary:not(.dos-container .btn):hover { .btn-primary:hover {
background: var(--phosphor-dim); background: var(--phosphor-dim);
color: var(--bg); color: var(--bg);
} }
.btn-danger.btn-danger:not(.dos-container .btn) { .btn-danger {
border-color: #cc3333; border-color: #cc3333;
color: #cc3333; color: #cc3333;
} }
.btn-danger.btn-danger:not(.dos-container .btn):hover { .btn-danger:hover {
background: #331111; background: #331111;
border-color: #ff4444; border-color: #ff4444;
color: #ff4444; color: #ff4444;
@@ -192,7 +187,7 @@ input::placeholder {
@media (max-width: 640px) { @media (max-width: 640px) {
h1 { font-size: 1.5rem; } h1 { font-size: 1.5rem; }
h2 { font-size: 1.25rem; } h2 { font-size: 1.25rem; }
.btn.btn:not(.dos-container .btn) { padding: 8px 14px; font-size: 0.85rem; min-height: 40px; } .btn { padding: 8px 14px; font-size: 0.85rem; min-height: 40px; }
input, textarea, select { font-size: 16px; } /* prevents iOS zoom */ input, textarea, select { font-size: 16px; } /* prevents iOS zoom */
} }
+1 -3
View File
@@ -1,5 +1,5 @@
<script> <script>
let { onUploadClick = () => {}, hideUpload = false } = $props(); let { onUploadClick = () => {} } = $props();
</script> </script>
<header class="header"> <header class="header">
@@ -17,9 +17,7 @@
<span class="logo-text">DOSTALGIA</span> <span class="logo-text">DOSTALGIA</span>
</a> </a>
<nav> <nav>
{#if !hideUpload}
<button class="btn" onclick={onUploadClick}>+ Upload</button> <button class="btn" onclick={onUploadClick}>+ Upload</button>
{/if}
</nav> </nav>
</div> </div>
</header> </header>
+9 -1
View File
@@ -134,7 +134,7 @@
{isSetup ? "Back" : game.title} {isSetup ? "Back" : game.title}
</button> </button>
{#if running} {#if running}
<button class="btn btn-danger" onclick={stopEmulator}> Stop</button> <button class="btn stop-btn" onclick={stopEmulator}> Stop</button>
{/if} {/if}
{/if} {/if}
</div> </div>
@@ -211,6 +211,14 @@
font-family: var(--font-sans); font-family: var(--font-sans);
} }
.link-button:hover { color: var(--phosphor); } .link-button:hover { color: var(--phosphor); }
.stop-btn {
border-color: #cc3333;
color: #ff4444;
}
.stop-btn:hover {
background: #331111;
box-shadow: 0 0 12px #331111;
}
/* Emulator canvas — always mounted */ /* Emulator canvas — always mounted */
.dos-container { .dos-container {
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>org.dostalgia</groupId> <groupId>org.dostalgia</groupId>
<artifactId>dostalgia</artifactId> <artifactId>dostalgia</artifactId>
<version>0.1.1</version> <version>0.1.0</version>
<properties> <properties>
<maven.compiler.release>21</maven.compiler.release> <maven.compiler.release>21</maven.compiler.release>
@@ -53,7 +53,7 @@ public class StaticResource {
@GET @GET
@jakarta.ws.rs.Path("/api/health") @jakarta.ws.rs.Path("/api/health")
public Response health() { public Response health() {
return Response.ok(Map.of("status", "ok", "version", "0.1.1")).build(); return Response.ok(Map.of("status", "ok", "version", "0.1.0")).build();
} }
private String guessContentType(String name) { private String guessContentType(String name) {
@@ -23,7 +23,7 @@ class StaticResourceTest {
assertInstanceOf(Map.class, entity); assertInstanceOf(Map.class, entity);
Map<?, ?> map = (Map<?, ?>) entity; Map<?, ?> map = (Map<?, ?>) entity;
assertEquals("ok", map.get("status")); assertEquals("ok", map.get("status"));
assertEquals("0.1.1", map.get("version")); assertEquals("0.1.0", map.get("version"));
} }
@Test @Test