273 lines
15 KiB
TeX
273 lines
15 KiB
TeX
\chapter{Automated Manual Build}
|
|
\ChapterLabel{AutomatedManualBuild}
|
|
\index{Gitea Actions}\index{runner}\index{build artifact}\index{LaTeX}\index{continuous integration}
|
|
|
|
\begin{devopsNote}[Automated build verification]
|
|
The team demonstrated push-triggered PDF compilation, downloadable build
|
|
artifacts, and a controlled failure followed by recovery using a self-managed
|
|
Gitea Actions runner. The following sections record the observed run results
|
|
and traceable source revisions. Jenkins merge checks are covered separately
|
|
in Chapter 4.
|
|
\end{devopsNote}
|
|
|
|
\section{Source and trigger}
|
|
The team maintains the complete buildable LaTeX source, bibliography, figures,
|
|
and nonsecret build instructions in the Gitea repository:
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app}.
|
|
The main document is \texttt{latex-manual/devopsAssignment.tex}; this chapter is
|
|
\texttt{latex-manual/devopsAutomatedManualBuild.tex}. The version-controlled
|
|
workflow is \texttt{.gitea/workflows/manual.yml}, and the build program is
|
|
\texttt{ci/build\_manual.py}.
|
|
|
|
The workflow uses the Git push event on \texttt{main},
|
|
\texttt{chapter3-build-automation}, and \texttt{chapter3-build-test}. The
|
|
actual demonstration pushes were made to \texttt{chapter3-build-test}.
|
|
Gitea Actions run 2 was triggered by a push from \texttt{vincentpenalosa}
|
|
and succeeded for commit
|
|
\texttt{9fec46a41ef1dcdffb40d0429e19475ba21af41c}:
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/2}.
|
|
Run 3 succeeded for the subsequent source commit
|
|
\texttt{e16a6deab277621f860c8a057a80c9737b5eb4b1}:
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/3}.
|
|
These runs demonstrate the configured source-push-to-workflow connection.
|
|
|
|
Git clients push over HTTPS to the public Gitea hostname on TCP port 443.
|
|
Caddy terminates TLS and forwards the request to Gitea on private container
|
|
port 3000. The runner VM reaches the public HTTPS Gitea hostname and does not
|
|
need a public inbound build, compiler, or management port. The runner checks
|
|
out source over the network and uploads the artifact through Gitea Actions;
|
|
no shared filesystem between the VM and Gitea is needed.
|
|
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=0.92\linewidth]{png/successful_run_1.png}
|
|
\caption{October 2026: push-triggered Gitea Actions run 2 on
|
|
\texttt{chapter3-build-test}, showing a successful job and one artifact.}
|
|
\label{fig:ch3-push-run2}
|
|
\end{figure}
|
|
|
|
\section{Runner setup}
|
|
The self-managed runner executes on Vincent's separate Ubuntu 22.04.5 LTS
|
|
VirtualBox VM (\texttt{x86\_64}), rather than on the shared DigitalOcean
|
|
Droplet hosting Gitea and Jenkins. The handoff records approximately 4 GB of
|
|
allocated memory and a 25 GB virtual disk; these are historical observations,
|
|
not current free-resource measurements. The installed Gitea runner version is
|
|
reported as 2.3.0. Its configured name is \texttt{vincent-ubuntu-manual},
|
|
with a repository-scoped registration for the SmartPark repository, label
|
|
\texttt{smartpark-latex:host}, and capacity one. The workflow selects the
|
|
label through \texttt{runs-on: smartpark-latex}.
|
|
|
|
The runner executes jobs in host mode, using TeX and Python utilities installed
|
|
on Ubuntu rather than launching Docker job containers. A dedicated unprivileged
|
|
\texttt{smartpark-runner} Linux account runs the service. The handoff identifies
|
|
\texttt{smartpark-runner.service}, configuration at
|
|
\texttt{/etc/smartpark-runner/config.yaml}, and a private runner identity at
|
|
\texttt{/var/lib/smartpark-runner/.runner}. A supplied service screenshot shows
|
|
the service active; successful jobs 2 and 3 additionally establish that the
|
|
runner executed workflow work. The VM must remain running and network-connected
|
|
to accept new jobs. No reboot-survival or current resource-availability test is
|
|
claimed without separate evidence.
|
|
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=0.92\linewidth]{png/runner_activated.png}
|
|
\caption{October 2026: Ubuntu service evidence for the separate
|
|
Gitea Actions runner VM. Service activity is not, by itself, proof of current
|
|
Gitea online status.}
|
|
\label{fig:ch3-runner-service}
|
|
\end{figure}
|
|
|
|
\section{Reproducible compilation}
|
|
On a clean Git checkout, the documented entry point is
|
|
\texttt{python3 ci/build\_manual.py}. This script copies the manual source to
|
|
a fresh temporary work directory and compiles the main file with
|
|
\texttt{latexmk -pdf}, stopping on LaTeX errors. It supports the document's
|
|
\texttt{minted} highlighting with Pygments and shell escape, and coordinates
|
|
bibliography, glossary, index, and repeated LaTeX passes. Source and workflow
|
|
edit rights must be restricted because enabling shell escape executes helper
|
|
programs. The expected deliverables are
|
|
\texttt{build/manual/SmartPark-Manual.pdf} and
|
|
\texttt{build/manual/build-info.txt}.
|
|
|
|
The supplied successful artifact metadata records \texttt{latexmk} 4.76,
|
|
\texttt{pdfTeX} 1.40.22 (TeX Live 2022/dev/Debian), and Pygments 2.11.2.
|
|
The handoff also reports \texttt{makeglossaries} 4.49 and packages including
|
|
\texttt{texlive-latex-extra}, \texttt{texlive-fonts-recommended},
|
|
\texttt{lmodern}, and \texttt{python3-pygments}. The build script removes old
|
|
deliverables, checks command exit status and the expected PDF, and treats
|
|
unresolved reference/citation summaries as errors. Therefore an old PDF
|
|
cannot silently stand in for a newly successful build. The compiler runs on
|
|
the runner VM, not in the Gitea application container.
|
|
|
|
Run 2's successful \texttt{manual} job took 41 seconds; run 3 also completed
|
|
successfully. Their run pages and downloadable \texttt{build-info.txt} files
|
|
provide the logged build context:
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/2}
|
|
and
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/3}.
|
|
Run 4 is the controlled negative compilation test, with a failed workflow
|
|
status. The run 4 screenshot records the negative test status; the job console
|
|
is the authoritative source for the compiler diagnostic.
|
|
|
|
\section{PDF version traceability}
|
|
The team maintains the human-readable manual version separately from the
|
|
machine-generated build identifier. The documented manual version for these
|
|
runs is \texttt{1.9-draft}. For Gitea Actions builds, the identification page
|
|
adds the triggering commit's short revision and the workflow run number.
|
|
The metadata is generated during the temporary build and is not pushed back
|
|
to the branch, avoiding a self-triggering push/build loop. Local builds use
|
|
\texttt{local}; local modified trees can display \texttt{dirty}, so a local
|
|
build is not substituted for Actions evidence.
|
|
|
|
The downloaded PDF for run 2 visibly identifies
|
|
\texttt{1.9-draft+build.2.9fec46a41ef1}, source revision
|
|
\texttt{9fec46a41ef1}, and workflow run \texttt{2}. The downloaded PDF for
|
|
run 3 displays \texttt{1.9-draft+build.3.e16a6deab277}, source revision
|
|
\texttt{e16a6deab277}, and workflow run \texttt{3}. The matching full
|
|
commits are recorded in Section 6. The respective build metadata timestamps
|
|
are October 10, 2026 at 02:12 UTC and 02:26 UTC. The identifiers printed in the respective downloaded PDFs match the
|
|
workflow run numbers and source revisions.
|
|
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=0.90\linewidth]{png/successful_run_2.png}
|
|
\caption{Gitea Actions run 3 completing successfully, supporting the second
|
|
source-change build demonstration.}
|
|
\label{fig:ch3-run3-success}
|
|
\end{figure}
|
|
|
|
\section{Downloadable artifact}
|
|
The workflow names artifacts using the workflow run and triggering source
|
|
commit. Run 2 uploaded a named downloadable artifact:
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/2}.
|
|
Its downloaded ZIP contains \texttt{SmartPark-Manual.pdf} and
|
|
\texttt{build-info.txt}. The 82-page PDF was extracted and opened
|
|
successfully. Its build identifier is
|
|
\texttt{1.9-draft+build.2.9fec46a41ef1}, matching run 2 and commit
|
|
\texttt{9fec46a41ef1dcdffb40d0429e19475ba21af41c}. Run 3 also
|
|
produced a distinct successful PDF and matching metadata, rather than
|
|
reusing the previous output.
|
|
|
|
A team member obtains an artifact by opening the matching Gitea Actions run,
|
|
choosing the named entry under Artifacts, downloading and extracting the ZIP,
|
|
and visually inspecting the PDF and its identification page. The workflow
|
|
requests a 30-day artifact retention period. The server's actually applied
|
|
retention policy was not independently verified. Artifacts are downloadable
|
|
build deliverables, not permanent backups.
|
|
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=0.92\linewidth]{png/successful_run_1.png}
|
|
\caption{October 2026: successful run 2 showing the named downloadable
|
|
manual artifact in the Gitea Actions interface.}
|
|
\label{fig:ch3-artifact-run2}
|
|
\end{figure}
|
|
|
|
\section{Change, failure, and repair evidence}
|
|
The team performed the following source-change and repair sequence on
|
|
\texttt{chapter3-build-test}. Expected results were compared with the
|
|
actual Gitea Actions status, with links to each run.
|
|
|
|
\begin{enumerate}
|
|
\item \textbf{First successful source change:} run 2, ``Document first manual
|
|
build demonstration,'' compiled commit
|
|
\texttt{9fec46a41ef1dcdffb40d0429e19475ba21af41c}, generated the PDF
|
|
identifier \texttt{1.9-draft+build.2.9fec46a41ef1}, and uploaded one named
|
|
artifact. Expected: build and artifact succeed; actual: success.
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/2}.
|
|
|
|
\item \textbf{Second successful source change:} run 3, ``Document second
|
|
manual build demonstration,'' compiled the next source change at commit
|
|
\texttt{e16a6deab277621f860c8a057a80c9737b5eb4b1}. The downloaded PDF
|
|
identifies \texttt{1.9-draft+build.3.e16a6deab277}. Expected: a different
|
|
build/PDF tied to this source revision; actual: successful run and matching
|
|
PDF metadata.
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/3}.
|
|
|
|
\item \textbf{Controlled compiler failure:} run 4, ``Demonstrate controlled
|
|
LaTeX compilation failure,'' used the deliberate undefined command
|
|
\verb|\SmartParkIntentionalBuildFailure|. Expected: nonzero LaTeX build status
|
|
and no successfully published PDF. The supplied screenshot confirms failed
|
|
workflow status and shows no artifact in that view. The run URL links to the associated commit and compiler job log.
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/4}.
|
|
|
|
\item \textbf{Repair:} run 5, ``Revert Demonstrate controlled LaTeX compilation
|
|
failure,'' restored a working document. Expected: successful compile and
|
|
artifact upload; actual: screenshot shows a successful job and one artifact.
|
|
The run page identifies the repair revision and downloadable artifact.
|
|
\url{https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app/actions/runs/5}.
|
|
\end{enumerate}
|
|
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=0.88\linewidth]{png/latex_compilation_failure.png}
|
|
\caption{October 2026: controlled LaTeX compilation failure recorded
|
|
by Gitea Actions run 4. The matching job log records the compiler failure.}
|
|
\label{fig:ch3-run4-failure}
|
|
\end{figure}
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=0.88\linewidth]{png/repaired_build.png}
|
|
\caption{October 2026: Gitea Actions run 5 succeeding after the
|
|
controlled error was reverted, with one downloadable artifact.}
|
|
\label{fig:ch3-run5-repair}
|
|
\end{figure}
|
|
|
|
\section{Runner and secret boundary}
|
|
The Chapter 3 runner uses Vincent's separate Ubuntu VirtualBox VM, not the
|
|
shared DigitalOcean Droplet. Its configured repository-scoped registration,
|
|
\texttt{smartpark-latex:host} execution label, capacity one, and unprivileged
|
|
\texttt{smartpark-runner} service account limit the jobs' intended access.
|
|
Host-mode jobs execute directly as that account and are \emph{not} isolated
|
|
from each other by disposable Docker containers. Consequently, workflow and
|
|
source changes targeting the runner should be restricted to reviewed team
|
|
contributors. A push-only trigger and label do not themselves establish an
|
|
access-control boundary.
|
|
|
|
The service configuration resides at
|
|
\texttt{/etc/smartpark-runner/config.yaml}; the private registration identity
|
|
resides at \texttt{/var/lib/smartpark-runner/.runner}. Runner registration
|
|
tokens, personal SSH keys, passwords and repository secrets must not appear
|
|
in Git, job logs, screenshots, or generated PDFs. The operational Passwords
|
|
table should contain only ownership and storage hints. No privileged Docker
|
|
socket access was granted to the Chapter 3 job environment on the shared
|
|
Droplet; doing so would expose the other Docker-hosted Gitea/Jenkins services
|
|
to substantial risk. Only outbound HTTPS access to Gitea is required.
|
|
|
|
The actual editor/branch permissions should be verified against repository
|
|
settings; this report does not claim that every policy was technically
|
|
enforced just because it is recommended. The service evidence is shown in
|
|
Figure~\ref{fig:ch3-runner-service}; nonsecret configuration lives under
|
|
\texttt{ci/} in the Gitea repository.
|
|
|
|
\section{Manual quality and controls}
|
|
The version-controlled source, reproducible workflow, host-mode runner,
|
|
compiler checks, visible build identifiers, successful PDF artifacts, and
|
|
controlled failure/repair are documented above. The manual version used for
|
|
the demonstrated builds is \texttt{1.9-draft}. The final released manual version is maintained by the team separately
|
|
from the build identifiers recorded for historical runs.
|
|
|
|
For operational records, the Hosts table identifies the Ubuntu runner VM,
|
|
its owner, role, outbound HTTPS access, and availability conditions. The
|
|
Passwords table tracks only the runner credential custodian and storage hint,
|
|
not the token or private runner identity. The team tracks Chapter 3 changes
|
|
in the manual history and retains source, build, and artifact links for
|
|
auditability. Index terms include runner, Gitea Actions, build artifact,
|
|
and reproducible compilation.
|
|
|
|
\textbf{Troubleshooting:} For queued jobs, check VM power/network access,
|
|
runner service status, repository scope, label matching, and capacity. For
|
|
checkout failures, check HTTPS/DNS and repository authorization. For compiler
|
|
failures, read the first actual TeX error, check paths and dependencies, and
|
|
rerun after a committed repair. For missing artifacts, check that
|
|
\texttt{build/manual/SmartPark-Manual.pdf} exists and inspect the upload step.
|
|
A green compiler step alone does not establish successful artifact upload.
|
|
For failure/repair evidence, keep the exact commit, run link, timestamp, and
|
|
outcome synchronized across the manual and screenshots.
|
|
|
|
\textbf{Final submission check:} Commit the integrated LaTeX and PNG files,
|
|
verify a new successful Gitea Actions build, download its PDF artifact, open
|
|
and inspect every figure and build identifier, and submit that downloaded PDF.
|
|
The submitted deliverable is the PDF downloaded from the final successful
|
|
Gitea Actions run.
|