mirror of
https://github.com/aculix/ticket-monitoring.git
synced 2026-10-27 07:15:51 +00:00
ci: publish multi-arch image to GHCR; move status port to 4733
GitHub Actions builds linux/amd64 and linux/arm64 on every push to main and pushes a single :latest tag to ghcr.io, so the container can be run without cloning or building. Tests gate the publish step.
This commit is contained in:
1 parent
b70968d259
commit
77bda09049
6 files changed
+103
-11
No files matched your search
+1
-1
@@ -45,7 +45,7 @@ CURRENCY=₹
|
|||||||
|
|
||||||
# ── Runtime ───────────────────────────────────────────────────────────────────
|
# ── Runtime ───────────────────────────────────────────────────────────────────
|
||||||
STATE_PATH=./state.json # Docker image defaults this to /data/state.json
|
STATE_PATH=./state.json # Docker image defaults this to /data/state.json
|
||||||
PORT=8080 # status endpoint (--loop mode only)
|
PORT=4733 # status endpoint (--loop mode only)
|
||||||
|
|
||||||
# Routes only the site checks through a SOCKS5 proxy; notifications stay direct.
|
# Routes only the site checks through a SOCKS5 proxy; notifications stay direct.
|
||||||
# Needed on datacenter hosts, whose IPs the site's WAF is likely to block.
|
# Needed on datacenter hosts, whose IPs the site's WAF is likely to block.
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
name: docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: docker-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm test
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# QEMU lets this amd64 runner build the arm64 half of the manifest.
|
||||||
|
- uses: docker/setup-qemu-action@v3
|
||||||
|
- uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ghcr.io/${{ github.repository }}:latest
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
+1
-1
@@ -8,7 +8,7 @@ COPY src/ src/
|
|||||||
|
|
||||||
ENV STATE_PATH=/data/state.json
|
ENV STATE_PATH=/data/state.json
|
||||||
VOLUME /data
|
VOLUME /data
|
||||||
EXPOSE 8080
|
EXPOSE 4733
|
||||||
|
|
||||||
# --env-file-if-exists so the container works with plain env vars when no .env is mounted.
|
# --env-file-if-exists so the container works with plain env vars when no .env is mounted.
|
||||||
CMD ["node", "--env-file-if-exists=.env", "src/index.js", "--loop"]
|
CMD ["node", "--env-file-if-exists=.env", "src/index.js", "--loop"]
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
# ticket-monitoring
|
# ticket-monitoring
|
||||||
|
|
||||||
|
[](https://github.com/aculix/ticket-monitoring/actions/workflows/docker.yml)
|
||||||
|
|
||||||
Watches [district.in](https://www.district.in) showtimes and sends a max-priority push to your
|
Watches [district.in](https://www.district.in) showtimes and sends a max-priority push to your
|
||||||
phone the second tickets go on sale for the movie, date, format and cinema you care about.
|
phone the second tickets go on sale for the movie, date, format and cinema you care about.
|
||||||
|
|
||||||
@@ -36,18 +38,53 @@ Shows added later still get through.
|
|||||||
|
|
||||||
The [ntfy app](https://ntfy.sh/#subscribe-phone) on your phone, and either Docker or Node.js 22+.
|
The [ntfy app](https://ntfy.sh/#subscribe-phone) on your phone, and either Docker or Node.js 22+.
|
||||||
|
|
||||||
## Quick start with Docker
|
## Quickest start: run the published image
|
||||||
|
|
||||||
|
A prebuilt image is published to GitHub Container Registry on every push to `main`, for both
|
||||||
|
`linux/amd64` and `linux/arm64`. It runs as-is on a normal server, an Apple Silicon Mac or a
|
||||||
|
Raspberry Pi, with nothing to clone and nothing to build.
|
||||||
|
|
||||||
|
Grab [`.env.example`](.env.example), save it as `.env`, fill it in using "Finding your IDs" below,
|
||||||
|
then:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name ticket-monitoring \
|
||||||
|
--restart unless-stopped \
|
||||||
|
--env-file .env \
|
||||||
|
-p 4733:4733 \
|
||||||
|
-v ticket-monitoring-data:/data \
|
||||||
|
ghcr.io/aculix/ticket-monitoring:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker logs -f ticket-monitoring
|
||||||
|
```
|
||||||
|
|
||||||
|
You want to see `tick: closed failures: 0` scrolling past once a minute.
|
||||||
|
|
||||||
|
The volume is what stops it re-alerting you about shows it already found, so keep it around across
|
||||||
|
restarts. Drop the `-p` flag if you don't want the status endpoint reachable. To update, pull the
|
||||||
|
image again and recreate the container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull ghcr.io/aculix/ticket-monitoring:latest
|
||||||
|
docker rm -f ticket-monitoring # then re-run the docker run command above
|
||||||
|
```
|
||||||
|
|
||||||
|
Only `:latest` is published, so that's always the current build of `main`.
|
||||||
|
|
||||||
|
## Quick start with Docker Compose
|
||||||
|
|
||||||
|
Handy if you'd rather keep the config in a file you can edit in place:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/aculix/ticket-monitoring.git
|
git clone https://github.com/aculix/ticket-monitoring.git
|
||||||
cd ticket-monitoring
|
cd ticket-monitoring
|
||||||
cp .env.example .env # edit it, see "Finding your IDs" below
|
cp .env.example .env # edit it, see "Finding your IDs" below
|
||||||
docker compose up -d --build
|
docker compose up -d # add --build to build locally instead of pulling
|
||||||
docker compose logs -f
|
docker compose logs -f
|
||||||
```
|
```
|
||||||
|
|
||||||
You want to see `tick: closed failures: 0` scrolling past once a minute.
|
|
||||||
|
|
||||||
## Quick start without Docker
|
## Quick start without Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -110,17 +147,21 @@ Everything is environment variables. `.env` is only a convenient place to put th
|
|||||||
| `CURRENCY` | `₹` | Price prefix |
|
| `CURRENCY` | `₹` | Price prefix |
|
||||||
| `EXPIRY_UTC` | *auto* | When to retire. Defaults to local midnight after `TARGET_DATE`. |
|
| `EXPIRY_UTC` | *auto* | When to retire. Defaults to local midnight after `TARGET_DATE`. |
|
||||||
| `STATE_PATH` | `./state.json` | Where dedupe state lives, `/data/state.json` in Docker |
|
| `STATE_PATH` | `./state.json` | Where dedupe state lives, `/data/state.json` in Docker |
|
||||||
| `PORT` | `8080` | Status endpoint |
|
| `PORT` | `4733` | Status endpoint |
|
||||||
| `PROXY_URL` | | SOCKS5 proxy for the site checks, see below |
|
| `PROXY_URL` | | SOCKS5 proxy for the site checks, see below |
|
||||||
|
|
||||||
## Status endpoint
|
## Status endpoint
|
||||||
|
|
||||||
While running continuously it serves JSON on `PORT`:
|
While running continuously it serves JSON on `PORT`, which defaults to 4733:
|
||||||
|
|
||||||
- `/` gives you state, `lastTick` and `proxied`
|
- `/` gives you state, `lastTick` and `proxied`
|
||||||
- `/?force=1` adds a live check right now, with no notifications and no state changes
|
- `/?force=1` adds a live check right now, with no notifications and no state changes
|
||||||
- `/healthz` returns `{"ok":true}`
|
- `/healthz` returns `{"ok":true}`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s localhost:4733/ | jq
|
||||||
|
```
|
||||||
|
|
||||||
Watch `lastTick.at`. If it's more than a couple of minutes old, the loop is stuck.
|
Watch `lastTick.at`. If it's more than a couple of minutes old, the loop is stuck.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|||||||
+4
-2
@@ -1,11 +1,13 @@
|
|||||||
services:
|
services:
|
||||||
monitor:
|
monitor:
|
||||||
|
# Pulls the prebuilt multi-arch image. Run `docker compose up --build` instead
|
||||||
|
# to build from this checkout; the result gets tagged with the same name.
|
||||||
|
image: ghcr.io/aculix/ticket-monitoring:latest
|
||||||
build: .
|
build: .
|
||||||
image: ticket-monitoring
|
|
||||||
container_name: ticket-monitoring
|
container_name: ticket-monitoring
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file: .env
|
env_file: .env
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080" # status endpoint; drop this line to keep it private
|
- "4733:4733" # status endpoint; drop this line to keep it private
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data # state survives restarts, so you aren't re-alerted
|
- ./data:/data # state survives restarts, so you aren't re-alerted
|
||||||
+1
-1
@@ -55,7 +55,7 @@ export function loadConfig() {
|
|||||||
|
|
||||||
// runtime
|
// runtime
|
||||||
statePath: process.env.STATE_PATH || "./state.json",
|
statePath: process.env.STATE_PATH || "./state.json",
|
||||||
port: num("PORT", 8080),
|
port: num("PORT", 4733),
|
||||||
proxyUrl: process.env.PROXY_URL || "",
|
proxyUrl: process.env.PROXY_URL || "",
|
||||||
dispatcher: null, // set by attachProxy() when PROXY_URL is present
|
dispatcher: null, // set by attachProxy() when PROXY_URL is present
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user