CI and releases

GitHub Actions checks pull requests and builds releases from a GitHub Release tag. PyPI publishing uses GitHub’s OIDC identity. Docker Hub publishing uses a scoped access token. Pull requests receive neither publishing credential.

Configure the repository

GitHub Pages

In Settings → Pages, choose GitHub Actions as the source. Configure the github-pages environment to allow release tags matching v*.

The project site is https://adarshdigievo.github.io/shinbot/. The landing page is at that root; Great Docs is at https://adarshdigievo.github.io/shinbot/docs/. This is a project site, so /shinbot/ is part of both URLs.

PyPI trusted publishing

Create a pending publisher for a new PyPI project, or add a trusted publisher to the existing project. Use these exact values:

Setting Value
PyPI project shinbot
GitHub owner adarshdigievo
Repository shinbot
Workflow filename release.yml
Environment pypi

Create the matching pypi environment in GitHub. Restrict deployment to release tags; add required reviewers if desired. No PyPI API token belongs in GitHub secrets. See PyPI’s publisher setup.

Docker Hub

Create the public repository adarshd96/shinbot. Create a Docker Hub personal access token with Read & Write access, without Delete access. Add these values to the GitHub dockerhub environment:

Type Name Value
Actions variable DOCKERHUB_USERNAME adarshd96
Actions secret DOCKERHUB_TOKEN The Docker Hub access token

Restrict the dockerhub environment to v* tags. Store the token only in that environment, not as a repository-wide secret. Rotate it through the environment’s secrets; do not place it in workflow files or release notes.

The Docker owner is adarshd96; the GitHub owner is adarshdigievo.

What runs

Workflow Trigger Result
ci.yml Pull request, push to main, manual run, release caller Python checks on Linux and macOS; runtime tests; browser journeys; wheel checks; isolated container integration
site-build.yml Called by Website checks or Release Great Docs build, landing-page assembly and rendered-link checks
pages.yml Pull request, push to main, manual run Validates the site without deploying it
release.yml Published GitHub Release or manual retry on a release tag Checks the tag and versions; runs CI and site checks; publishes images, then PyPI, then the website and documentation

Actions use reviewed commit pins; the actionlint container uses a verified image digest. Python and runtime lockfiles are checked in. Documentation dependencies are isolated in the docs dependency group.

Prepare a version

Work from a clean checkout. Update the synchronized version fields with:

uv run python scripts/release.py set-version 0.1.0a2
uv lock
uv run python scripts/release.py check

The helper updates the Python package, TypeScript package and lock root, both Compose files and the integration fixture’s image tag. uv lock refreshes the Python lock metadata. It accepts stable versions such as 0.1.0 and prereleases such as 0.1.0a2, 0.1.0b1 and 0.1.0rc1.

Review dependency/license changes, run CI and the site build, then commit the version change. Create a tag such as v0.1.0a2 at that commit and publish a GitHub Release for it. Set GitHub’s prerelease flag for a, b and rc versions. The release check rejects a mismatched flag or tag.

Published artifacts

Every release produces a Python wheel and source archive, four core Docker images, and images for desktop mode and the optional Telegram plugin:

adarshd96/shinbot:VERSION-control
adarshd96/shinbot:VERSION-runtime
adarshd96/shinbot:VERSION-computer
adarshd96/shinbot:VERSION-browser
adarshd96/shinbot:VERSION-desktop
adarshd96/shinbot:VERSION-telegram

Images are built for linux/amd64 and linux/arm64, with build provenance and SBOM attestations. Container journeys run on the Linux CI host; cross-platform image builds do not replace native runtime testing on every architecture.

BuildKit stores reusable layers in buildcache-<service> tags in the same Docker Hub repository. These tags are build caches, not runnable releases. They can be removed to reclaim storage; the next release will rebuild the layers.

After PyPI publishing, a serialized promotion job checks the current latest release before updating latest-control, latest-runtime, latest-computer, latest-browser, latest-desktop and latest-telegram. Prereleases keep versioned tags. The launcher uses the exact image set bundled with its package, never the mutable latest-* aliases.

PyPI publishing waits for all image builds and pushes, so a newly installable package has its matching containers. Package attestations are produced by the PyPI publishing action.

Handle a failed release

Inspect the failed job before retrying. A failed matrix can leave some versioned Docker tags published; rerun failed jobs to finish the set. PyPI versions cannot be overwritten. If a version is already published and needs different code, make a new release rather than moving its tag.

For a publishing-only retry after CI has passed, select the existing release tag and explicitly skip the repeated CI jobs:

gh workflow run release.yml --ref v0.1.0a2 -f skip_checks=true

This still validates the release identity and dependency advisories, builds and checks the site and distributions, and publishes the service images. Normal releases and manual runs without skip_checks run the full CI suite.

The release workflow deploys the landing page and documentation built from the release tag after PyPI publishing succeeds. Pushes to main, pull requests and manual website checks do not publish anything. Each successful release deploys its tagged website, including prereleases. A website deployment can fail without unpublishing the package; rerun the failed deployment job. Use its deployment URL and test both the root and /docs/.

For local troubleshooting, build _site/ and run the same scripts used by CI. GitHub account settings, environment protections and registry permissions are only verified by an actual GitHub Actions run.