472 lines
28 KiB
HTML
472 lines
28 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="navy" dir="ltr">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>Docker - JellyTau Documentation</title>
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
<meta name="description" content="Requirements, traceability, and architecture for the JellyTau Jellyfin client.">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff">
|
|
|
|
<link rel="icon" href="../favicon.svg">
|
|
<link rel="shortcut icon" href="../favicon.png">
|
|
<link rel="stylesheet" href="../css/variables.css">
|
|
<link rel="stylesheet" href="../css/general.css">
|
|
<link rel="stylesheet" href="../css/chrome.css">
|
|
<link rel="stylesheet" href="../css/print.css" media="print">
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
|
<link rel="stylesheet" href="../fonts/fonts.css">
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" href="../highlight.css">
|
|
<link rel="stylesheet" href="../tomorrow-night.css">
|
|
<link rel="stylesheet" href="../ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
</head>
|
|
<body class="sidebar-visible no-js">
|
|
<div id="body-container">
|
|
<!-- Provide site root to javascript -->
|
|
<script>
|
|
var path_to_root = "../";
|
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "navy";
|
|
</script>
|
|
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script>
|
|
try {
|
|
var theme = localStorage.getItem('mdbook-theme');
|
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script>
|
|
var theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
var html = document.querySelector('html');
|
|
html.classList.remove('navy')
|
|
html.classList.add(theme);
|
|
var body = document.querySelector('body');
|
|
body.classList.remove('no-js')
|
|
body.classList.add('js');
|
|
</script>
|
|
|
|
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script>
|
|
var body = document.querySelector('body');
|
|
var sidebar = null;
|
|
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
} else {
|
|
sidebar = 'hidden';
|
|
}
|
|
sidebar_toggle.checked = sidebar === 'visible';
|
|
body.classList.remove('sidebar-visible');
|
|
body.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<div class="sidebar-scrollbox">
|
|
<ol class="chapter"><li class="chapter-item expanded affix "><a href="../index.html">Introduction</a></li><li class="chapter-item expanded affix "><li class="part-title">Requirements & Traceability</li><li class="chapter-item expanded "><a href="../requirements.html"><strong aria-hidden="true">1.</strong> Requirements Specification</a></li><li class="chapter-item expanded "><a href="../traceability.html"><strong aria-hidden="true">2.</strong> Traceability Matrix</a></li><li class="chapter-item expanded "><a href="../traceability-ci.html"><strong aria-hidden="true">3.</strong> Traceability CI</a></li><li class="chapter-item expanded "><a href="../traces-quick-ref.html"><strong aria-hidden="true">4.</strong> Traces Quick Reference</a></li><li class="chapter-item expanded affix "><li class="part-title">Architecture</li><li class="chapter-item expanded "><a href="../architecture/index.html"><strong aria-hidden="true">5.</strong> Overview</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../architecture/01-rust-backend.html"><strong aria-hidden="true">5.1.</strong> Rust Backend</a></li><li class="chapter-item "><a href="../architecture/02-svelte-frontend.html"><strong aria-hidden="true">5.2.</strong> Svelte Frontend</a></li><li class="chapter-item "><a href="../architecture/03-data-flow.html"><strong aria-hidden="true">5.3.</strong> Data Flow</a></li><li class="chapter-item "><a href="../architecture/04-type-sync-and-threading.html"><strong aria-hidden="true">5.4.</strong> Type Sync & Threading</a></li><li class="chapter-item "><a href="../architecture/05-platform-backends.html"><strong aria-hidden="true">5.5.</strong> Platform Backends</a></li><li class="chapter-item "><a href="../architecture/06-downloads-and-offline.html"><strong aria-hidden="true">5.6.</strong> Downloads & Offline</a></li><li class="chapter-item "><a href="../architecture/07-connectivity.html"><strong aria-hidden="true">5.7.</strong> Connectivity</a></li><li class="chapter-item "><a href="../architecture/08-database-design.html"><strong aria-hidden="true">5.8.</strong> Database Design</a></li><li class="chapter-item "><a href="../architecture/09-security.html"><strong aria-hidden="true">5.9.</strong> Security</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">UX</li><li class="chapter-item expanded "><a href="../ux-flows.html"><strong aria-hidden="true">6.</strong> UX Flows</a></li><li class="chapter-item expanded affix "><li class="part-title">Specs — Pending Work</li><li class="chapter-item expanded "><a href="../specs/index.html"><strong aria-hidden="true">7.</strong> Specs Index</a></li><li class="chapter-item expanded "><a href="../specs/SPEC-TEMPLATE.html"><strong aria-hidden="true">8.</strong> Spec Template</a></li><li class="chapter-item expanded "><a href="../specs/SPEC-REVIEW-CHECKLIST.html"><strong aria-hidden="true">9.</strong> Spec Review Checklist</a></li><li class="chapter-item expanded "><a href="../specs/playback-backend-unification.html"><strong aria-hidden="true">10.</strong> Playback Backend Unification</a></li><li class="chapter-item expanded "><a href="../specs/linux-native-video-spike.html"><strong aria-hidden="true">11.</strong> Linux Native Video Spike</a></li><li class="chapter-item expanded "><a href="../specs/backend-owned-stream-selection.html"><strong aria-hidden="true">12.</strong> Backend-Owned Stream Selection</a></li><li class="chapter-item expanded "><a href="../specs/player-facade-enforcement.html"><strong aria-hidden="true">13.</strong> Player Facade Enforcement</a></li><li class="chapter-item expanded "><a href="../specs/windows-native-audio-backend.html"><strong aria-hidden="true">14.</strong> Windows Native Audio Backend</a></li><li class="chapter-item expanded "><a href="../specs/libmpv2-migration.html"><strong aria-hidden="true">15.</strong> libmpv2 Migration</a></li><li class="chapter-item expanded "><a href="../specs/read-through-media-cache.html"><strong aria-hidden="true">16.</strong> Read-Through Media Cache</a></li><li class="chapter-item expanded "><a href="../specs/scoped-search.html"><strong aria-hidden="true">17.</strong> Scoped Search</a></li><li class="chapter-item expanded "><a href="../specs/scoped-search-boundary.html"><strong aria-hidden="true">18.</strong> Scoped Search Boundary</a></li><li class="chapter-item expanded "><a href="../specs/scoped-search-boundary-implementation.html"><strong aria-hidden="true">19.</strong> Scoped Search Boundary — Implementation</a></li><li class="chapter-item expanded "><a href="../specs/frontend-domain-model.html"><strong aria-hidden="true">20.</strong> Frontend Domain Model</a></li><li class="chapter-item expanded "><a href="../specs/desktop-native-video.html"><strong aria-hidden="true">21.</strong> Desktop Native Video</a></li><li class="chapter-item expanded "><a href="../specs/build-provenance.html"><strong aria-hidden="true">22.</strong> Build Provenance</a></li><li class="chapter-item expanded affix "><li class="part-title">Build & Release</li><li class="chapter-item expanded "><a href="../build/build-release.html"><strong aria-hidden="true">23.</strong> Build & Release</a></li><li class="chapter-item expanded "><a href="../release-checklist.html"><strong aria-hidden="true">24.</strong> Release Checklist</a></li><li class="chapter-item expanded "><a href="../native-player-verification.html"><strong aria-hidden="true">25.</strong> Native Player Verification</a></li><li class="chapter-item expanded "><a href="../build/build-desktop-packages.html"><strong aria-hidden="true">26.</strong> Desktop Packaging</a></li><li class="chapter-item expanded "><a href="../build/build-windows.html"><strong aria-hidden="true">27.</strong> Windows Build</a></li><li class="chapter-item expanded "><a href="../defect-windows.html"><strong aria-hidden="true">28.</strong> Defect Windows</a></li><li class="chapter-item expanded "><a href="../build/docker.html" class="active"><strong aria-hidden="true">29.</strong> Docker</a></li><li class="chapter-item expanded "><a href="../build/build-builder-image.html"><strong aria-hidden="true">30.</strong> Builder Image</a></li><li class="chapter-item expanded affix "><li class="spacer"></li><li class="chapter-item expanded affix "><a href="../api-redirect.html">Rust API Reference (rustdoc)</a></li></ol>
|
|
</div>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
|
<div class="sidebar-resize-indicator"></div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Track and set sidebar scroll position -->
|
|
<script>
|
|
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
|
|
sidebarScrollbox.addEventListener('click', function(e) {
|
|
if (e.target.tagName === 'A') {
|
|
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
|
|
}
|
|
}, { passive: true });
|
|
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
|
|
sessionStorage.removeItem('sidebar-scroll');
|
|
if (sidebarScrollTop) {
|
|
// preserve sidebar scroll position when navigating via links within sidebar
|
|
sidebarScrollbox.scrollTop = sidebarScrollTop;
|
|
} else {
|
|
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
|
|
var activeSection = document.querySelector('#sidebar .active');
|
|
if (activeSection) {
|
|
activeSection.scrollIntoView({ block: 'center' });
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
<div id="menu-bar" class="menu-bar sticky">
|
|
<div class="left-buttons">
|
|
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</label>
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<h1 class="menu-title">JellyTau Documentation</h1>
|
|
|
|
<div class="right-buttons">
|
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
</a>
|
|
<a href="https://gitea.tourolle.paris/dtourolle/jellytau" title="Git repository" aria-label="Git repository">
|
|
<i id="git-repository-button" class="fa fa-github"></i>
|
|
</a>
|
|
<a href="https://gitea.tourolle.paris/dtourolle/jellytau/_edit/master/docs/../docs/build/docker.md" title="Suggest an edit" aria-label="Suggest an edit">
|
|
<i id="git-edit-button" class="fa fa-edit"></i>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script>
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<h1 id="docker--cicd-setup-for-jellytau"><a class="header" href="#docker--cicd-setup-for-jellytau">Docker & CI/CD Setup for JellyTau</a></h1>
|
|
<p>This document explains how to use the Docker configuration and Gitea Act CI/CD pipeline for building and testing JellyTau.</p>
|
|
<h2 id="overview"><a class="header" href="#overview">Overview</a></h2>
|
|
<p>The setup includes:</p>
|
|
<ul>
|
|
<li><strong>Dockerfile.builder</strong>: Pre-built image with all dependencies (push to your registry)</li>
|
|
<li><strong>Dockerfile</strong>: Multi-stage build for local testing and building</li>
|
|
<li><strong>docker-compose.yml</strong>: Orchestration for local development and testing</li>
|
|
<li><strong>.gitea/workflows/build-and-test.yml</strong>: Automated CI/CD pipeline using pre-built builder image</li>
|
|
</ul>
|
|
<h3 id="quick-start"><a class="header" href="#quick-start">Quick Start</a></h3>
|
|
<p><strong>For CI/CD (Gitea Actions)</strong>:</p>
|
|
<ol>
|
|
<li>Build and push builder image (see <a href="build-builder-image.html">build-builder-image.md</a>)</li>
|
|
<li>Push to master branch - workflow runs automatically</li>
|
|
<li>Check Actions tab for results and APK artifacts</li>
|
|
</ol>
|
|
<p><strong>For Local Testing</strong>:</p>
|
|
<pre><code class="language-bash">docker-compose run test # Run tests
|
|
docker-compose run android-build # Build APK
|
|
docker-compose run dev # Interactive shell
|
|
</code></pre>
|
|
<h2 id="docker-usage"><a class="header" href="#docker-usage">Docker Usage</a></h2>
|
|
<h3 id="prerequisites"><a class="header" href="#prerequisites">Prerequisites</a></h3>
|
|
<ul>
|
|
<li>Docker Engine 20.10+</li>
|
|
<li>Docker Compose 2.0+ (if using docker-compose)</li>
|
|
<li>At least 10GB free disk space (for Android SDK and build artifacts)</li>
|
|
</ul>
|
|
<h3 id="building-the-docker-image"><a class="header" href="#building-the-docker-image">Building the Docker Image</a></h3>
|
|
<pre><code class="language-bash"># Build the complete image
|
|
docker build -t jellytau:latest .
|
|
|
|
# Build specific target
|
|
docker build -t jellytau:test --target test .
|
|
docker build -t jellytau:android --target android-build .
|
|
</code></pre>
|
|
<h3 id="using-docker-compose"><a class="header" href="#using-docker-compose">Using Docker Compose</a></h3>
|
|
<h4 id="run-tests-only"><a class="header" href="#run-tests-only">Run Tests Only</a></h4>
|
|
<pre><code class="language-bash">docker-compose run test
|
|
</code></pre>
|
|
<p>This will:</p>
|
|
<ol>
|
|
<li>Install all dependencies</li>
|
|
<li>Run frontend tests (Vitest)</li>
|
|
<li>Run Rust backend tests</li>
|
|
<li>Report results</li>
|
|
</ol>
|
|
<h4 id="build-android-apk"><a class="header" href="#build-android-apk">Build Android APK</a></h4>
|
|
<pre><code class="language-bash">docker-compose run android-build
|
|
</code></pre>
|
|
<p>This will:</p>
|
|
<ol>
|
|
<li>Run tests first (depends on test service)</li>
|
|
<li>If tests pass, build the Android APK</li>
|
|
<li>Output APK files to <code>src-tauri/gen/android/app/build/outputs/apk/</code></li>
|
|
</ol>
|
|
<h4 id="interactive-development"><a class="header" href="#interactive-development">Interactive Development</a></h4>
|
|
<pre><code class="language-bash">docker-compose run dev
|
|
</code></pre>
|
|
<p>This starts an interactive shell with all development tools available. From here you can:</p>
|
|
<pre><code class="language-bash">bun install
|
|
bun run build
|
|
bun test
|
|
bun run tauri android build --apk true
|
|
</code></pre>
|
|
<h4 id="run-all-services-in-sequence"><a class="header" href="#run-all-services-in-sequence">Run All Services in Sequence</a></h4>
|
|
<pre><code class="language-bash">docker-compose up --abort-on-container-exit
|
|
</code></pre>
|
|
<h3 id="extracting-build-artifacts"><a class="header" href="#extracting-build-artifacts">Extracting Build Artifacts</a></h3>
|
|
<p>After a successful build, APK files are located in:</p>
|
|
<pre><code>src-tauri/gen/android/app/build/outputs/apk/
|
|
</code></pre>
|
|
<p>Copy to your host machine:</p>
|
|
<pre><code class="language-bash">docker cp jellytau-android-build:/app/src-tauri/gen/android/app/build/outputs/apk ./apk-output
|
|
</code></pre>
|
|
<h2 id="gitea-act-cicd-pipeline"><a class="header" href="#gitea-act-cicd-pipeline">Gitea Act CI/CD Pipeline</a></h2>
|
|
<p>The <code>.gitea/workflows/build-and-test.yml</code> workflow automates:</p>
|
|
<p><strong>Single Job</strong>: Runs on every push to <code>master</code> and PRs</p>
|
|
<ul>
|
|
<li>Uses pre-built builder image (no setup time)</li>
|
|
<li>Installs project dependencies</li>
|
|
<li>Runs frontend tests (Vitest)</li>
|
|
<li>Runs Rust backend tests</li>
|
|
<li>Builds the frontend</li>
|
|
<li>Builds the Android APK</li>
|
|
<li>Uploads APK as artifact (30-day retention)</li>
|
|
</ul>
|
|
<p>The workflow skips markdown files to avoid unnecessary builds.</p>
|
|
<h3 id="workflow-triggers"><a class="header" href="#workflow-triggers">Workflow Triggers</a></h3>
|
|
<p>The workflow runs on:</p>
|
|
<ul>
|
|
<li>Push to <code>master</code> or <code>main</code> branches</li>
|
|
<li>Pull requests to <code>master</code> or <code>main</code> branches</li>
|
|
<li>Can be extended with: <code>workflow_dispatch</code> for manual triggers</li>
|
|
</ul>
|
|
<h3 id="setting-up-the-builder-image"><a class="header" href="#setting-up-the-builder-image">Setting Up the Builder Image</a></h3>
|
|
<p>Before using the CI/CD pipeline, you must build and push the builder image:</p>
|
|
<pre><code class="language-bash"># Build the image
|
|
docker build -f Dockerfile.builder -t jellytau-builder:latest .
|
|
|
|
# Tag for your registry
|
|
docker tag jellytau-builder:latest gitea.tourolle.paris/dtourolle/jellytau-builder:latest
|
|
|
|
# Push to registry
|
|
docker push gitea.tourolle.paris/dtourolle/jellytau-builder:latest
|
|
</code></pre>
|
|
<p>See <a href="build-builder-image.html">build-builder-image.md</a> for detailed instructions.</p>
|
|
<h3 id="setting-up-gitea-act"><a class="header" href="#setting-up-gitea-act">Setting Up Gitea Act</a></h3>
|
|
<ol>
|
|
<li>
|
|
<p><strong>Ensure builder image is pushed</strong> (see above)</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Push to Gitea repository</strong>:
|
|
The workflow will automatically trigger on push to <code>master</code> or pull requests</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>View workflow runs in Gitea UI</strong>:</p>
|
|
<ul>
|
|
<li>Navigate to your repository</li>
|
|
<li>Go to Actions tab</li>
|
|
<li>Click on workflow runs to see logs</li>
|
|
</ul>
|
|
</li>
|
|
<li>
|
|
<p><strong>Test locally</strong> (optional):</p>
|
|
<pre><code class="language-bash"># Install act if needed
|
|
curl https://gitea.com/actions/setup-act/releases/download/v0.25.0/act-0.25.0-linux-x86_64.tar.gz | tar xz
|
|
|
|
# Run locally (requires builder image to be available)
|
|
./act push --file .gitea/workflows/build-and-test.yml
|
|
</code></pre>
|
|
</li>
|
|
</ol>
|
|
<h3 id="customizing-the-workflow"><a class="header" href="#customizing-the-workflow">Customizing the Workflow</a></h3>
|
|
<h4 id="modify-build-triggers"><a class="header" href="#modify-build-triggers">Modify Build Triggers</a></h4>
|
|
<p>Edit <code>.gitea/workflows/build-and-test.yml</code> to change when builds run:</p>
|
|
<pre><code class="language-yaml">on:
|
|
push:
|
|
branches:
|
|
- master
|
|
- develop # Add more branches
|
|
paths:
|
|
- 'src/**' # Only run if src/ changes
|
|
- 'src-tauri/**' # Only run if Rust code changes
|
|
</code></pre>
|
|
<h4 id="add-notifications"><a class="header" href="#add-notifications">Add Notifications</a></h4>
|
|
<p>Add Slack, Discord, or email notifications on build completion:</p>
|
|
<pre><code class="language-yaml">- name: Notify on success
|
|
if: success()
|
|
run: |
|
|
curl -X POST https://slack-webhook-url...
|
|
</code></pre>
|
|
<h4 id="customize-apk-upload"><a class="header" href="#customize-apk-upload">Customize APK Upload</a></h4>
|
|
<p>Modify artifact retention or add to cloud storage:</p>
|
|
<pre><code class="language-yaml">- name: Upload APK to S3
|
|
uses: actions/s3-sync@v1
|
|
with:
|
|
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY }}
|
|
aws_secret_access_key: ${{ secrets.AWS_SECRET_KEY }}
|
|
aws_bucket: my-apk-bucket
|
|
source_dir: src-tauri/gen/android/app/build/outputs/apk/
|
|
</code></pre>
|
|
<h2 id="environment-setup-in-ci"><a class="header" href="#environment-setup-in-ci">Environment Setup in CI</a></h2>
|
|
<h3 id="secret-variables"><a class="header" href="#secret-variables">Secret Variables</a></h3>
|
|
<p>To use secrets in the workflow, set them in Gitea:</p>
|
|
<ol>
|
|
<li>Go to Repository Settings → Secrets</li>
|
|
<li>Add secrets like:
|
|
<ul>
|
|
<li><code>AWS_ACCESS_KEY</code> for S3 uploads</li>
|
|
<li><code>SLACK_WEBHOOK_URL</code> for notifications</li>
|
|
<li><code>GITHUB_TOKEN</code> for releases (pre-configured)</li>
|
|
</ul>
|
|
</li>
|
|
</ol>
|
|
<h2 id="troubleshooting"><a class="header" href="#troubleshooting">Troubleshooting</a></h2>
|
|
<h3 id="out-of-memory-during-build"><a class="header" href="#out-of-memory-during-build">Out of Memory During Build</a></h3>
|
|
<p>Android builds are memory-intensive. If you get OOM errors:</p>
|
|
<pre><code class="language-bash"># Limit memory in docker-compose
|
|
services:
|
|
android-build:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 6G
|
|
</code></pre>
|
|
<p>Or increase Docker's memory allocation in Docker Desktop settings.</p>
|
|
<h3 id="android-sdk-download-timeout"><a class="header" href="#android-sdk-download-timeout">Android SDK Download Timeout</a></h3>
|
|
<p>If downloads timeout, increase timeout or download manually:</p>
|
|
<pre><code class="language-bash"># In container, with longer timeout
|
|
timeout 600 sdkmanager --sdk_root=$ANDROID_HOME ...
|
|
</code></pre>
|
|
<h3 id="rust-compilation-errors"><a class="header" href="#rust-compilation-errors">Rust Compilation Errors</a></h3>
|
|
<p>Make sure Rust is updated:</p>
|
|
<pre><code class="language-bash">rustup update
|
|
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
|
|
</code></pre>
|
|
<h3 id="cache-issues"><a class="header" href="#cache-issues">Cache Issues</a></h3>
|
|
<p>Clear Docker cache and rebuild:</p>
|
|
<pre><code class="language-bash">docker-compose down -v # Remove volumes
|
|
docker system prune # Clean up dangling images
|
|
docker-compose up --build
|
|
</code></pre>
|
|
<h2 id="performance-tips"><a class="header" href="#performance-tips">Performance Tips</a></h2>
|
|
<ol>
|
|
<li><strong>Cache Reuse</strong>: Both Docker and Gitea Act cache dependencies across runs</li>
|
|
<li><strong>Parallel Steps</strong>: The workflow runs frontend and Rust tests in series; consider parallelizing for faster CI</li>
|
|
<li><strong>Incremental Builds</strong>: Rust and Node caches persist between runs</li>
|
|
<li><strong>Docker Buildkit</strong>: Enable for faster builds:
|
|
<pre><code class="language-bash">DOCKER_BUILDKIT=1 docker build .
|
|
</code></pre>
|
|
</li>
|
|
</ol>
|
|
<h2 id="security-considerations"><a class="header" href="#security-considerations">Security Considerations</a></h2>
|
|
<ul>
|
|
<li>Dockerfile uses <code>ubuntu:24.04</code> base image from official Docker Hub</li>
|
|
<li>NDK is downloaded from official Google servers (verified via HTTPS)</li>
|
|
<li>No credentials are stored in the Dockerfile</li>
|
|
<li>Use Gitea Secrets for sensitive values (API keys, tokens, etc.)</li>
|
|
<li>Lock dependency versions in <code>Cargo.toml</code> and <code>package.json</code></li>
|
|
</ul>
|
|
<h2 id="next-steps"><a class="header" href="#next-steps">Next Steps</a></h2>
|
|
<ol>
|
|
<li>Test locally with <code>docker-compose up</code></li>
|
|
<li>Push to your Gitea repository</li>
|
|
<li>Monitor workflow runs in the Actions tab</li>
|
|
<li>Configure secrets in repository settings for production builds</li>
|
|
<li>Set up artifact retention policies (currently 30 days)</li>
|
|
</ol>
|
|
<h2 id="references"><a class="header" href="#references">References</a></h2>
|
|
<ul>
|
|
<li><a href="https://docs.gitea.io/en-us/actions/">Gitea Actions Documentation</a></li>
|
|
<li><a href="https://docs.docker.com/build/building/multi-stage/">Docker Multi-stage Builds</a></li>
|
|
<li><a href="https://developer.android.com/studio/command-line">Android Build Tools</a></li>
|
|
<li><a href="https://tauri.app/v1/guides/building/android">Tauri Android Guide</a></li>
|
|
</ul>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
<a rel="prev" href="../defect-windows.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../build/build-builder-image.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
<a rel="prev" href="../defect-windows.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../build/build-builder-image.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
window.playground_copyable = true;
|
|
</script>
|
|
|
|
|
|
<script src="../elasticlunr.min.js"></script>
|
|
<script src="../mark.min.js"></script>
|
|
<script src="../searcher.js"></script>
|
|
|
|
<script src="../clipboard.min.js"></script>
|
|
<script src="../highlight.js"></script>
|
|
<script src="../book.js"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|