deploy
Build and Deploy / build (push) Failing after 36s
Build and Deploy / deploy (push) Has been skipped

This commit is contained in:
2026-05-29 19:14:21 +02:00
parent ffd8b3e5c9
commit 4cc545478c
7 changed files with 67 additions and 140 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# Base URL of the backend HTTP API. # Base URL of the backend HTTP API.
VITE_API_BASE=https://localhost:3000 VITE_API_BASE=http://localhost:3000
# Base URL of the backend websocket. Optional: when omitted it is derived # Base URL of the backend websocket. Optional: when omitted it is derived
# from VITE_API_BASE by swapping the protocol (https -> wss). # from VITE_API_BASE by swapping the protocol (https -> wss).
VITE_WS_BASE=wss://localhost:3000 VITE_WS_BASE=ws://localhost:3000
+59
View File
@@ -0,0 +1,59 @@
name: Build and Deploy
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
run: |
git clone ${{ github.server_url }}/${{ github.repository }}.git .
git checkout ${{ github.sha }}
- name: Login to Gitea Registry
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | \
docker login https://gitea.johannesbot.de -u ${{ secrets.REGISTRY_USER }} --password-stdin
- name: Build Image
run: docker build -t gitea.johannesbot.de/johannesbot/mc-computer-craft-api-frontend:latest .
- name: Push Image
run: docker push gitea.johannesbot.de/johannesbot/mc-computer-craft-api-frontend:latest
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create deployment directory
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT || 22 }}
script: mkdir -p /home/${{ secrets.SSH_USER }}/mc-computer-craft-api-frontend
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT || 22 }}
script: |
cd /home/${{ secrets.SSH_USER }}/mc-computer-craft-api
# Login as root/sudo to ensure we can pull
echo "${{ secrets.REGISTRY_PASSWORD }}" | sudo docker login https://gitea.johannesbot.de -u ${{ secrets.REGISTRY_USER }} --password-stdin
sudo docker compose pull
sudo docker compose up -d --remove-orphans
sudo docker image prune -f
+2
View File
@@ -6,6 +6,8 @@ export interface LiveItem {
mod: string; mod: string;
amount: number; amount: number;
updatedAt: string; updatedAt: string;
/** Optional icon URL served by the backend (e.g. "/api/icon/minecraft/iron_ingot.png"). */
icon?: string | null;
} }
export interface ModInfo { export interface ModInfo {
+1
View File
@@ -49,6 +49,7 @@ function onModChange(event: Event): void {
function toggleOrder(): void { function toggleOrder(): void {
emit('update', { order: props.filters.order === 'asc' ? 'desc' : 'asc' }); emit('update', { order: props.filters.order === 'asc' ? 'desc' : 'asc' });
} }
</script>
<template> <template>
<div class="filter-bar panel"> <div class="filter-bar panel">
+1 -1
View File
@@ -68,7 +68,7 @@ function buildConfig(): ChartConfiguration<'line'> {
bodyColor: '#2fd4c4', bodyColor: '#2fd4c4',
padding: 10, padding: 10,
callbacks: { callbacks: {
label: (ctx) => ` ${fullNumber(ctx.parsed.y)}`, label: (ctx) => ` ${fullNumber(ctx.parsed.y ?? 0)}`,
}, },
}, },
}, },
-135
View File
@@ -1,135 +0,0 @@
<script setup lang="ts">
import { useRouter } from 'vue-router';
import type { LiveItem } from '../api/types.js';
import { abbreviateNumber, fullNumber } from '../utils/format.js';
defineProps<{
items: LiveItem[];
}>();
const router = useRouter();
function openItem(item: LiveItem): void {
router.push({ name: 'item', params: { name: item.name } });
}
function label(item: LiveItem): string {
return item.displayName ?? item.name;
}
</script>
<template>
<div class="table-wrap panel">
<table class="table">
<thead>
<tr>
<th class="table__col-item">Item</th>
<th class="table__col-mod">Mod</th>
<th class="table__col-amount">Amount</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in items"
:key="item.name"
class="table__row"
tabindex="0"
@click="openItem(item)"
@keydown.enter="openItem(item)"
>
<td class="table__col-item">
<span class="table__name">{{ label(item) }}</span>
<span class="table__id mono">{{ item.name }}</span>
</td>
<td class="table__col-mod">
<span class="tag mono">{{ item.mod }}</span>
</td>
<td class="table__col-amount mono" :title="fullNumber(item.amount)">
{{ abbreviateNumber(item.amount) }}
</td>
</tr>
<tr v-if="items.length === 0">
<td colspan="3" class="table__empty">No items match the current filters.</td>
</tr>
</tbody>
</table>
</div>
</template>
<style scoped>
.table-wrap {
overflow: hidden;
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th {
text-align: left;
font-size: 11px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-dim);
padding: 12px 16px;
border-bottom: 1px solid var(--border);
background: var(--bg-panel-2);
}
.table__col-amount {
text-align: right;
}
.table__row {
cursor: pointer;
transition: background-color 0.12s ease;
}
.table__row td {
padding: 11px 16px;
border-bottom: 1px solid var(--border);
}
.table__row:last-child td {
border-bottom: none;
}
.table__row:hover,
.table__row:focus {
background: var(--accent-soft);
outline: none;
}
.table__name {
display: block;
font-weight: 500;
}
.table__id {
display: block;
font-size: 11px;
color: var(--text-dim);
}
.tag {
display: inline-block;
font-size: 12px;
padding: 2px 8px;
border: 1px solid var(--border-bright);
border-radius: 5px;
color: var(--accent);
background: var(--accent-soft);
}
.table__col-amount {
font-size: 15px;
color: var(--text);
}
.table__empty {
text-align: center;
color: var(--text-dim);
padding: 28px 16px !important;
}
</style>
+2 -2
View File
@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import FilterBar from '../components/FilterBar.vue'; import FilterBar from '../components/FilterBar.vue';
import ItemTable from '../components/ItemTable.vue'; import ItemGrid from '../components/ItemGrid.vue';
import { useLiveData } from '../composables/useLiveData.js'; import { useLiveData } from '../composables/useLiveData.js';
import type { LiveFilters } from '../api/types.js'; import type { LiveFilters } from '../api/types.js';
import { abbreviateNumber, formatRelative } from '../utils/format.js'; import { abbreviateNumber, formatRelative } from '../utils/format.js';
@@ -53,7 +53,7 @@ function onFilterUpdate(value: Partial<LiveFilters>): void {
<span v-else>Waiting for first update</span> <span v-else>Waiting for first update</span>
</p> </p>
<ItemTable :items="items" /> <ItemGrid :items="items" />
</div> </div>
</template> </template>