6 Commits

Author SHA1 Message Date
b6511e5273 feat: add build job to CI workflow for Docker image creation and pushing
All checks were successful
CI / test (push) Successful in 12m19s
CI / build (push) Successful in 3m27s
2025-11-06 12:06:05 +01:00
bcb15bd0e4 chore: remove obsolete CI workflow configuration 2025-11-06 11:59:48 +01:00
42f8714d71 feat: add CI workflow configuration for testing and building
All checks were successful
CI / test (push) Successful in 14m26s
2025-11-06 11:44:35 +01:00
1881ebe24f fix: correct syntax for environment variable references in CI workflow
All checks were successful
CI / test (push) Successful in 6m11s
2025-11-04 21:36:05 +01:00
d90aae3d0a style: update CSS variables and styles for improved theming and consistency
Some checks failed
CI / test (push) Failing after 4m1s
2025-11-04 21:23:52 +01:00
9934d1483d Merge pull request 'feat/ci-overhaul-20251029' (#11) from feat/ci-overhaul-20251029 into main
Some checks failed
CI / test (push) Failing after 2m5s
Reviewed-on: #11
2025-11-02 18:13:14 +01:00
4 changed files with 222 additions and 139 deletions

View File

@@ -1,74 +0,0 @@
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
env:
APT_CACHER_NG: http://192.168.88.14:3142
DB_DRIVER: postgresql+psycopg2
DB_HOST: 192.168.88.35
DB_NAME: calminer_test
DB_USER: calminer
DB_PASSWORD: calminer_password
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17
env:
POSTGRES_USER: ${ { env.DB_USER } }
POSTGRES_PASSWORD: ${ { env.DB_PASSWORD } }
POSTGRES_DB: ${ { env.DB_NAME } }
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Update apt-cacher-ng config
run: |-
echo 'Acquire::http::Proxy "{{ env.APT_CACHER_NG }}";' | tee /etc/apt/apt.conf.d/01apt-cacher-ng
apt-get update
- name: Update system packages
run: apt-get upgrade -y
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Install Playwright system dependencies
run: playwright install-deps
- name: Install Playwright browsers
run: playwright install
- name: Run tests
env:
DATABASE_DRIVER: ${ { env.DB_DRIVER } }
DATABASE_HOST: ${ { env.DB_HOST } }
DATABASE_PORT: 5432
DATABASE_USER: ${ { env.DB_USER } }
DATABASE_PASSWORD: ${ { env.DB_PASSWORD } }
DATABASE_NAME: ${ { env.DB_NAME } }
run: |
pytest tests/ --cov=.
- name: Build Docker image
run: |
docker build -t calminer .

View File

@@ -0,0 +1,140 @@
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
env:
APT_CACHER_NG: http://192.168.88.14:3142
DB_DRIVER: postgresql+psycopg2
DB_HOST: 192.168.88.35
DB_NAME: calminer_test
DB_USER: calminer
DB_PASSWORD: calminer_password
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17
env:
POSTGRES_USER: ${{ env.DB_USER }}
POSTGRES_PASSWORD: ${{ env.DB_PASSWORD }}
POSTGRES_DB: ${{ env.DB_NAME }}
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Get pip cache dir
id: pip-cache
run: |
echo "path=$(pip cache dir)" >> $GITEA_OUTPUT
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ${{ steps.pip-cache.outputs.path }}
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt', 'requirements-test.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Update apt-cacher-ng config
run: |-
echo 'Acquire::http::Proxy "{{ env.APT_CACHER_NG }}";' | tee /etc/apt/apt.conf.d/01apt-cacher-ng
apt-get update
- name: Update system packages
run: apt-get upgrade -y
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Install Playwright system dependencies
run: playwright install-deps
- name: Install Playwright browsers
run: playwright install
- name: Run tests
env:
DATABASE_DRIVER: ${{ env.DB_DRIVER }}
DATABASE_HOST: postgres
DATABASE_PORT: 5432
DATABASE_USER: ${{ env.DB_USER }}
DATABASE_PASSWORD: ${{ env.DB_PASSWORD }}
DATABASE_NAME: ${{ env.DB_NAME }}
run: |
pytest tests/ --cov=.
- name: Build Docker image
run: |
docker build -t calminer .
build:
runs-on: ubuntu-latest
needs: test
env:
DEFAULT_BRANCH: main
REGISTRY_URL: ${{ secrets.REGISTRY_URL }}
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
REGISTRY_CONTAINER_NAME: calminer
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Collect workflow metadata
id: meta
shell: bash
run: |
ref_name="${GITHUB_REF_NAME:-${GITHUB_REF##*/}}"
event_name="${GITHUB_EVENT_NAME:-}"
sha="${GITHUB_SHA:-}"
if [ "$ref_name" = "${DEFAULT_BRANCH:-main}" ]; then
echo "on_default=true" >> "$GITHUB_OUTPUT"
else
echo "on_default=false" >> "$GITHUB_OUTPUT"
fi
echo "ref_name=$ref_name" >> "$GITHUB_OUTPUT"
echo "event_name=$event_name" >> "$GITHUB_OUTPUT"
echo "sha=$sha" >> "$GITHUB_OUTPUT"
- name: Set up QEMU and Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to gitea registry
if: ${{ steps.meta.outputs.on_default == 'true' }}
uses: docker/login-action@v3
continue-on-error: true
with:
registry: ${{ env.REGISTRY_URL }}
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ env.REGISTRY_PASSWORD }}
- name: Build and push image
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile
push: ${{ steps.meta.outputs.on_default == 'true' && steps.meta.outputs.event_name != 'pull_request' && (env.REGISTRY_URL != '' && env.REGISTRY_USERNAME != '' && env.REGISTRY_PASSWORD != '') }}
tags: |
${{ env.REGISTRY_URL }}/allucanget/${{ env.REGISTRY_CONTAINER_NAME }}:latest
${{ env.REGISTRY_URL }}/allucanget/${{ env.REGISTRY_CONTAINER_NAME }}:${{ steps.meta.outputs.sha }}

View File

@@ -1 +0,0 @@
black

View File

@@ -1,25 +1,29 @@
:root { :root {
--color-background: #f4f5f7; --bg: #0b0f14;
--color-surface: #ffffff; --bg-2: #0f141b;
--color-text-primary: #2a1f33; --card: #151b23;
--color-text-secondary: #624769; --text: #e6edf3;
--color-text-muted: #64748b; --muted: #a9b4c0;
--color-text-subtle: #94a3b8; --brand: #f1b21a;
--brand-2: #f6c648;
--brand-3: #f9d475;
--accent: #2ba58f;
--danger: #d14b4b;
--shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
--radius: 14px;
--radius-sm: 10px;
--container: 1180px;
--muted: var(--muted);
--color-text-subtle: rgba(169, 180, 192, 0.6);
--color-text-invert: #ffffff; --color-text-invert: #ffffff;
--color-text-dark: #0f172a; --color-text-dark: #0f172a;
--color-text-strong: #111827; --color-text-strong: #111827;
--color-primary: #5f320d; --color-border: rgba(255, 255, 255, 0.08);
--color-primary-strong: #7e4c13; --color-border-strong: rgba(255, 255, 255, 0.12);
--color-primary-stronger: #837c15; --color-highlight: rgba(241, 178, 26, 0.08);
--color-accent: #bff838; --color-panel-shadow: rgba(0, 0, 0, 0.25);
--color-border: #e2e8f0; --color-panel-shadow-deep: rgba(0, 0, 0, 0.35);
--color-border-strong: #cbd5e1; --color-surface-alt: rgba(21, 27, 35, 0.7);
--color-highlight: #eef2ff;
--color-panel-shadow: rgba(15, 23, 42, 0.08);
--color-panel-shadow-deep: rgba(15, 23, 42, 0.12);
--color-surface-alt: #f8fafc;
--color-success: #047857;
--color-error: #b91c1c;
--space-2xs: 0.25rem; --space-2xs: 0.25rem;
--space-xs: 0.5rem; --space-xs: 0.5rem;
--space-sm: 0.75rem; --space-sm: 0.75rem;
@@ -33,15 +37,30 @@
--font-size-lg: 1.25rem; --font-size-lg: 1.25rem;
--font-size-xl: 1.5rem; --font-size-xl: 1.5rem;
--font-size-2xl: 2rem; --font-size-2xl: 2rem;
--panel-radius: 12px; --panel-radius: var(--radius);
--table-radius: 10px; --table-radius: var(--radius-sm);
}
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
} }
body { body {
margin: 0; margin: 0;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', 'Roboto',
background-color: var(--color-background); Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji';
color: var(--color-text-primary); color: var(--text);
background: linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 100%);
line-height: 1.45;
}
a {
color: var(--brand);
} }
.app-layout { .app-layout {
@@ -51,7 +70,7 @@ body {
.app-sidebar { .app-sidebar {
width: 264px; width: 264px;
background-color: var(--color-primary); background-color: var(--card);
color: var(--color-text-invert); color: var(--color-text-invert);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -59,6 +78,7 @@ body {
position: sticky; position: sticky;
top: 0; top: 0;
height: 100vh; height: 100vh;
border-right: 1px solid var(--color-border);
} }
.sidebar-inner { .sidebar-inner {
@@ -82,11 +102,7 @@ body {
width: 44px; width: 44px;
height: 44px; height: 44px;
border-radius: 12px; border-radius: 12px;
background: linear-gradient( background: linear-gradient(0deg, var(--brand-3), var(--accent));
0deg,
var(--color-primary-stronger),
var(--color-accent)
);
color: var(--color-text-invert); color: var(--color-text-invert);
font-weight: 700; font-weight: 700;
font-size: 1.1rem; font-size: 1.1rem;
@@ -207,7 +223,7 @@ body {
} }
.app-main { .app-main {
background-color: var(--color-background); background-color: var(--bg);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
@@ -240,7 +256,7 @@ body {
.dashboard-subtitle { .dashboard-subtitle {
margin: 0.35rem 0 0; margin: 0.35rem 0 0;
color: var(--color-text-muted); color: var(--muted);
} }
.dashboard-actions { .dashboard-actions {
@@ -259,7 +275,7 @@ body {
.page-subtitle { .page-subtitle {
margin-top: 0.35rem; margin-top: 0.35rem;
color: var(--color-text-muted); color: var(--muted);
font-size: 0.95rem; font-size: 0.95rem;
} }
@@ -271,13 +287,14 @@ body {
} }
.settings-card { .settings-card {
background: var(--color-surface); background: var(--card);
border-radius: 12px; border-radius: var(--radius);
padding: 1.5rem; padding: 1.5rem;
box-shadow: 0 4px 14px var(--color-panel-shadow); box-shadow: var(--shadow);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.75rem; gap: 0.75rem;
border: 1px solid var(--color-border);
} }
.settings-card h2 { .settings-card h2 {
@@ -287,7 +304,7 @@ body {
.settings-card p { .settings-card p {
margin: 0; margin: 0;
color: var(--color-text-muted); color: var(--muted);
} }
.settings-card-note { .settings-card-note {
@@ -311,7 +328,7 @@ body {
.color-form-field.is-env-override { .color-form-field.is-env-override {
background: rgba(191, 248, 56, 0.12); background: rgba(191, 248, 56, 0.12);
border-color: var(--color-accent); border-color: var(--accent);
} }
.color-field-header { .color-field-header {
@@ -319,13 +336,13 @@ body {
justify-content: space-between; justify-content: space-between;
gap: var(--space-sm); gap: var(--space-sm);
font-weight: 600; font-weight: 600;
color: var(--color-text-strong); color: var(--text);
font-family: "Fira Code", "Consolas", "Courier New", monospace; font-family: 'Fira Code', 'Consolas', 'Courier New', monospace;
font-size: 0.85rem; font-size: 0.85rem;
} }
.color-field-default { .color-field-default {
color: var(--color-text-muted); color: var(--muted);
font-weight: 500; font-weight: 500;
} }
@@ -337,7 +354,7 @@ body {
.color-env-flag { .color-env-flag {
font-size: 0.78rem; font-size: 0.78rem;
font-weight: 600; font-weight: 600;
color: var(--color-accent); color: var(--accent);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.04em; letter-spacing: 0.04em;
} }
@@ -349,7 +366,7 @@ body {
} }
.color-value-input { .color-value-input {
font-family: "Fira Code", "Consolas", "Courier New", monospace; font-family: 'Fira Code', 'Consolas', 'Courier New', monospace;
} }
.color-value-input[disabled] { .color-value-input[disabled] {
@@ -378,7 +395,7 @@ body {
} }
.env-overrides-table code { .env-overrides-table code {
font-family: "Fira Code", "Consolas", "Courier New", monospace; font-family: 'Fira Code', 'Consolas', 'Courier New', monospace;
font-size: 0.85rem; font-size: 0.85rem;
} }
@@ -391,7 +408,7 @@ body {
border-radius: 999px; border-radius: 999px;
font-weight: 600; font-weight: 600;
text-decoration: none; text-decoration: none;
background: var(--color-primary); background: var(--brand);
color: var(--color-text-invert); color: var(--color-text-invert);
transition: transform 0.2s ease, box-shadow 0.2s ease; transition: transform 0.2s ease, box-shadow 0.2s ease;
} }
@@ -410,26 +427,27 @@ body {
} }
.metric-card { .metric-card {
background: var(--color-surface); background: var(--card);
border-radius: 12px; border-radius: var(--radius);
padding: 1.2rem 1.4rem; padding: 1.2rem 1.4rem;
box-shadow: 0 4px 14px var(--color-panel-shadow); box-shadow: var(--shadow);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.35rem; gap: 0.35rem;
border: 1px solid var(--color-border);
} }
.metric-label { .metric-label {
font-size: 0.82rem; font-size: 0.82rem;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.04em; letter-spacing: 0.04em;
color: var(--color-text-muted); color: var(--muted);
} }
.metric-value { .metric-value {
font-size: 1.45rem; font-size: 1.45rem;
font-weight: 700; font-weight: 700;
color: var(--color-text-dark); color: var(--muted);
} }
.dashboard-charts { .dashboard-charts {
@@ -522,7 +540,7 @@ body {
} }
.list-detail { .list-detail {
color: var(--color-text-secondary); color: var(--muted);
font-size: 0.95rem; font-size: 0.95rem;
} }
@@ -532,7 +550,7 @@ body {
} }
.btn.is-loading::after { .btn.is-loading::after {
content: ""; content: '';
width: 0.85rem; width: 0.85rem;
height: 0.85rem; height: 0.85rem;
border: 2px solid rgba(255, 255, 255, 0.6); border: 2px solid rgba(255, 255, 255, 0.6);
@@ -550,7 +568,7 @@ body {
} }
.panel { .panel {
background-color: var(--color-surface); background-color: var(--card);
border-radius: var(--panel-radius); border-radius: var(--panel-radius);
padding: var(--space-xl); padding: var(--space-xl);
box-shadow: 0 2px 8px var(--color-panel-shadow); box-shadow: 0 2px 8px var(--color-panel-shadow);
@@ -560,7 +578,7 @@ body {
.panel h2, .panel h2,
.panel h3 { .panel h3 {
font-weight: 700; font-weight: 700;
color: var(--color-text-dark); color: var(--text);
margin: 0 0 var(--space-sm); margin: 0 0 var(--space-sm);
} }
@@ -583,7 +601,7 @@ body {
flex-direction: column; flex-direction: column;
gap: var(--space-sm); gap: var(--space-sm);
font-weight: 600; font-weight: 600;
color: var(--color-text-strong); color: var(--text);
} }
.form-grid input, .form-grid input,
@@ -598,7 +616,7 @@ body {
.form-grid input:focus, .form-grid input:focus,
.form-grid textarea:focus, .form-grid textarea:focus,
.form-grid select:focus { .form-grid select:focus {
outline: 2px solid var(--color-primary-strong); outline: 2px solid var(--brand-2);
outline-offset: 1px; outline-offset: 1px;
} }
@@ -624,13 +642,13 @@ body {
} }
.btn.primary { .btn.primary {
background-color: var(--color-primary-strong); background-color: var(--brand-2);
color: var(--color-text-invert); color: var(--color-text-invert);
} }
.btn.primary:hover, .btn.primary:hover,
.btn.primary:focus { .btn.primary:focus {
background-color: var(--color-primary-stronger); background-color: var(--brand-3);
} }
.result-output { .result-output {
@@ -638,14 +656,14 @@ body {
color: var(--color-surface-alt); color: var(--color-surface-alt);
padding: 1rem; padding: 1rem;
border-radius: 8px; border-radius: 8px;
font-family: "Fira Code", "Consolas", "Courier New", monospace; font-family: 'Fira Code', 'Consolas', 'Courier New', monospace;
overflow-x: auto; overflow-x: auto;
margin-top: 1.5rem; margin-top: 1.5rem;
} }
.monospace-input { .monospace-input {
width: 100%; width: 100%;
font-family: "Fira Code", "Consolas", "Courier New", monospace; font-family: 'Fira Code', 'Consolas', 'Courier New', monospace;
min-height: 120px; min-height: 120px;
} }
@@ -670,7 +688,7 @@ table {
} }
thead { thead {
background-color: var(--color-primary); background-color: var(--brand);
color: var(--color-text-invert); color: var(--color-text-invert);
} }
@@ -687,7 +705,7 @@ tbody tr:nth-child(even) {
.empty-state { .empty-state {
margin-top: 1.5rem; margin-top: 1.5rem;
color: var(--color-text-muted); color: var(--muted);
font-style: italic; font-style: italic;
} }
@@ -701,15 +719,15 @@ tbody tr:nth-child(even) {
} }
.feedback.success { .feedback.success {
color: var(--color-success); color: var(--accent);
} }
.feedback.error { .feedback.error {
color: var(--color-error); color: var(--danger);
} }
.site-footer { .site-footer {
background-color: var(--color-primary); background-color: var(--brand);
color: var(--color-text-invert); color: var(--color-text-invert);
margin-top: 3rem; margin-top: 3rem;
} }