ci: cache GitHub builds and document image distribution
CI / Test and publish (push) Successful in 25s
CI / Test and publish (push) Successful in 25s
This commit is contained in:
@@ -37,8 +37,17 @@ jobs:
|
|||||||
- name: Check Docker
|
- name: Check Docker
|
||||||
run: docker version
|
run: docker version
|
||||||
|
|
||||||
|
- uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
- name: Check formatting, lint and build the release binary
|
- name: Check formatting, lint and build the release binary
|
||||||
run: docker build --target test --tag "$TEST_IMAGE" .
|
uses: docker/build-push-action@v7
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
target: test
|
||||||
|
tags: ${{ env.TEST_IMAGE }}
|
||||||
|
load: true
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
- name: Run E2E tests without network access
|
- name: Run E2E tests without network access
|
||||||
run: >-
|
run: >-
|
||||||
@@ -47,11 +56,16 @@ jobs:
|
|||||||
--memory 256m --cpus 2 --pids-limit 128 "$TEST_IMAGE"
|
--memory 256m --cpus 2 --pids-limit 128 "$TEST_IMAGE"
|
||||||
|
|
||||||
- name: Build the runtime image from the tested binary
|
- name: Build the runtime image from the tested binary
|
||||||
run: >-
|
uses: docker/build-push-action@v7
|
||||||
docker build --target runtime
|
with:
|
||||||
--label "org.opencontainers.image.revision=$REVISION"
|
context: .
|
||||||
--label "org.opencontainers.image.source=$SOURCE"
|
target: runtime
|
||||||
--tag "$IMAGE:sha-$REVISION" .
|
tags: ${{ env.IMAGE }}:sha-${{ env.REVISION }}
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.revision=${{ env.REVISION }}
|
||||||
|
org.opencontainers.image.source=${{ env.SOURCE }}
|
||||||
|
load: true
|
||||||
|
cache-from: type=gha
|
||||||
|
|
||||||
- name: Smoke-test the runtime image
|
- name: Smoke-test the runtime image
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -4,41 +4,83 @@ A small, stateless Rust service that turns [Vacationplanner](https://vacationpla
|
|||||||
vacations into an iCalendar subscription for Apple Calendar and other calendar apps.
|
vacations into an iCalendar subscription for Apple Calendar and other calendar apps.
|
||||||
It only calls `GET /v1/vacations/year/{year}`.
|
It only calls `GET /v1/vacations/year/{year}`.
|
||||||
|
|
||||||
## Run
|
## Ready-made Docker images
|
||||||
|
|
||||||
The registry requires authentication. Log in with a `packager` token that has
|
Both registries provide the same service for `linux/amd64`. Each platform tests,
|
||||||
`read:package` permission, then run the published `linux/amd64` image:
|
builds and publishes its own image:
|
||||||
|
|
||||||
|
| Registry | Package | Image |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| GitHub Container Registry | [GitHub package](https://github.com/valentineus/vacationplanner2ics/pkgs/container/vacationplanner2ics) | `ghcr.io/valentineus/vacationplanner2ics:latest` |
|
||||||
|
| Gitea Container Registry | [Gitea package](https://code.popov.link/packager/-/packages/container/vacationplanner2ics/latest) | `code.popov.link/packager/vacationplanner2ics:latest` |
|
||||||
|
|
||||||
|
Available tags:
|
||||||
|
|
||||||
|
- `latest`: the latest successful `master` build on that platform.
|
||||||
|
- `sha-<full-commit-sha>`: the tested commit.
|
||||||
|
- `v*`: the corresponding Git tag; does not overwrite `latest`.
|
||||||
|
|
||||||
|
Pull from GitHub:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker pull ghcr.io/valentineus/vacationplanner2ics:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Gitea currently requires a `packager` token with `read:package` permission.
|
||||||
|
Enter the token at the password prompt:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker login code.popov.link --username packager
|
docker login code.popov.link --username packager
|
||||||
docker run -d --name vacationplanner2ics --restart unless-stopped --read-only \
|
docker pull code.popov.link/packager/vacationplanner2ics:latest
|
||||||
-p 127.0.0.1:8080:8080 code.popov.link/packager/vacationplanner2ics:latest
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Or build from source with Docker Compose (also works natively on ARM64):
|
## Self-hosted usage
|
||||||
|
|
||||||
|
Docker is the only runtime requirement. Start either image, for example:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker compose up -d --build app
|
docker run -d --name vacationplanner2ics --restart unless-stopped --read-only \
|
||||||
|
-p 127.0.0.1:8080:8080 ghcr.io/valentineus/vacationplanner2ics:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
The service listens on `127.0.0.1:8080`. `GET /healthz` returns `ok`.
|
To use Gitea, replace the image name with the Gitea image listed above.
|
||||||
For public access, put an HTTPS reverse proxy in front of it.
|
Verify that the service is ready:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl --fail http://127.0.0.1:8080/healthz
|
||||||
|
```
|
||||||
|
|
||||||
|
The expected response is `ok`. The example exposes the service on
|
||||||
|
`127.0.0.1:8080`; for public access, put an HTTPS reverse proxy in front of it.
|
||||||
The image serves HTTP only. Its `scratch` filesystem contains a static musl binary
|
The image serves HTTP only. Its `scratch` filesystem contains a static musl binary
|
||||||
and CA certificates for outgoing HTTPS requests, with no shell or package manager.
|
and CA certificates for outgoing HTTPS requests, with no shell or package manager.
|
||||||
It runs as an unprivileged user.
|
It runs as an unprivileged user.
|
||||||
|
|
||||||
## Subscribe
|
## Calendar subscription and privacy
|
||||||
|
|
||||||
Add a calendar subscription using this URL, replacing the host and placeholder:
|
**Self-hosting is recommended. Do not blindly trust any hosted instance,
|
||||||
|
including the maintainer's.** Subscription URLs contain your Vacationplanner
|
||||||
|
API token. Service operators and hosting, CDN or proxy providers that terminate
|
||||||
|
HTTPS can read the full request URL, including its GET parameters. HTTPS protects
|
||||||
|
the connection; it does not hide the token from those operators.
|
||||||
|
|
||||||
|
The maintainer's instance is at [vacationplanner.popov.link](https://vacationplanner.popov.link/).
|
||||||
|
Query-string logging is disabled on the maintainer's server, but that is not a
|
||||||
|
guarantee of confidentiality across the infrastructure. Use it only if you accept
|
||||||
|
that trust requirement. Be careful with subscription URLs and prefer a server
|
||||||
|
you control.
|
||||||
|
|
||||||
|
Add a calendar subscription using this URL, replacing the token placeholder.
|
||||||
|
For self-hosting, also replace the host with your own:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
https://calendar.example.com/calendar.ics?token=YOUR_API_TOKEN
|
https://vacationplanner.popov.link/calendar.ics?token=YOUR_API_TOKEN
|
||||||
```
|
```
|
||||||
|
|
||||||
To select years:
|
To select years:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
https://calendar.example.com/calendar.ics?token=YOUR_API_TOKEN&years=2026,2027,2028
|
https://vacationplanner.popov.link/calendar.ics?token=YOUR_API_TOKEN&years=2026,2027,2028
|
||||||
```
|
```
|
||||||
|
|
||||||
| Query parameter | Meaning |
|
| Query parameter | Meaning |
|
||||||
@@ -97,28 +139,46 @@ access disabled. They cover calendar parsing with an independent iCalendar
|
|||||||
library, year selection, input/upstream failures and subscription updates.
|
library, year selection, input/upstream failures and subscription updates.
|
||||||
Tests use fake credentials only.
|
Tests use fake credentials only.
|
||||||
|
|
||||||
|
## Building from source
|
||||||
|
|
||||||
|
Clone the canonical repository and build with Docker Compose. This also works
|
||||||
|
natively on ARM64:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://code.popov.link/valentineus/vacationplanner2ics.git
|
||||||
|
cd vacationplanner2ics
|
||||||
|
docker compose up -d --build app
|
||||||
|
```
|
||||||
|
|
||||||
## CI and dependency updates
|
## CI and dependency updates
|
||||||
|
|
||||||
[Gitea Actions](https://code.popov.link/valentineus/vacationplanner2ics/actions)
|
[Gitea Actions](https://code.popov.link/valentineus/vacationplanner2ics/actions)
|
||||||
runs one CI workflow for `master` pushes, pull requests, `v*` tags and manual runs: formatting,
|
and [GitHub Actions](https://github.com/valentineus/vacationplanner2ics/actions)
|
||||||
|
run independent CI workflows for `master` pushes, pull requests, `v*` tags and manual runs: formatting,
|
||||||
Clippy with warnings denied, release compilation, the four E2E tests without
|
Clippy with warnings denied, release compilation, the four E2E tests without
|
||||||
network access, and an HTTP/shutdown check of the actual runtime image.
|
network access, and an HTTP/shutdown check of the actual runtime image.
|
||||||
Only successful `master` builds and `v*` tags publish images to
|
Only successful `master` builds and `v*` tags publish images. Gitea publishes
|
||||||
`code.popov.link/packager/vacationplanner2ics`:
|
only to `code.popov.link`; GitHub publishes only to `ghcr.io`.
|
||||||
|
|
||||||
- `latest`: the latest successful `master` build.
|
Both workflows build natively on AMD64, limit compilation to two jobs and package
|
||||||
- `sha-<full-commit-sha>`: the tested commit.
|
the already-tested binary. Gitea reuses the runner's BuildKit/Cargo caches;
|
||||||
- `v*`: the corresponding Git tag; does not overwrite `latest`.
|
GitHub saves Docker build layers in its Actions cache.
|
||||||
|
|
||||||
CI uses the runner's native AMD64 architecture, reuses BuildKit/Cargo caches,
|
Gitea publishing uses the Actions secret `REGISTRY_TOKEN`, belonging to `packager`
|
||||||
limits compilation to two jobs and packages the already-tested binary.
|
with `write:package` permission. GitHub uses its automatic `GITHUB_TOKEN` with
|
||||||
Publishing requires the Actions secret `REGISTRY_TOKEN`, belonging to `packager`
|
`packages: write`; no extra publishing secret is needed. No Vacationplanner
|
||||||
with `write:package` permission. No Vacationplanner token is used in CI.
|
token is used in either CI.
|
||||||
|
|
||||||
Renovate runs daily or manually, using `RENOVATE_TOKEN` for Gitea and
|
Renovate runs on Gitea daily or manually, using `RENOVATE_TOKEN` for Gitea and
|
||||||
`RENOVATE_GITHUB_TOKEN` for dependency metadata. Non-major updates are grouped;
|
`RENOVATE_GITHUB_TOKEN` for dependency metadata. Non-major updates are grouped;
|
||||||
updates require review and are not merged automatically.
|
updates require review and are not merged automatically.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Repository locations: [Gitea — canonical source](https://code.popov.link/valentineus/vacationplanner2ics) · [GitHub — secondary mirror](https://github.com/valentineus/vacationplanner2ics).
|
||||||
|
|
||||||
|
Changes are pushed to Gitea and automatically mirrored to GitHub.
|
||||||
|
|||||||
Reference in New Issue
Block a user