Sebastiano Druda

← Back to writing

Guide / Tools, Infrastructure & Workflows

Deployment Should Be Boring Enough to Trust

Build predictable releases with validation, restricted credentials and manifest ownership. Examine the boundaries of this static site’s deployment pipeline.

A deployment is a poor place to discover that a local file was required but never committed, that a credential has broader access than expected or that removing an old page means deleting the entire remote directory. These are predictable failure modes that should be addressed before the release starts.

The pipeline for this site takes source from a private repository, validates it, builds static output and transfers only owned production files to HostingPerTe. Its value lies less in automating a command than in making the boundary between a reviewed change and a public artifact explicit.

The best deployment is the one that contains no surprises.

Build from a known source state

A release should identify the source revision it represents. Local work can include uncommitted files, cached output and environment-specific configuration. A clean CI checkout provides a more controlled starting point, provided the build declares its dependencies and required inputs.

This project uses the lockfile with npm ci, runs its validation commands and generates static output. The build environment is part of the release contract even though Node does not run on the production host to serve articles.

Deterministic behavior matters more than claiming that every byte is timeless. Publication eligibility intentionally depends on build time, and generated artifacts can reflect their inputs. The useful guarantee is that declared source, dependencies and relevant configuration explain the output, rather than hidden local files.

A scheduled article illustrates the boundary. Its source can exist in the repository while remaining excluded until a later build. The serving host does not independently evaluate the publication date for every request. A successful source commit alone does not make a future article public.

Run checks that protect the release

Formatting, linting and type checks catch different classes of defects. Unit tests protect publication rules and deployment helpers. Browser tests exercise navigation, accessibility, responsive layout and interactive behavior. Build-output assertions inspect what will actually be transferred.

These checks should be required by the release path, not merely documented as commands someone ought to remember. A manual deployment that bypasses them creates a second, weaker definition of ready.

The output guard is especially important for a static site. It can reject demo pages, source maps, private files and runtime endpoints that do not belong in production. Sitemap and RSS validation can confirm that discovery files agree with the public article corpus.

Keep checks connected to a real contract. A large test count is not a substitute for relevant coverage. When a defect escapes, add a focused regression if it represents a durable behavior, and explain which boundary the earlier checks did not cover.

Give the workflow narrow authority

A build needs to read source and dependencies. A deployment needs permission to write the verified hosting destination. Those capabilities should not automatically imply broad write access to the repository or unrelated server files.

GitHub’s secure-use guidance discusses restricted workflow permissions, secret handling and pinning actions to full commit identifiers. These controls reduce exposure in the automation environment; they do not replace reviewing the commands the workflow actually runs.

For this site, hosting credentials are supplied through GitHub Secrets. The password does not belong in source, generated output, command examples or final reports. Configuration names can be documented without disclosing their values when those values are sensitive.

Review logs as an output surface. Shell tracing, error messages and temporary configuration dumps can expose information even when the workflow file itself contains only secret references. The deployment tool should report useful stages and counts without printing authentication material.

Preflight the destination without changing it

Before a new hosting configuration is trusted, establish the protocol, technical endpoint, account scope and remote root. Generic hosting instructions may describe a path that differs from the jailed view seen by a particular account.

A read-only preflight can check connectivity and the intended document root. It should not silently repair an uncertain configuration by creating directories or deleting content. If the account view is unclear, resolve that uncertainty before writing production files.

The public hostname and the transfer hostname have separate roles. This project’s public canonical origin remains the www domain, while deployment uses the verified technical HostingPerTe endpoint. That separation avoids making transfer connectivity depend on a public DNS change during migration.

Preflight success is still only one milestone. It establishes access to a destination, not that the generated site is correct or that public requests will serve the uploaded revision.

Own a manifest, not the whole server

The deployment manifest records files managed by this site. Cleanup can compare the new inventory with the previous owned inventory and remove stale files within that boundary. Provider-owned directories remain outside it.

This is safer than treating the remote root as disposable. Shared hosting can contain certificate validation files or provider-managed resources that are unrelated to the application build. A broad mirror-delete operation can remove them even when the new site itself is valid.

Cleanup authority should be smaller than connection authority.

The manifest also makes source deletions concrete. Removing an obsolete route from the repository is insufficient if its previous HTML remains on the server. Conversely, deleting every remote file to guarantee freshness creates unnecessary disruption. Ownership-aware cleanup resolves the intended removal without expanding its scope.

Validate manifest paths before using them. A stored path is data, not permission to traverse arbitrary directories. The deployment implementation should enforce the allowed roots and reject unsafe or unrecognized entries.

Order uploads around dependencies

A page can fail during deployment if its HTML references an asset that has not arrived yet. Uploading required assets before dependent pages reduces that risk. Discovery files and server configuration also deserve deliberate placement in the sequence.

A file-transfer deployment is not a fully atomic release of the entire website. During the transition, some requests may observe old pages and others new ones. Preserve compatibility where possible, and avoid describing safe ordering as a guarantee that every request sees one identical revision.

Stale owned assets should be removed only after the new output is uploaded successfully. Updating the manifest last preserves a clear record of the completed release rather than claiming ownership state before the transfer finishes.

If a transfer fails, inspect the confirmed stage and retry safely. Do not respond by emptying the web root. The recovery procedure should work with the existing files and manifest rather than making a partial release worse through an unrelated destructive action.

Serialize production releases when concurrent uploads could interleave files and manifests. Cancelling a transfer halfway through can leave an uncertain state that the next job must reconcile. A workflow concurrency boundary with deliberate cancellation behavior makes that risk visible. It does not replace idempotent transfer logic, but it prevents two otherwise valid releases from competing for the same destination at the same time. Check that scheduled and manually triggered deployments use the same boundary as ordinary pushes.

Verify the public result

A successful CI job proves that the workflow completed its configured steps. Live checks should then confirm the visitor-facing result: key pages, representative old and new articles, search, sitemap, verification file and Research PDFs.

Check actual GET responses as well as redirects and headers where relevant. A provider proxy can serve different asset classes through different paths. The DNS and hosting guide explains why a correct configuration file does not establish every property of the public response.

Compare a known artifact or revision-sensitive page with the expected release. A generic homepage status of 200 can be returned by an old deployment or the wrong document root. Verification should distinguish those cases.

The release report should identify the commit, CI result, deployment result and remaining limitations separately. That makes the outcome reviewable and gives the next maintainer a reliable starting point. A deployment becomes boring when its assumptions are explicit, its authority is bounded and its evidence comes from the system that users actually reach.

Sources

  1. Secure use of GitHub Actions — checked 2026-10-14

Topics

34 / Guide

GitHub Actions Became My Publishing System

Versioned articles, validation, static builds and search indexing form a publishing pipeline. Here is how this site connects editorial changes to delivery.

ci cd · github · 7 min