mirror of
https://github.com/rr-/pq-cli.git
synced 2026-09-28 22:33:59 -06:00
build: add Docker builds
Co-authored-by: Jakub Stastka <jakub@stastka.org>
This commit is contained in:
co-authored by
Jakub Stastka
parent
7426924170
commit
696fad78b3
+12
@@ -0,0 +1,12 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN pip install --no-cache-dir .
|
||||
|
||||
CMD ["pqcli", "--basic"]
|
||||
@@ -41,6 +41,43 @@ $ cd pq-cli
|
||||
$ pip install --user .
|
||||
```
|
||||
|
||||
## Docker / Docker Compose
|
||||
|
||||
The repository includes a `Dockerfile` and `docker-compose.yml` that run the
|
||||
game with `--basic` and keep save data in a persistent named volume.
|
||||
|
||||
There is no registry pipeline required for this setup: build locally, then run
|
||||
with Compose.
|
||||
|
||||
```console
|
||||
# Build image locally from the Dockerfile
|
||||
docker compose build
|
||||
|
||||
# First run (interactive): create your character in the shared save volume
|
||||
docker compose run --rm pqcli-init
|
||||
|
||||
# Later runs on a server (detached, default save slot 1):
|
||||
docker compose up -d pqcli
|
||||
|
||||
# List existing saves in the same volume:
|
||||
docker compose run --rm pqcli-init pqcli --basic --list-saves
|
||||
|
||||
# Change detached slot if needed (example: slot 2):
|
||||
PQCLI_SAVE_SLOT=2 docker compose up -d pqcli
|
||||
|
||||
# Follow logs / stop detached container:
|
||||
docker compose logs -f pqcli
|
||||
docker compose stop pqcli
|
||||
```
|
||||
|
||||
On first run, if no save data exists in the mounted volume, `pqcli` will
|
||||
automatically launch an interactive character-creation bootstrap in CLI mode
|
||||
before starting the normal interface.
|
||||
|
||||
For server usage, run first-time setup without a forced slot (`pqcli-init`),
|
||||
then run the long-lived detached service (`pqcli`) that loads slot `1` by
|
||||
default.
|
||||
|
||||
## Contributing
|
||||
|
||||
```sh
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
pqcli-init:
|
||||
build: .
|
||||
image: ghcr.io/${GITHUB_REPOSITORY_OWNER:-local}/pq-cli:latest
|
||||
stdin_open: true
|
||||
tty: true
|
||||
command: ["pqcli", "--basic"]
|
||||
environment:
|
||||
XDG_CONFIG_HOME: /data
|
||||
volumes:
|
||||
- pqcli-data:/data
|
||||
|
||||
pqcli:
|
||||
build: .
|
||||
stdin_open: true
|
||||
tty: true
|
||||
stop_signal: SIGINT
|
||||
stop_grace_period: 30s
|
||||
command: ["sh", "-c", "pqcli --basic --load-save ${PQCLI_SAVE_SLOT:-1}"]
|
||||
environment:
|
||||
XDG_CONFIG_HOME: /data
|
||||
volumes:
|
||||
- pqcli-data:/data
|
||||
|
||||
volumes:
|
||||
pqcli-data:
|
||||
@@ -66,6 +66,21 @@ def list_players(roster: Roster, file: T.Optional[T.Any] = None) -> None:
|
||||
print(f"{i}. {player.name}", file=file)
|
||||
|
||||
|
||||
def bootstrap_first_run(roster: Roster, args: argparse.Namespace) -> None:
|
||||
if roster.players or args.list_saves or args.load_save:
|
||||
return
|
||||
|
||||
print("No saved characters found. Starting first-run character creation.")
|
||||
ui = BasicUserInterface(roster, None, args)
|
||||
while not roster.players:
|
||||
player = ui.create_player(auto_play=False)
|
||||
if player:
|
||||
return
|
||||
if not ui.confirm("No character created. Do you want to try again?"):
|
||||
print("A character is required for first run.", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
args = parse_args()
|
||||
roster = Roster.load(SAVE_PATH)
|
||||
@@ -83,6 +98,8 @@ def main() -> None:
|
||||
list_players(roster, file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
bootstrap_first_run(roster, args)
|
||||
|
||||
try:
|
||||
ui = args.ui(roster, player, args)
|
||||
ui.run()
|
||||
|
||||
@@ -101,7 +101,7 @@ class BasicUserInterface(BaseUserInterface):
|
||||
self.quit()
|
||||
break
|
||||
|
||||
def create_player(self) -> T.Optional[Player]:
|
||||
def create_player(self, *, auto_play: bool = True) -> T.Optional[Player]:
|
||||
name = input("Name your new character: ")
|
||||
if not name:
|
||||
print("Cancelled.")
|
||||
@@ -123,7 +123,9 @@ class BasicUserInterface(BaseUserInterface):
|
||||
name=name, race=race, class_=class_, stats=stats
|
||||
)
|
||||
self.roster.players.append(player)
|
||||
if self.confirm("Do you want to play as your new character?"):
|
||||
if auto_play and self.confirm(
|
||||
"Do you want to play as your new character?"
|
||||
):
|
||||
self.play(player)
|
||||
return player
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ dependencies = [
|
||||
"xdg-base-dirs>=6.0.0,<7.0.0",
|
||||
"urwid>=2.1.2,<3.0.0",
|
||||
"urwid-readline>=0.13,<1.0.0",
|
||||
"pre-commit>=4.5.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
||||
@@ -61,6 +61,7 @@ name = "pqcli"
|
||||
version = "1.0.4"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "pre-commit" },
|
||||
{ name = "urwid" },
|
||||
{ name = "urwid-readline" },
|
||||
{ name = "xdg-base-dirs" },
|
||||
@@ -78,6 +79,7 @@ dev = [
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "pre-commit", specifier = ">=4.5.0" },
|
||||
{ name = "urwid", specifier = ">=2.1.2,<3.0.0" },
|
||||
{ name = "urwid-readline", specifier = ">=0.13,<1.0.0" },
|
||||
{ name = "windows-curses", marker = "extra == 'windows'", specifier = ">=2.3.0,<3.0.0" },
|
||||
|
||||
Reference in New Issue
Block a user