89 Commits

Author SHA1 Message Date
3f78f2d4c5 Readding ServiceAccount (#212)
* Readding ServiceAccount

* Bumping version
2026-06-10 03:32:09 +00:00
b5eb61a43d Adding health probes, resource requests and fixing container permissions (#210)
* Adding health probes and fixing container permissions

* Bump version

* Cleanup

* No ServiceAccount anymore

* No ServiceAccount anymore

* Update pull secrets

* Fixing yaml issue

* Fixed resource requests and limits

* Bumping version
2026-06-09 23:41:50 +00:00
240af34978 Updating Helm documentation (#209)
* Updating Helm documentation

* No version number
2026-05-29 22:06:53 +00:00
1a4f1d94b6 Fix pod security (#204)
* Fix pod security

* Extra security context

* Use correct security context
2026-05-29 18:06:47 +00:00
6612d0d02b Fix install directory for helm chart (#207)
* Fixing helm publish path

* Fixing install dir for helm chart
2026-05-29 17:46:22 +00:00
d77966351b Fixing helm publish path (#206) 2026-05-29 17:37:12 +00:00
039bd77ec1 Add more specific settings for HTTPRoute (#203)
* Adding Helm chart

* Update maintainer

* Updating filesystem settings to prevent issues

* CREATE_CLIENTS is now true by default

* Add name override options

* Validation for postges

* Fix plain connection string in pod env

* Simplifying secret management

* Fix port quoting

* Init container to run sql file

* Fix port type

* Fix secret management

* Working now

* Fixing Postgres connection issue

* Upgrade postgres init container

* Auto add UUIDs when starting postgres

* feat: Use standard value names for adding HTTPReoute

* fix: Remove merge issues

* chore: bump version
2026-05-29 17:30:07 +00:00
7d772f4b5e Add GitHub Action to test the helm chart before merging (#205)
* Adding Helm chart

* Update maintainer

* Updating filesystem settings to prevent issues

* CREATE_CLIENTS is now true by default

* Add name override options

* Validation for postges

* Fix plain connection string in pod env

* Simplifying secret management

* Fix port quoting

* Init container to run sql file

* Fix port type

* Fix secret management

* Working now

* Fixing Postgres connection issue

* Upgrade postgres init container

* Auto add UUIDs when starting postgres

* Add Github action to publish new Helm charts on push

* Fixing url

* Removing duplicate files

* Adding documentation for helm chart

* Reorganizing

* Adding helm testing
2026-05-29 17:22:28 +00:00
865203fa93 Merge pull request #202 from GothenburgBitFactory/dependabot/cargo/openssl-0.10.80
Bump openssl from 0.10.79 to 0.10.80
2026-05-29 16:40:29 +00:00
0f422af080 Bump openssl from 0.10.79 to 0.10.80
Bumps [openssl](https://github.com/rust-openssl/rust-openssl) from 0.10.79 to 0.10.80.
- [Release notes](https://github.com/rust-openssl/rust-openssl/releases)
- [Commits](https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.79...openssl-v0.10.80)

---
updated-dependencies:
- dependency-name: openssl
  dependency-version: 0.10.80
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 17:55:41 +00:00
2aab707178 Merge pull request #201 from GothenburgBitFactory/dependabot/github_actions/github-actions-45018e1108 2026-05-18 22:42:19 -06:00
7556092a84 Bump the github-actions group with 3 updates
Bumps the github-actions group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [azure/setup-helm](https://github.com/azure/setup-helm) and [helm/chart-releaser-action](https://github.com/helm/chart-releaser-action).


Updates `actions/checkout` from 4 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

Updates `azure/setup-helm` from 4 to 5
- [Release notes](https://github.com/azure/setup-helm/releases)
- [Changelog](https://github.com/Azure/setup-helm/blob/main/CHANGELOG.md)
- [Commits](https://github.com/azure/setup-helm/compare/v4...v5)

Updates `helm/chart-releaser-action` from 1.6.0 to 1.7.0
- [Release notes](https://github.com/helm/chart-releaser-action/releases)
- [Commits](https://github.com/helm/chart-releaser-action/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: azure/setup-helm
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: helm/chart-releaser-action
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-17 23:52:57 +00:00
79118c0366 Forgot to fix the chart path (#200) 2026-05-12 11:44:49 -04:00
5165897200 Helm-chart GitHub action (#199) 2026-05-12 08:00:16 -04:00
d7d9de3bbe Auto add UUIDs when starting postgres 2026-05-11 21:11:11 -04:00
269efce4f1 Upgrade postgres init container 2026-05-11 21:11:11 -04:00
ef98290f37 Fixing Postgres connection issue 2026-05-11 21:11:11 -04:00
79d54cae5d Working now 2026-05-11 21:11:11 -04:00
2f84198600 Fix secret management 2026-05-11 21:11:11 -04:00
c857163d85 Fix port type 2026-05-11 21:11:11 -04:00
27c3f954c9 Init container to run sql file 2026-05-11 21:11:11 -04:00
a8f7281786 Fix port quoting 2026-05-11 21:11:11 -04:00
84c06475c6 Simplifying secret management 2026-05-11 21:11:11 -04:00
c58bb4800d Fix plain connection string in pod env 2026-05-11 21:11:11 -04:00
eee66c5475 Validation for postges 2026-05-11 21:11:11 -04:00
9bddb2f261 Add name override options 2026-05-11 21:11:11 -04:00
911c0cbc57 CREATE_CLIENTS is now true by default 2026-05-11 21:11:11 -04:00
ed3b5553fa Updating filesystem settings to prevent issues 2026-05-11 21:11:11 -04:00
583d7dbe63 Update maintainer 2026-05-11 21:11:11 -04:00
b98c87798c Adding Helm chart 2026-05-11 21:11:11 -04:00
dd1b87dad5 Bump the github-actions group with 2 updates
Bumps the github-actions group with 2 updates: [actions/add-to-project](https://github.com/actions/add-to-project) and [docker/build-push-action](https://github.com/docker/build-push-action).


Updates `actions/add-to-project` from 1.0.2 to 2.0.0
- [Release notes](https://github.com/actions/add-to-project/releases)
- [Commits](https://github.com/actions/add-to-project/compare/v1.0.2...v2.0.0)

Updates `docker/build-push-action` from 6 to 7
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/add-to-project
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/build-push-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-11 20:53:32 -04:00
e1bebc7325 Bump openssl from 0.10.78 to 0.10.79
Bumps [openssl](https://github.com/rust-openssl/rust-openssl) from 0.10.78 to 0.10.79.
- [Release notes](https://github.com/rust-openssl/rust-openssl/releases)
- [Commits](https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.78...openssl-v0.10.79)

---
updated-dependencies:
- dependency-name: openssl
  dependency-version: 0.10.79
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-06 23:31:42 -04:00
5356f2baaa Bump actix-http from 3.12.0 to 3.12.1
Bumps [actix-http](https://github.com/actix/actix-web) from 3.12.0 to 3.12.1.
- [Release notes](https://github.com/actix/actix-web/releases)
- [Changelog](https://github.com/actix/actix-web/blob/main/CHANGES.md)
- [Commits](https://github.com/actix/actix-web/compare/http-v3.12.0...http-v3.12.1)

---
updated-dependencies:
- dependency-name: actix-http
  dependency-version: 3.12.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-25 09:26:40 -04:00
389113ce92 Bump openssl from 0.10.73 to 0.10.78
Bumps [openssl](https://github.com/rust-openssl/rust-openssl) from 0.10.73 to 0.10.78.
- [Release notes](https://github.com/rust-openssl/rust-openssl/releases)
- [Commits](https://github.com/rust-openssl/rust-openssl/compare/openssl-v0.10.73...openssl-v0.10.78)

---
updated-dependencies:
- dependency-name: openssl
  dependency-version: 0.10.78
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-25 09:26:21 -04:00
25d8708630 Add an MSRV comment to Dockerfiles 2026-04-18 08:34:21 -04:00
6746e6ed3b Update Rust version
Signed-off-by: Evangelos Lamprou <vagos@lamprou.xyz>
2026-04-17 07:53:03 -04:00
bac5e50448 Fix docker build invocations (#188)
Signed-off-by: Evangelos Lamprou <vagos@lamprou.xyz>
2026-04-17 07:51:27 -04:00
da96579546 Bump rand from 0.9.1 to 0.9.4 (#186)
Bumps [rand](https://github.com/rust-random/rand) from 0.9.1 to 0.9.4.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/0.9.4/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/rand_core-0.9.1...0.9.4)

---
updated-dependencies:
- dependency-name: rand
  dependency-version: 0.9.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 20:12:08 -04:00
4fe70cf030 Bump tokio from 1.51.0 to 1.52.0 in the cargo group (#187)
Bumps the cargo group with 1 update: [tokio](https://github.com/tokio-rs/tokio).


Updates `tokio` from 1.51.0 to 1.52.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.51.0...tokio-1.52.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.52.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 20:11:51 -04:00
24674bb0e0 Bump tempfile from 3.23.0 to 3.27.0 in the cargo group (#185)
Bumps the cargo group with 1 update: [tempfile](https://github.com/Stebalien/tempfile).


Updates `tempfile` from 3.23.0 to 3.27.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.23.0...v3.27.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-version: 3.27.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-06 20:41:39 -04:00
8a2092b176 Bump the cargo group across 1 directory with 2 updates (#184)
Bumps the cargo group with 2 updates in the / directory: [uuid](https://github.com/uuid-rs/uuid) and [tokio](https://github.com/tokio-rs/tokio).


Updates `uuid` from 1.22.0 to 1.23.0
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.22.0...v1.23.0)

Updates `tokio` from 1.50.0 to 1.51.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.50.0...tokio-1.51.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 1.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: tokio
  dependency-version: 1.51.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-04 14:49:23 -04:00
c475c01f51 group dependabot updates (#182) 2026-03-12 22:13:48 -04:00
7f07803b5b Bump clap from 4.5.41 to 4.5.60 (#181)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.41 to 4.5.60.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.41...clap_complete-v4.5.60)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.60
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-12 22:01:21 -04:00
409bdd4d2b Bump docker/setup-qemu-action from 3 to 4 (#176)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 20:16:31 -04:00
3b68d5aa3a Bump docker/login-action from 3 to 4 (#177)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 20:16:22 -04:00
832be300ca Bump docker/metadata-action from 5 to 6 (#179)
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 20:16:14 -04:00
6c30505fb3 Bump docker/setup-buildx-action from 3 to 4 (#180)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-09 20:15:59 -04:00
591f38943f Bump tokio from 1.49.0 to 1.50.0 (#174)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.49.0 to 1.50.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.49.0...tokio-1.50.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.50.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-08 14:41:11 -04:00
5320b850c4 Bump uuid from 1.21.0 to 1.22.0 (#175)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.21.0 to 1.22.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.21.0...v1.22.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-07 10:09:06 -05:00
c5e78104a2 Bump actix-web from 4.12.0 to 4.13.0 (#173)
Bumps [actix-web](https://github.com/actix/actix-web) from 4.12.0 to 4.13.0.
- [Release notes](https://github.com/actix/actix-web/releases)
- [Changelog](https://github.com/actix/actix-web/blob/main/CHANGES.md)
- [Commits](https://github.com/actix/actix-web/compare/web-v4.12.0...web-v4.13.0)

---
updated-dependencies:
- dependency-name: actix-web
  dependency-version: 4.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-18 20:00:57 -05:00
875e39d474 Bump uuid from 1.20.0 to 1.21.0 (#172)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.20.0 to 1.21.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.20.0...v1.21.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 1.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-16 22:21:57 -05:00
3c6a599613 Bump time from 0.3.41 to 0.3.47 (#170)
Bumps [time](https://github.com/time-rs/time) from 0.3.41 to 0.3.47.
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.41...v0.3.47)

---
updated-dependencies:
- dependency-name: time
  dependency-version: 0.3.47
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-07 09:32:40 -05:00
a6a8b7c68d Update MSRV to support newer versions of time (#171) 2026-02-07 09:13:10 -05:00
5bc24d43e3 Bump uuid from 1.19.0 to 1.20.0 (#169)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.19.0 to 1.20.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.19.0...v1.20.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 1.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-04 20:49:12 -05:00
aa5e97a9fd Bump bytes from 1.10.1 to 1.11.1 (#168)
Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.10.1 to 1.11.1.
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.10.1...v1.11.1)

---
updated-dependencies:
- dependency-name: bytes
  dependency-version: 1.11.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-04 20:47:39 -05:00
3282386849 Bump tokio from 1.48.0 to 1.49.0 (#165)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.48.0 to 1.49.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.48.0...tokio-1.49.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.49.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-05 20:59:30 -05:00
a862f02682 Bump actions/cache from 4 to 5 (#164)
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 21:25:57 -05:00
2e69bea5ea Bump uuid from 1.18.0 to 1.19.0 (#163)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.18.0 to 1.19.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.18.0...v1.19.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 1.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 23:03:54 -05:00
c60e95bbf0 Bump actions/checkout from 5 to 6 (#162)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-27 22:41:56 -05:00
9cf07e9d80 Update actix-* to latest (#161) 2025-11-17 21:38:55 -05:00
c3470f4756 Add all new issues to the project (#159) 2025-11-13 19:31:39 -05:00
789106b517 Refactor Docker build commands in README (#157)
Updated Docker build commands for SQLite and Postgres to include Dockerfile specifications.

Fixes #156.
2025-11-01 15:30:52 -04:00
72aeebdda7 Bump rusqlite from 0.32.1 to 0.37.0 (#158)
Bumps [rusqlite](https://github.com/rusqlite/rusqlite) from 0.32.1 to 0.37.0.
- [Release notes](https://github.com/rusqlite/rusqlite/releases)
- [Changelog](https://github.com/rusqlite/rusqlite/blob/master/Changelog.md)
- [Commits](https://github.com/rusqlite/rusqlite/compare/v0.32.1...v0.37.0)

---
updated-dependencies:
- dependency-name: rusqlite
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-16 19:33:51 -04:00
eed6421a4e Bump tokio from 1.47.0 to 1.48.0 (#155)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.47.0 to 1.48.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.47.0...tokio-1.48.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-14 20:33:46 -04:00
5d013073cb Bump to -pre version 2025-10-11 19:02:31 +00:00
67524a0a91 Simplify cargo publish steps in RELEASING.md
Updated release instructions to simplify publishing process.
2025-10-11 14:58:26 -04:00
d206729d5e v0.7.1 2025-10-11 18:57:23 +00:00
bf19b76577 Bump actix-rt from 2.10.0 to 2.11.0 (#151)
Bumps [actix-rt](https://github.com/actix/actix-net) from 2.10.0 to 2.11.0.
- [Release notes](https://github.com/actix/actix-net/releases)
- [Commits](https://github.com/actix/actix-net/compare/rt-v2.10.0...rt-v2.11.0)

---
updated-dependencies:
- dependency-name: actix-rt
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-10 21:21:10 -04:00
505dd3f442 Bump tempfile from 3.22.0 to 3.23.0 (#153)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.22.0 to 3.23.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.22.0...v3.23.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-version: 3.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-23 22:09:46 -04:00
e10f3e6cfb Bump tempfile from 3.21.0 to 3.22.0 (#152)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.21.0 to 3.22.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.21.0...v3.22.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-version: 3.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-10 19:04:12 -04:00
213be852b8 Fix add_version calls when no history exists on the server (#149)
This fixes a bug in 25911b44a6 where the
check in the storage implementation was too strict (not allowing
`clients.latest_version_id == Uuid::nil()`), causing spurious failures.

Well, two bugs, one in each storage implementation.
2025-08-20 15:21:04 -04:00
b57dd24d9e Bump tempfile from 3.20.0 to 3.21.0 (#150)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.20.0 to 3.21.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/commits)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-version: 3.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-20 08:45:41 -04:00
a9cf67c8e2 Document Cargo features in the binaries page (#148) 2025-08-18 08:29:32 -04:00
daf6855f14 Bump slab from 0.4.10 to 0.4.11 (#147)
Bumps [slab](https://github.com/tokio-rs/slab) from 0.4.10 to 0.4.11.
- [Release notes](https://github.com/tokio-rs/slab/releases)
- [Changelog](https://github.com/tokio-rs/slab/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/slab/compare/v0.4.10...v0.4.11)

---
updated-dependencies:
- dependency-name: slab
  dependency-version: 0.4.11
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 22:09:38 -04:00
dbc9a6909b Bump actions/checkout from 4 to 5 (#145)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 19:55:19 -04:00
1ad9e344c7 Bump uuid from 1.17.0 to 1.18.0 (#146)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.17.0 to 1.18.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 1.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 19:55:00 -04:00
3820a8deea Document the different sslmodes recognized by the postgres crate (#144)
LibPQ will happily accept invalid certificates or hostnames, while the
Rust client will not. This can cause some confusion, so draw attention
to it here.
2025-08-04 07:24:59 -04:00
2de70ac336 Capture and log errors from bb8 (#143) 2025-08-03 11:13:58 -04:00
c2b4c94fb5 Merge remote-tracking branch 'origin/main' 2025-08-02 21:01:41 -04:00
0a317cd86d Only publish docs on tags (#136) 2025-08-01 17:48:34 -04:00
1b80398365 Merge post-0.7.0-release updates into main 2025-07-30 22:41:25 -04:00
5a2bd4cde7 Use git context for building docker images 2025-07-30 21:50:30 -04:00
e5b35210af include dockerfiles in context 2025-07-30 21:38:58 -04:00
3bbfcb9f88 Fix Dockerfile reference 2025-07-30 21:35:21 -04:00
8752531e2c Use correct option to docker/build-push-action for Dockerfiles 2025-07-30 21:33:46 -04:00
a94be2649e Use correct option to docker/build-push-action for Dockerfiles 2025-07-30 21:32:27 -04:00
624efa8b0d stop excluding the postgres crate 2025-07-30 21:23:53 -04:00
ae9adf1572 Bump to -pre version 2025-07-30 21:23:03 -04:00
547621950f v0.7.0 2025-07-30 21:20:25 -04:00
43 changed files with 1836 additions and 315 deletions

View File

@ -6,3 +6,4 @@
!sqlite/
!postgres/
!entrypoint-*
!Dockerfile*

View File

@ -5,6 +5,9 @@ updates:
directory: "/"
schedule:
interval: "weekly"
groups:
github-actions:
patterns: ["*"]
# Enable updates for Rust packages
- package-ecosystem: "cargo"
directory: "/" # Location of package manifests
@ -16,3 +19,8 @@ updates:
# behind
- dependency-name: "*"
update-types: ["version-update:semver-patch"]
groups:
cargo:
patterns: ["*"]
# leave major changes in their own PRs
update-types: ["minor", "patch"]

18
.github/workflows/add-to-project.yml vendored Normal file
View File

@ -0,0 +1,18 @@
# This adds all new issues to the Taskwarrior project, for better tracking.
# It uses a PAT that belongs to @taskwarrior.
name: Add issues to Taskwarrior Project
on:
issues:
types:
- opened
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v2.0.0
with:
project-url: https://github.com/orgs/GothenburgBitFactory/projects/4
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}

View File

@ -13,16 +13,16 @@ jobs:
name: "Check & Clippy"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Cache cargo registry
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
@ -48,10 +48,10 @@ jobs:
name: "Rustdoc"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Cache cargo registry
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
@ -96,7 +96,7 @@ jobs:
runs-on: ubuntu-latest
name: "Formatting"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: actions-rs/toolchain@v1
with:
@ -114,19 +114,18 @@ jobs:
runs-on: ubuntu-latest
name: "Cargo Semver Checks"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: obi1kenobi/cargo-semver-checks-action@v2
with:
# exclude the binary package from semver checks, since it is not published as a crate.
# exclude postgres temporarily until it is released
exclude: taskchampion-sync-server,taskchampion-sync-server-storage-postgres
exclude: taskchampion-sync-server
mdbook:
runs-on: ubuntu-latest
name: "mdBook Documentation"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v2

View File

@ -10,18 +10,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Login to ghcr.io
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta-sqlite
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: |
ghcr.io/gothenburgbitfactory/taskchampion-sync-server
@ -31,10 +31,9 @@ jobs:
type=semver,pattern={{major}}.{{minor}}
type=match,pattern=\d.\d.\d,value=latest
- name: Build and push
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
path: "{context}/Dockerfile-sqlite"
file: "./Dockerfile-sqlite"
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta-sqlite.outputs.tags }}
@ -43,16 +42,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Login to ghcr.io
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta-postgres
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: |
ghcr.io/gothenburgbitfactory/taskchampion-sync-server-postgres
@ -62,10 +61,9 @@ jobs:
type=semver,pattern={{major}}.{{minor}}
type=match,pattern=\d.\d.\d,value=latest
- name: Build and push
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
path: "{context}/Dockerfile-postgres"
file: "./Dockerfile-postgres"
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta-postgres.outputs.tags }}

169
.github/workflows/helm-test.yml vendored Normal file
View File

@ -0,0 +1,169 @@
name: Helm Chart Tests
on:
push:
branches: [main]
paths:
- 'helm/**'
pull_request:
paths:
- 'helm/**'
jobs:
helm-test:
runs-on: ubuntu-latest
name: "Helm Lint & Template"
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Helm
uses: azure/setup-helm@v5
with:
version: latest
- name: Helm lint (default values — expects failure, no backend enabled)
run: |
helm lint helm/taskchampion-sync-server \
--strict 2>&1 || true
- name: Template default values — must fail validation
run: |
if helm template test-release helm/taskchampion-sync-server 2>/dev/null; then
echo "❌ Expected chart to fail validation (no backend enabled) but it succeeded"
exit 1
fi
echo "✓ Correctly rejects chart with no backend enabled"
- name: Template with SQLite values
run: |
helm template test-release helm/taskchampion-sync-server \
-f helm/taskchampion-sync-server/examples/sqlite-values.yaml \
--debug > /tmp/helm-sqlite.yaml
echo "=== Generated resources (SQLite) ==="
grep -E '^# Source:' /tmp/helm-sqlite.yaml
# Verify key resources exist
grep -q 'kind: Deployment' /tmp/helm-sqlite.yaml
grep -q 'kind: Service' /tmp/helm-sqlite.yaml
grep -q 'kind: Ingress' /tmp/helm-sqlite.yaml
# Verify SQLite-specific rendering
grep -q 'emptyDir' /tmp/helm-sqlite.yaml
grep -q 'DATA_DIR' /tmp/helm-sqlite.yaml
# Verify PostgreSQL-specific rendering is absent
if grep -q 'initContainers' /tmp/helm-sqlite.yaml; then
echo "❌ initContainers should not appear in SQLite mode"
exit 1
fi
if grep -q 'CONNECTION' /tmp/helm-sqlite.yaml; then
echo "❌ CONNECTION env var should not appear in SQLite mode"
exit 1
fi
# Verify correct image tag (no -postgres suffix)
grep -q 'image:.*taskchampion-sync-server:0.7.0' /tmp/helm-sqlite.yaml
echo "✓ SQLite template generated successfully"
- name: Template with PostgreSQL values
run: |
helm template test-release helm/taskchampion-sync-server \
-f helm/taskchampion-sync-server/examples/postgres-values.yaml \
--debug > /tmp/helm-postgres.yaml
echo "=== Generated resources (PostgreSQL) ==="
grep -E '^# Source:' /tmp/helm-postgres.yaml
# Verify key resources exist
grep -q 'kind: Deployment' /tmp/helm-postgres.yaml
grep -q 'kind: Service' /tmp/helm-postgres.yaml
grep -q 'kind: Secret' /tmp/helm-postgres.yaml
# Verify PostgreSQL-specific rendering
grep -q 'kind: HTTPRoute' /tmp/helm-postgres.yaml
grep -q 'initContainers' /tmp/helm-postgres.yaml
grep -q 'CONNECTION' /tmp/helm-postgres.yaml
grep -q 'replicas: 3' /tmp/helm-postgres.yaml
# Verify correct image tag (with -postgres suffix)
grep -q 'image:.*taskchampion-sync-server-postgres:0.7.0' /tmp/helm-postgres.yaml
# Verify SQLite-specific rendering is absent
if grep -q 'DATA_DIR' /tmp/helm-postgres.yaml; then
echo "❌ DATA_DIR env var should not appear in PostgreSQL mode"
exit 1
fi
echo "✓ PostgreSQL template generated successfully"
- name: Template with both backends enabled — must fail validation
run: |
if helm template test-release helm/taskchampion-sync-server \
--set sqlite.enabled=true \
--set postgres.enabled=true 2>/dev/null; then
echo "❌ Expected chart to fail validation (both backends enabled) but it succeeded"
exit 1
fi
echo "✓ Correctly rejects chart with both backends enabled"
- name: Template with custom overrides
run: |
helm template test-release helm/taskchampion-sync-server \
--set sqlite.enabled=true \
--set postgres.enabled=false \
--set nameOverride=custom-name \
--set image.tag=latest \
--debug > /tmp/helm-custom.yaml
# Verify custom name override
grep -q 'custom-name' /tmp/helm-custom.yaml
grep -q 'custom-name-pvc' /tmp/helm-custom.yaml
# Verify custom image tag
grep -q 'image:.*taskchampion-sync-server:latest' /tmp/helm-custom.yaml
echo "✓ Custom overrides template generated successfully"
- name: Helm install dry-run (SQLite)
run: |
helm install test-release helm/taskchampion-sync-server \
-f helm/taskchampion-sync-server/examples/sqlite-values.yaml \
--dry-run 2>&1 | head -5
echo "✓ Helm install dry-run (SQLite) succeeded"
helm-kubeconform:
runs-on: ubuntu-latest
name: "Kubeconform Validation"
needs: helm-test
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Helm
uses: azure/setup-helm@v5
with:
version: latest
- name: Download kubeconform
run: |
wget -q -O /tmp/kubeconform.tar.gz \
https://github.com/yannh/kubeconform/releases/download/v0.6.7/kubeconform-linux-amd64.tar.gz
tar -xzf /tmp/kubeconform.tar.gz -C /usr/local/bin/ kubeconform
kubeconform -v
- name: Validate SQLite output against Kubernetes schemas
run: |
helm template test-release helm/taskchampion-sync-server \
-f helm/taskchampion-sync-server/examples/sqlite-values.yaml > /tmp/helm-sqlite.yaml
kubeconform -strict /tmp/helm-sqlite.yaml
echo "✓ SQLite resources are valid Kubernetes manifests"
- name: Validate PostgreSQL output against Kubernetes schemas
run: |
helm template test-release helm/taskchampion-sync-server \
-f helm/taskchampion-sync-server/examples/postgres-values.yaml > /tmp/helm-postgres.yaml
# Skip kubeconform on HTTPRoute since Gateway API CRDs aren't bundled
kubeconform -strict -ignore-missing-schemas /tmp/helm-postgres.yaml
echo "✓ PostgreSQL resources are valid Kubernetes manifests"

View File

@ -2,8 +2,8 @@ name: docs
on:
push:
branches:
- main
tags:
- '*'
permissions:
contents: write
@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v2
@ -28,3 +28,4 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/book
keep_files: true

36
.github/workflows/publish-helm.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: Publish Helm Charts
on:
push:
branches:
- main
paths:
- 'helm/**'
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v5
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.7.0
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
with:
charts_dir: helm
install_dir: helm-chart

View File

@ -15,7 +15,7 @@ jobs:
- "17"
rust:
# MSRV
- "1.85.0"
- "1.88.0"
- "stable"
runs-on: ubuntu-latest
@ -39,16 +39,16 @@ jobs:
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Cache cargo registry
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: target
key: ${{ runner.os }}-${{ matrix.rust }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}

View File

@ -14,7 +14,7 @@ jobs:
permissions: write-all
name: "Audit Rust Dependencies"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: rustsec/audit-check@v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}

623
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,30 +6,30 @@ members = [
"sqlite",
"postgres",
]
rust-version = "1.85.0" # MSRV
rust-version = "1.88.0" # MSRV
[workspace.dependencies]
async-trait = "0.1.88"
uuid = { version = "^1.17.0", features = ["serde", "v4"] }
actix-web = "^4.11.0"
uuid = { version = "^1.23.0", features = ["serde", "v4"] }
actix-web = "^4.13.0"
anyhow = "1.0"
thiserror = "2.0"
futures = "^0.3.25"
serde_json = "^1.0"
serde = { version = "^1.0.147", features = ["derive"] }
clap = { version = "^4.5.6", features = ["string", "env"] }
clap = { version = "^4.5.60", features = ["string", "env"] }
log = "^0.4.17"
env_logger = "^0.11.7"
rusqlite = { version = "0.32", features = ["bundled"] }
rusqlite = { version = "0.37", features = ["bundled"] }
chrono = { version = "^0.4.38", features = ["serde"] }
actix-rt = "2"
tempfile = "3"
pretty_assertions = "1"
temp-env = "0.3"
tokio = { version = "*", features = ["rt", "macros"] }
tokio = { version = "1.52", features = ["rt", "macros"] }
tokio-postgres = { version = "0.7.13", features = ["with-uuid-1"] }
bb8 = "0.9.0"
bb8-postgres = { version = "0.9.0", features = ["with-uuid-1"] }
openssl = { version = "0.10.73", default-features = false, features = ["vendored"] }
openssl = { version = "0.10.80", default-features = false, features = ["vendored"] }
native-tls = { version = "0.2.14", default-features = false, features = ["vendored"] }
postgres-native-tls = "0.5.1"

View File

@ -1,6 +1,7 @@
# Versions must be major.minor
# Default versions are as below
ARG RUST_VERSION=1.85
# RUST_VERSION should match the MSRV in Cargo.toml.
ARG RUST_VERSION=1.88
ARG ALPINE_VERSION=3.20
FROM docker.io/rust:${RUST_VERSION}-alpine${ALPINE_VERSION} AS builder

View File

@ -1,6 +1,7 @@
# Versions must be major.minor
# Default versions are as below
ARG RUST_VERSION=1.85
# RUST_VERSION should match the MSRV in Cargo.toml.
ARG RUST_VERSION=1.88
ARG ALPINE_VERSION=3.20
FROM docker.io/rust:${RUST_VERSION}-alpine${ALPINE_VERSION} AS builder

View File

@ -74,20 +74,17 @@ To build the images, execute the following commands.
SQLite:
```sh
source .env
docker build \
--build-arg RUST_VERSION=${RUST_VERSION} \
--build-arg ALPINE_VERSION=${ALPINE_VERSION} \
-t taskchampion-sync-server docker/sqlite
-t taskchampion-sync-server \
-f Dockerfile-sqlite .
```
Postgres:
```sh
source .env
docker build \
--build-arg RUST_VERSION=${RUST_VERSION} \
--build-arg ALPINE_VERSION=${ALPINE_VERSION} \
-t taskchampion-sync-server-postgres docker/postgres
-t taskchampion-sync-server-postgres \
-f Dockerfile-postgres .
```
Now to run it, simply exec.

View File

@ -4,7 +4,7 @@
1. Run `cargo test`
1. Run `cargo clean && cargo clippy`
1. Remove the `-pre` from `version` in all `*/Cargo.toml`, and from the `version = ..` in any references between packages.
1. Update the link to `docker-compose.yml` in `README.md` to refer to the new version.
1. Update the link to `docker-compose.yml` in `docs/src/usage/docker-compose.md` to refer to the new version.
1. Update the docker image in `docker-compose.yml` to refer to the new version.
1. Run `cargo semver-checks` (https://crates.io/crates/cargo-semver-checks)
1. Run `cargo build --release`
@ -12,66 +12,9 @@
1. Run `git tag vX.Y.Z`
1. Run `git push upstream`
1. Run `git push upstream --tag vX.Y.Z`
1. Run `cargo publish -p taskchampion-sync-server-core`
1. Run `cargo publish -p taskchampion-sync-server-storage-sqlite` (and add any other new published packages here)
1. Run `cargo publish` to publish all packages in the workspace
1. Bump the patch version in `*/Cargo.toml` and add the `-pre` suffix. This allows `cargo-semver-checks` to check for changes not accounted for in the version delta.
1. Run `cargo build --release` again to update `Cargo.lock`
1. Commit that change with comment "Bump to -pre version".
1. Run `git push upstream`
1. Navigate to the tag in the GitHub releases UI and create a release with general comments about the changes in the release
---
For the next release,
- remove postgres from the exclusion list in `.github/workflows/checks.yml` after the release
- include the folowing in the release notes:
Running the Docker image for this server without specifying DATA_DIR
defaulted to storing the server data in
`/var/lib/taskchampion-sync-server`. However, the Dockerfile only
specifies that the subdirectory `/var/lib/taskchampion-sync-server/data`
is a VOLUME. This change fixes the default to match the VOLUME, putting
the server data on an ephemeral volume or, if a `--volume
$NAME:/var/lib/taskchampion-sync-server/data` argument is provided to
`docker run`, in a named volume.
Before this commit, with default settings the server data is stored in
the container's ephemeral writeable layer. When the container is killed,
the data is lost. This issue does not affect deployments with `docker
compose`, as the compose configuration specifies a correct `DATA_DIR`.
You can determine if your deployment is affected as follows. First,
determine the ID of the running server container, `$CONTAINER`. Examine
the volumes for that container:
```shell
$ docker container inspect $CONTAINER | jq '.[0].Config.Volumes'
{
"/var/lib/task-champion-sync-server/data": {}
}
```
Next, find the server data, in a `.sqlite3` file:
```shell
$ docker exec $CONTAINER find /var/lib/taskchampion-sync-server
/var/lib/taskchampion-sync-server
/var/lib/taskchampion-sync-server/data
/var/lib/taskchampion-sync-server/taskchampion-sync-server.sqlite3
```
If the data is not in a directory mounted as a volume, then it is
ephemeral. To copy the data out of the container:
```shell
docker cp $CONTAINER:/var/lib/taskchampion-sync-server/taskchampion-sync-server.sqlite3 /tmp
```
You may then upgrade the image and use `docker cp` to copy the data back
to the correct location, `/var/lib/taskchampion-sync-server/data`.
Note that, as long as all replicas are fully synced, the TaskChampion
sync protocol is resilient to loss of server data, so even if the server
data has been lost, `task sync` may continue to work.

View File

@ -1,6 +1,6 @@
[package]
name = "taskchampion-sync-server-core"
version = "0.7.0-pre"
version = "0.7.2-pre"
authors = ["Dustin J. Mitchell <dustin@mozilla.com>"]
edition = "2021"
description = "Core of sync protocol for TaskChampion"

View File

@ -43,7 +43,7 @@ services:
condition: service_completed_successfully
tss:
image: ghcr.io/gothenburgbitfactory/taskchampion-sync-server:0.6.1
image: ghcr.io/gothenburgbitfactory/taskchampion-sync-server:0.7.1
restart: unless-stopped
environment:
- "RUST_LOG=info"

View File

@ -2,9 +2,10 @@
- [Introduction](./introduction.md)
- [Usage](./usage.md)
- [Docker Compose](./usage/docker-compose.md)
- [Docker Images](./usage/docker-images.md)
- [Binaries](./usage/binaries.md)
- [Docker Images](./usage/docker-images.md)
- [Docker Compose](./usage/docker-compose.md)
- [Helm](./usage/helm.md)
- [Integration](./integration.md)
- [Pre-built Images](./integration/pre-built.md)
- [Rust Crates](./integration/crates.md)

View File

@ -10,16 +10,38 @@ One binary is provided for each storage backend:
- `taskchampion-sync-server` (SQLite)
- `taskchampion-sync-server-postgres` (Postgres)
### Building the Binary
This is a standard Rust project, and can be built with `cargo build --release`.
By default, only the SQLite binary is built. To also build the Postgres binary,
use
```none
cargo build --release --features postgres
```
To disable building the SQLite binary and build only the Postgres binary, use
```none
cargo build --release --no-default-features --features postgres
```
### Running the Binary
The server is configured with command-line options or environment variables.
See the `--help` output for full details.
For the SQLite binary, the `--data-dir` option or `DATA_DIR` environment
variable specifies where the server should store its data. For the Postgres
binary, the `--connection` option or `CONNECTION` environment variable
specifies the connection information, in the form of a [LibPQ-style connection
variable specifies where the server should store its data.
For the Postgres binary, the `--connection` option or `CONNECTION` environment
variable specifies the connection information, in the form of a [LibPQ-style
connection
URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).
Note that unlike LibPQ, the Rust client only supports `sslmode` values
`disable`, `prefer`, and `require`, and will always validate CA hostnames and
certificates when using TLS.
The remaining options are common to all binaries.
The `--listen` option specifies the interface and port the server listens on.

View File

@ -1,7 +1,7 @@
# Docker Compose
The
[`docker-compose.yml`](https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/refs/tags/v0.6.1/docker-compose.yml)
[`docker-compose.yml`](https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/refs/tags/v0.7.1/docker-compose.yml)
file in this repository is sufficient to run taskchampion-sync-server,
including setting up TLS certificates using Lets Encrypt, thanks to
[Caddy](https://caddyserver.com/). This setup uses the SQLite backend, which is

131
docs/src/usage/helm.md Normal file
View File

@ -0,0 +1,131 @@
# Helm
A Helm chart is available for deploying taskchampion-sync-server on Kubernetes.
## Adding the Repository
```sh
helm repo add taskchampion https://gothenburgbitfactory.org/taskchampion-sync-server
helm repo update
```
## Installing
```sh
# SQLite backend
helm install taskchampion-sync-server taskchampion/taskchampion-sync-server \
--set sqlite.enabled=true
# PostgreSQL backend
helm install taskchampion-sync-server taskchampion/taskchampion-sync-server \
--set postgres.enabled=true \
--set postgres.host=my-postgres \
--set postgres.db=taskchampion \
--set postgres.username=myuser \
--set postgres.password=mypassword
```
## Storage Backends
Exactly one storage backend must be enabled. The chart fails validation if
neither or both are enabled.
### SQLite
Mounts a volume at `sqlite.dataDir` (default `/var/lib/taskchampion-sync-server/data`).
The volume defaults to `emptyDir` but can be backed by a PVC or
existing PersistentVolumeClaim:
| Value | Description |
|-------|-------------|
| `sqlite.persistence.enabled` | Create a PVC (default: `false`) |
| `sqlite.existingPV` | Use an existing PVC by name |
| `sqlite.emptyDir` | emptyDir volume settings (default fallback) |
### PostgreSQL
Creates a Deployment with optional replicas, an auto-generated or existing
secret for the connection string, and an init container that waits for
PostgreSQL, applies the schema, and optionally seeds client IDs.
**Secret handling** — When `postgres.existingSecret` is empty (default), the
chart creates a secret named `{release-name}-connection` with a `conn` key.
When set, the chart reads the named secret. It accepts either a `conn` key
with a full [LibPQ-style URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS)
or individual fields (`host`, `port`, `username`, `password`, `database`) that
override the corresponding `postgres.*` values.
**Init container** — Enabled by default. Waits for PG readiness, downloads
the schema from `https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/v0.7.0/postgres/schema.sql`,
applies it, and seeds client IDs if `clientIdSecret` is set. Override the
schema URL with `postgres.initContainer.schemaUrl`.
**Replicas** — Replicas only apply with PostgreSQL:
`replicas.enabled=true`, `replicas.count=N`. SQLite is always single-replica.
## Secrets
### Client ID Secret
Optional. Restrict which client IDs the server accepts. Create a Secret with
comma-separated UUIDs (base64-encoded) under a `client-ids` key:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: my-client-ids
type: Opaque
data:
client-ids: <base64-encoded comma-separated UUIDs>
```
Reference it via `clientIdSecret: "my-client-ids"`. The value is available to
the server as `CLIENT_ID` and to the init container as `CLIENT_IDS`.
## Networking
The chart does not implement TLS. Terminate TLS at the ingress or gateway and
proxy HTTP to port 8080.
### Ingress (NGINX)
```yaml
ingress:
enabled: true
hosts:
- taskchampion.example.com
```
### HTTPRoute (Kubernetes Gateway API)
Use `parentRefs`, `hostnames`, and `rules`:
```yaml
httpRoute:
enabled: true
parentRefs:
- name: my-gateway
hostnames:
- tasks.example.com
rules:
- path:
type: PathPrefix
value: /
backendPort: 8080
```
The deprecated fields `httpRoute.gateway`, `httpRoute.host`,
`httpRoute.path`, and `httpRoute.port` are used as a fallback when the
structured arrays are empty.
### ServiceAccount and RBAC
When `serviceAccount.create` is `true` (default), the chart creates a
ServiceAccount, a Role with `get`/`create`/`update`/`patch` on secrets, and
a RoleBinding. Set `serviceAccount.name` to use an existing SA.
## Reference
See the chart's [values.yaml](https://github.com/GothenburgBitFactory/taskchampion-sync-server/blob/main/helm/taskchampion-sync-server/values.yaml)
for all configurable options.

View File

@ -0,0 +1,5 @@
# Patterns to ignore when building the Helm chart
.git
examples/
.DS_Store
*.tgz

View File

@ -0,0 +1,17 @@
apiVersion: v2
name: taskchampion-sync-server
description: A Helm chart for deploying TaskChampion Sync Server on Kubernetes
type: application
version: 0.2.1
appVersion: "0.7.0"
keywords:
- taskchampion
- taskwarrior
- sync
- task-management
home: https://github.com/GothenburgBitFactory/taskchampion-sync-server
sources:
- https://github.com/GothenburgBitFactory/taskchampion-sync-server
maintainers:
- name: Jansen Fuller
email: jansendfuller@mailfence.com

View File

@ -0,0 +1,138 @@
# TaskChampion Sync Server Helm Chart
Deploy the [TaskChampion Sync Server](https://github.com/GothenburgBitFactory/taskchampion-sync-server) on Kubernetes.
## Prerequisites
- Kubernetes 1.23+
- Helm 3+
## Installing
```console
helm repo add taskchampion https://gothenburgbitfactory.org/taskchampion-sync-server
helm repo update
helm install my-release taskchampion/taskchampion-sync-server --set sqlite.enabled=true
```
## Storage Backends
Exactly one storage backend must be enabled. The chart fails validation if neither or both are enabled.
### SQLite
| Parameter | Default | Description |
|-----------|---------|-------------|
| `sqlite.enabled` | `false` | Enable SQLite backend |
| `sqlite.dataDir` | `/var/lib/taskchampion-sync-server/data` | Data directory path |
| `sqlite.existingPV` | `""` | Use an existing PVC name |
| `sqlite.persistence.enabled` | `false` | Create a PVC |
| `sqlite.persistence.size` | `1Gi` | PVC size |
| `sqlite.persistence.accessMode` | `ReadWriteOnce` | PVC access mode |
| `sqlite.emptyDir` | — | emptyDir volume settings |
### PostgreSQL
| Parameter | Default | Description |
|-----------|---------|-------------|
| `postgres.enabled` | `false` | Enable PostgreSQL backend |
| `postgres.host` | `""` | PostgreSQL host |
| `postgres.port` | `5432` | PostgreSQL port |
| `postgres.db` | `taskchampion` | Database name |
| `postgres.username` | `""` | Database user |
| `postgres.password` | `""` | Database password |
| `postgres.sslMode` | `disable` | SSL mode |
| `postgres.existingSecret` | `""` | Use existing secret by name |
**Secret** — When `existingSecret` is empty (default), a secret named `{release-name}-connection` is created with a `conn` key. When set, the chart reads that secret. It accepts either a `conn` key with a full URI or individual keys (`host`, `port`, `username`, `password`, `database`) that override `postgres.*` values.
**Init container** — Enabled by default. Waits for PG readiness, downloads and applies the schema (from the chart's `appVersion` URL), and seeds client IDs if `clientIdSecret` is set. Override with `postgres.initContainer.schemaUrl`.
**Replicas** — Only apply with PostgreSQL (`replicas.enabled=true`, `replicas.count=N`). SQLite is single-replica.
## Secrets
### Client ID Secret
Restrict which client IDs the server accepts. Create a Secret with comma-separated UUIDs (base64-encoded) under a `client-ids` key:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: my-client-ids
type: Opaque
data:
client-ids: <base64-encoded comma-separated UUIDs>
```
Reference via `clientIdSecret: "my-client-ids"`.
## Networking
The chart does not implement TLS. Terminate TLS at the ingress or gateway.
### Service
| Parameter | Default | Description |
|-----------|---------|-------------|
| `service.type` | `ClusterIP` | Service type |
| `service.port` | `8080` | Service port |
| `service.targetPort` | `8080` | Container port |
### Ingress (NGINX)
| Parameter | Default | Description |
|-----------|---------|-------------|
| `ingress.enabled` | `false` | Enable NGINX ingress |
| `ingress.className` | `""` | Ingress class name |
| `ingress.annotations` | `{}` | Ingress annotations |
| `ingress.hosts` | `[]` | Host list |
| `ingress.tls` | `[]` | TLS configuration |
### HTTPRoute (Kubernetes Gateway API)
| Parameter | Default | Description |
|-----------|---------|-------------|
| `httpRoute.enabled` | `false` | Enable HTTPRoute |
| `httpRoute.parentRefs` | `[]` | Parent gateway references (primary) |
| `httpRoute.hostnames` | `[]` | Hostnames |
| `httpRoute.rules` | `[]` | Routing rules |
| `httpRoute.gateway` | `""` | (Deprecated) Single gateway name |
| `httpRoute.host` | `""` | (Deprecated) Single hostname |
| `httpRoute.path` | `"/"` | (Deprecated) Single path |
| `httpRoute.port` | `8080` | (Deprecated) Single port |
**Recommended** — use `parentRefs`, `hostnames`, `rules`. The deprecated
single-value fields (`gateway`, `host`, `path`, `port`) are used as a fallback
when the arrays are empty.
## ServiceAccount and RBAC
| Parameter | Default | Description |
|-----------|---------|-------------|
| `serviceAccount.create` | `true` | Create SA, Role, and RoleBinding |
| `serviceAccount.name` | `""` | Use existing SA name |
When created, the chart provisions a ServiceAccount, a Role with
`get`/`create`/`update`/`patch` on secrets, and a RoleBinding.
## Image Configuration
| Parameter | Default | Description |
|-----------|---------|-------------|
| `image.repo` | `ghcr.io/gothenburgbitfactory/taskchampion-sync-server` | Image repository |
| `image.tag` | `"0.7.0"` | Image tag |
| `image.pullPolicy` | `IfNotPresent` | Pull policy |
| `image.pullSecrets` | `[]` | Pull secrets |
PostgreSQL appends `-postgres` to the image repo automatically.
## Environment Variables
Custom env vars are passed via `env`. `DATA_DIR` (SQLite) and `conn`
(PostgreSQL) are set automatically and must not be set manually.
## Full Configuration
See [values.yaml](values.yaml).

View File

@ -0,0 +1,33 @@
sqlite:
enabled: false
postgres:
enabled: true
database: taskchampion
host: postgres-primary
username: taskchampion-user
clientIdSecret: "taskchampion-client-ids"
env:
- name: RUST_LOG
value: debug
- name: LISTEN
value: "0.0.0.0:8080"
- name: CREATE_CLIENTS
value: "false"
replicas:
enabled: true
count: 3
image:
pullSecrets:
- name: my-registry-secret
httpRoute:
enabled: true
gateway: "my-gateway"
host: "taskchampion.example.com"
path: "/"
port: 8080

View File

@ -0,0 +1,25 @@
sqlite:
enabled: true
existingPV: ""
emptyDir:
sizeLimit: 1Gi
persistence:
enabled: false
postgres:
enabled: false
clientIdSecret: "taskchampion-client-ids"
env:
- name: RUST_LOG
value: info
- name: LISTEN
value: "0.0.0.0:8080"
- name: CREATE_CLIENTS
value: "false"
ingress:
enabled: true
hosts:
- taskchampion.example.com

View File

@ -0,0 +1,46 @@
Thank you for installing {{ .Chart.Name }} — version {{ .Chart.Version }} (app: {{ .Chart.AppVersion }}).
## Storage Backend
{{- if eq .Values.sqlite.enabled true }}
**SQLite** — Data is stored at `{{ .Values.sqlite.dataDir }}`.
{{- if .Values.sqlite.persistence.enabled }}
PersistentVolumeClaim: `{{ include "taskchampion-sync-server.fullname" . }}-pvc`
{{- else if .Values.sqlite.existingPV }}
Using existing PVC: `{{ .Values.sqlite.existingPV }}`
{{- else }}
Using an emptyDir volume (ephemeral — data is lost on pod restart).
Set `sqlite.persistence.enabled=true` for persistent storage.
{{- end }}
{{- end }}
{{- if eq .Values.postgres.enabled true }}
**PostgreSQL** — Connection URI stored in Secret `{{ include "taskchampion-sync-server.postgres-secret-name" . }}`.
Host: {{ .Values.postgres.host }}:{{ .Values.postgres.port }}
Database: {{ .Values.postgres.database }}
{{- end }}
## Verify the Deployment
kubectl get pods -l {{ include "taskchampion-sync-server.selectorLabels" . | replace ": " "=" | replace "\n" "," | trimSuffix "," }}
## Check Pod Logs
kubectl logs -l {{ include "taskchampion-sync-server.selectorLabels" . | replace ": " "=" | replace "\n" "," | trimSuffix "," }}
## Test the API
kubectl port-forward svc/{{ include "taskchampion-sync-server.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }}
curl http://localhost:{{ .Values.service.port }}/
## View Connection Secret (PostgreSQL only)
{{- if eq .Values.postgres.enabled true }}
kubectl get secret {{ include "taskchampion-sync-server.postgres-secret-name" . }} -o jsonpath="{.data.connection}" | base64 -d
{{- end }}
## Configuration
For full configuration options, see:
https://github.com/GothenburgBitFactory/taskchampion-sync-server

View File

@ -0,0 +1,100 @@
{{- /*
taskchampion-sync-server helpers
*/ -}}
{{- define "taskchampion-sync-server.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "taskchampion-sync-server.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "taskchampion-sync-server.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
app.kubernetes.io/name: {{ include "taskchampion-sync-server.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: server
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "taskchampion-sync-server.selectorLabels" -}}
app.kubernetes.io/name: {{ include "taskchampion-sync-server.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "taskchampion-sync-server.postgres-connection" -}}
{{- $host := .Values.postgres.host -}}
{{- $port := .Values.postgres.port | toString -}}
{{- $username := .Values.postgres.username -}}
{{- $password := .Values.postgres.password -}}
{{- $database := .Values.postgres.database -}}
{{- /* Override individual fields from existingSecret where present */ -}}
{{- if .Values.postgres.existingSecret -}}
{{- $secret := lookup "v1" "Secret" .Release.Namespace .Values.postgres.existingSecret -}}
{{- if $secret -}}
{{- if index $secret.data "host" -}}
{{- $host = index $secret.data "host" | b64dec -}}
{{- end -}}
{{- if index $secret.data "port" -}}
{{- $port = index $secret.data "port" | b64dec -}}
{{- end -}}
{{- if index $secret.data "username" -}}
{{- $username = index $secret.data "username" | b64dec -}}
{{- end -}}
{{- if index $secret.data "password" -}}
{{- $password = index $secret.data "password" | b64dec -}}
{{- end -}}
{{- if index $secret.data "database" -}}
{{- $database = index $secret.data "database" | b64dec -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- /* Build URI */ -}}
{{- $uri := "postgresql://" -}}
{{- if ne $username "" -}}
{{- $uri = printf "%s%s" $uri $username -}}
{{- if ne $password "" -}}
{{- $uri = printf "%s:%s" $uri $password -}}
{{- end -}}
{{- $uri = printf "%s@" $uri -}}
{{- end -}}
{{- $uri = printf "%s%s" $uri $host -}}
{{- if ne $port "5432" -}}
{{- $uri = printf "%s:%s" $uri $port -}}
{{- end -}}
{{- $uri = printf "%s/%s" $uri $database -}}
{{- if .Values.postgres.sslMode -}}
{{- $uri = printf "%s?sslmode=%s" $uri .Values.postgres.sslMode -}}
{{- end -}}
{{- $uri -}}
{{- end -}}
{{- define "taskchampion-sync-server.schema-url" -}}
{{- if .Values.postgres.initContainer.schemaUrl -}}
{{- .Values.postgres.initContainer.schemaUrl -}}
{{- else -}}
{{- printf "https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/v%s/postgres/schema.sql" .Chart.AppVersion -}}
{{- end -}}
{{- end -}}
{{- define "taskchampion-sync-server.postgres-secret-name" -}}
{{- printf "%s-connection" .Release.Name -}}
{{- end -}}
{{- define "taskchampion-sync-server.serviceAccountName" -}}
{{- default (include "taskchampion-sync-server.fullname" .) .Values.serviceAccount.name -}}
{{- end -}}

View File

@ -0,0 +1,176 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "taskchampion-sync-server.fullname" . }}
labels:
{{- include "taskchampion-sync-server.labels" . | nindent 4 }}
spec:
{{- if and (eq .Values.postgres.enabled true) .Values.replicas.enabled }}
replicas: {{ .Values.replicas.count }}
{{- else }}
replicas: 1
{{- end }}
selector:
matchLabels:
{{- include "taskchampion-sync-server.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "taskchampion-sync-server.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.image.pullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.serviceAccount.create }}
serviceAccountName: {{ include "taskchampion-sync-server.serviceAccountName" . }}
{{- end }}
securityContext:
{{- toYaml .Values.securityContext | nindent 8 }}
{{- if and .Values.postgres.enabled .Values.postgres.initContainer.enabled }}
initContainers:
- name: postgres-init
image: "{{ .Values.postgres.initContainer.image }}"
imagePullPolicy: {{ .Values.postgres.initContainer.imagePullPolicy }}
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 999
env:
- name: PGURI
valueFrom:
secretKeyRef:
name: {{ include "taskchampion-sync-server.postgres-secret-name" . }}
key: connection
- name: SCHEMA_URL
value: {{ include "taskchampion-sync-server.schema-url" . | quote }}
{{- if .Values.clientIdSecret }}
- name: CLIENT_IDS
valueFrom:
secretKeyRef:
name: {{ .Values.clientIdSecret }}
key: client-ids
{{- end }}
command:
- sh
- -c
- |
set -e
until pg_isready -d "$PGURI"; do
echo 'Waiting for PostgreSQL...'
sleep 2
done
echo "Downloading schema from ${SCHEMA_URL}..."
wget -qO /tmp/schema.sql "$SCHEMA_URL" || {
echo 'Failed to download schema - continuing with main container'
exit 0
}
psql "$PGURI" -f /tmp/schema.sql || {
echo 'Schema execution failed (SQL error) - continuing with main container'
exit 0
}
echo 'Schema executed successfully'
if [ -n "$CLIENT_IDS" ]; then
echo "Inserting client IDs..."
IFS=','
for client_id in $CLIENT_IDS; do
client_id=$(echo "$client_id" | tr -d ' ')
[ -z "$client_id" ] && continue
psql "$PGURI" -c "INSERT INTO clients (client_id) VALUES ('$client_id') ON CONFLICT (client_id) DO NOTHING;" || {
echo "Failed to insert client $client_id - continuing"
}
done
unset IFS
echo "Client ID insertion complete"
fi
{{- end }}
containers:
- name: taskchampion-sync-server
{{- if eq .Values.postgres.enabled true }}
image: "{{ .Values.image.repository }}-postgres:{{ .Values.image.tag }}"
{{- else }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
{{- end }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1092
readOnlyRootFilesystem: true
{{- if eq .Values.postgres.enabled true }}
command:
- /bin/taskchampion-sync-server-postgres
{{- else }}
command:
- /bin/taskchampion-sync-server
{{- end }}
env:
{{- toYaml .Values.env | nindent 12 }}
{{- if .Values.clientIdSecret }}
- name: CLIENT_ID
valueFrom:
secretKeyRef:
name: {{ .Values.clientIdSecret }}
key: client-ids
{{- end }}
{{- if eq .Values.sqlite.enabled true }}
- name: DATA_DIR
value: {{ .Values.sqlite.dataDir }}
{{- end }}
{{- if eq .Values.postgres.enabled true }}
- name: CONNECTION
valueFrom:
secretKeyRef:
name: {{ include "taskchampion-sync-server.postgres-secret-name" . }}
key: connection
{{- end }}
ports:
- name: http
containerPort: {{ .Values.service.targetPort }}
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 10
{{- if eq .Values.postgres.enabled true }}
resources:
{{- toYaml .Values.postgres.resources | nindent 12 }}
{{- else }}
resources:
{{- toYaml .Values.sqlite.resources | nindent 12 }}
{{- end }}
{{- if eq .Values.sqlite.enabled true }}
volumeMounts:
- name: data
mountPath: {{ .Values.sqlite.dataDir }}
{{- end }}
{{- if eq .Values.sqlite.enabled true }}
volumes:
{{- if .Values.sqlite.existingPV }}
- name: data
persistentVolumeClaim:
claimName: {{ .Values.sqlite.existingPV }}
{{- else if .Values.sqlite.persistence.enabled }}
- name: data
persistentVolumeClaim:
claimName: {{ include "taskchampion-sync-server.fullname" . }}-pvc
{{- else }}
- name: data
emptyDir:
{{- if .Values.sqlite.emptyDir.sizeLimit }}
sizeLimit: {{ .Values.sqlite.emptyDir.sizeLimit }}
{{- end }}
{{- if .Values.sqlite.emptyDir.medium }}
medium: {{ .Values.sqlite.emptyDir.medium }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,57 @@
{{- if .Values.httpRoute.enabled }}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ include "taskchampion-sync-server.fullname" . }}
labels:
{{- include "taskchampion-sync-server.labels" . | nindent 4 }}
{{- with .Values.httpRoute.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
parentRefs:
{{- if .Values.httpRoute.parentRefs }}
{{- range .Values.httpRoute.parentRefs }}
- name: {{ .name }}
{{- if .namespace }}
namespace: {{ .namespace }}
{{- end }}
{{- if .sectionName }}
sectionName: {{ .sectionName }}
{{- end }}
{{- end }}
{{- else if .Values.httpRoute.gateway }}
- name: {{ .Values.httpRoute.gateway }}
{{- end }}
{{- $hostnames := .Values.httpRoute.hostnames }}
{{- if and (not $hostnames) .Values.httpRoute.host }}
{{- $hostnames = list .Values.httpRoute.host }}
{{- end }}
{{- if $hostnames }}
hostnames:
{{- range $hostnames }}
- {{ . | quote }}
{{- end }}
{{- end }}
rules:
{{- if .Values.httpRoute.rules }}
{{- range .Values.httpRoute.rules }}
- matches:
- path:
type: {{ .path.type | default "PathPrefix" }}
value: {{ .path.value | default "/" }}
backendRefs:
- name: {{ include "taskchampion-sync-server.fullname" $ }}
port: {{ .backendPort | default 8080 }}
{{- end }}
{{- else }}
- matches:
- path:
type: PathPrefix
value: {{ .Values.httpRoute.path | default "/" }}
backendRefs:
- name: {{ include "taskchampion-sync-server.fullname" . }}
port: {{ .Values.httpRoute.port | default 8080 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,58 @@
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "taskchampion-sync-server.fullname" . }}
labels:
{{- include "taskchampion-sync-server.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
rules:
{{- $svcName := include "taskchampion-sync-server.fullname" . -}}
{{- $svcPort := $.Values.service.port -}}
{{- range .Values.ingress.hosts }}
{{- if kindIs "string" . }}
- host: {{ . | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ $svcName }}
port:
number: {{ $svcPort }}
{{- else }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path | default "/" | quote }}
pathType: {{ .pathType | default "Prefix" }}
backend:
service:
name: {{ $svcName }}
port:
number: {{ $svcPort }}
{{- else }}
- path: /
pathType: Prefix
backend:
service:
name: {{ $svcName }}
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,17 @@
{{- if and (eq .Values.sqlite.enabled true) .Values.sqlite.persistence.enabled (not .Values.sqlite.existingPV) }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "taskchampion-sync-server.fullname" . }}-pvc
labels:
{{- include "taskchampion-sync-server.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.sqlite.persistence.accessMode }}
resources:
requests:
storage: {{ .Values.sqlite.persistence.size }}
{{- if .Values.sqlite.persistence.storageClass }}
storageClassName: {{ .Values.sqlite.persistence.storageClass }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,11 @@
{{- if .Values.postgres.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "taskchampion-sync-server.postgres-secret-name" . }}
labels:
{{- include "taskchampion-sync-server.labels" . | nindent 4 }}
type: Opaque
data:
connection: {{ include "taskchampion-sync-server.postgres-connection" . | b64enc }}
{{- end }}

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "taskchampion-sync-server.fullname" . }}
labels:
{{- include "taskchampion-sync-server.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
protocol: TCP
name: http
selector:
{{- include "taskchampion-sync-server.selectorLabels" . | nindent 4 }}

View File

@ -0,0 +1,9 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "taskchampion-sync-server.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "taskchampion-sync-server.labels" . | nindent 4 }}
{{- end }}

View File

@ -0,0 +1,14 @@
{{- /* Validate imagePullSecrets entries are objects (not plain strings) */ -}}
{{- range $i, $secret := .Values.image.pullSecrets -}}
{{- if not (kindIs "map" $secret) -}}
{{- fail (printf "ERROR: image.pullSecrets[%d] is a string (%q). Each entry must be an object with a 'name' key, e.g.\n image:\n pullSecrets:\n - name: %s" $i $secret $secret) -}}
{{- end -}}
{{- end -}}
{{- if and (eq .Values.sqlite.enabled false) (eq .Values.postgres.enabled false) -}}
{{- fail "ERROR: Exactly one storage backend must be enabled. Either sqlite.enabled or postgres.enabled must be true." -}}
{{- end -}}
{{- if and (eq .Values.sqlite.enabled true) (eq .Values.postgres.enabled true) -}}
{{- fail "ERROR: Only one storage backend can be enabled. Both sqlite.enabled and postgres.enabled cannot be true at the same time." -}}
{{- end -}}

View File

@ -0,0 +1,169 @@
# Override the chart name used in resource names
nameOverride: ""
# Override the full resource name (takes precedence over nameOverride)
fullnameOverride: ""
# Image configuration
image:
repository: ghcr.io/gothenburgbitfactory/taskchampion-sync-server
tag: "0.7.0"
pullPolicy: IfNotPresent
pullSecrets: []
# pullSecrets expects a list of objects with a "name" key:
# pullSecrets:
# - name: my-registry-cred
# Existing secret containing client IDs (comma-separated UUIDs)
# Expected key: client-ids
clientIdSecret: ""
# Environment variables passed directly to the container
# NOTE: DATA_DIR and CONNECTION are set automatically based on backend
# To add secret/configMap references, use valueFrom:
# - name: MY_SECRET_VAR
# valueFrom:
# secretKeyRef:
# name: my-secret
# key: my-key
env:
- name: RUST_LOG
value: info
- name: LISTEN
value: "0.0.0.0:8080"
- name: CREATE_CLIENTS
value: "true"
# Service configuration
service:
type: ClusterIP
port: 8080
targetPort: 8080
# Ingress configuration
# Each host can be a string (simple) or a map with path rules:
# hosts:
# - host: app.example.com
# paths:
# - path: /
# pathType: Prefix
# - path: /api
# pathType: Exact
ingress:
enabled: false
className: ""
annotations: {}
hosts: []
tls: []
# HTTPRoute configuration (Kubernetes Gateway API)
httpRoute:
enabled: false
annotations: {}
# List of parent gateway references.
# name is required; namespace and sectionName are optional.
parentRefs: []
# parentRefs:
# - name: my-gateway
# namespace: gateway-system # optional — cross-namespace gateway reference
# sectionName: https # optional — targets a specific listener on the gateway
# List of hostnames the route applies to.
hostnames: []
# hostnames:
# - tasks.example.com
# - tasks.internal.example.com
# List of routing rules. Each rule matches a path and forwards to this chart's Service.
# When empty, falls back to the deprecated path/port fields below.
rules: []
# rules:
# - path:
# type: PathPrefix # PathPrefix or Exact
# value: /
# backendPort: 8080
# Deprecated: use parentRefs instead
gateway: ""
# Deprecated: use hostnames instead
host: ""
# Deprecated: use rules instead
path: "/"
port: 8080
# Replica configuration (only applies when postgres is enabled)
replicas:
enabled: false
count: 1
# ServiceAccount configuration
# The app does not access the Kubernetes API, so no RBAC permissions are needed.
# A dedicated ServiceAccount is created to give the pod a stable identity
# for network policies, pod security, or future RBAC.
serviceAccount:
# create specifies whether a ServiceAccount should be created
create: true
# name sets the ServiceAccount name
name: taskchampion-sync-server
# Security context for the pod
# NOTE: runAsUser and runAsGroup are intentionally unset.
# The Docker entrypoint requires root to chown the data directory and then
# drops privileges via su-exec to the taskchampion user (uid 1092).
securityContext:
fsGroup: 100
# SQLite backend configuration (mutually exclusive with postgres)
sqlite:
enabled: false
dataDir: /var/lib/taskchampion-sync-server/data
# Resource limits and requests
resources:
limits:
memory: 25Mi
cpu: 100m
requests:
# 5Mi is sufficient for the SQLite image
memory: 5Mi
cpu: 10m
existingPV: ""
emptyDir:
sizeLimit: ""
medium: ""
persistence:
enabled: true
size: 1Gi
accessMode: ReadWriteOnce
storageClass: ""
existingClaim: ""
# PostgreSQL configuration
postgres:
enabled: false
existingSecret: "" # If empty, auto-create secret; if provided, use existing
# Individual connection components for building connection string
database: taskchampion
host: postgres
port: 5432
username: user
password: ""
# SSL mode for the PostgreSQL connection.
# Use 'disable' for internal cluster connections (no TLS).
# Options: disable, allow, prefer, require, verify-ca, verify-full
sslMode: disable
initContainer:
enabled: true
image: postgres:17-alpine
imagePullPolicy: IfNotPresent
# Override the schema URL. Defaults to the official schema for this chart's appVersion.
# e.g. https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/v0.7.0/postgres/schema.sql
schemaUrl: ""
# Resource limits and requests
resources:
limits:
memory: 100Mi
cpu: 100m
requests:
# 20Mi is the minimum for the Postgres image
memory: 20Mi
cpu: 10m

View File

@ -1,6 +1,6 @@
[package]
name = "taskchampion-sync-server-storage-postgres"
version = "0.7.0-pre"
version = "0.7.2-pre"
authors = ["Dustin J. Mitchell <dustin@v.igoro.us>"]
edition = "2021"
description = "Postgres backend for TaskChampion-sync-server"
@ -16,7 +16,7 @@ bb8.workspace = true
chrono.workspace = true
env_logger.workspace = true
log.workspace = true
taskchampion-sync-server-core = { path = "../core", version = "0.7.0-pre" }
taskchampion-sync-server-core = { path = "../core", version = "0.7.2-pre" }
thiserror.workspace = true
tokio-postgres.workspace = true
tokio.workspace = true

View File

@ -39,6 +39,26 @@ use uuid::Uuid;
#[cfg(test)]
mod testing;
/// An `ErrorSink` implementation that logs errors to the Rust log.
#[derive(Debug, Clone, Copy)]
pub struct LogErrorSink;
impl LogErrorSink {
fn new() -> Box<Self> {
Box::new(Self)
}
}
impl bb8::ErrorSink<tokio_postgres::Error> for LogErrorSink {
fn sink(&self, e: tokio_postgres::Error) {
log::error!("Postgres connection error: {e}");
}
fn boxed_clone(&self) -> Box<dyn bb8::ErrorSink<tokio_postgres::Error>> {
Self::new()
}
}
/// A storage backend which uses Postgres.
pub struct PostgresStorage {
pool: bb8::Pool<PostgresConnectionManager<MakeTlsConnector>>,
@ -49,7 +69,10 @@ impl PostgresStorage {
let connector = native_tls::TlsConnector::new()?;
let connector = postgres_native_tls::MakeTlsConnector::new(connector);
let manager = PostgresConnectionManager::new_from_stringlike(connection_string, connector)?;
let pool = bb8::Pool::builder().build(manager).await?;
let pool = bb8::Pool::builder()
.error_sink(LogErrorSink::new())
.build(manager)
.await?;
Ok(Self { pool })
}
}
@ -249,8 +272,13 @@ impl StorageTxn for Txn {
"UPDATE clients
SET latest_version_id = $1,
versions_since_snapshot = versions_since_snapshot + 1
WHERE client_id = $2 and latest_version_id = $3",
&[&version_id, &self.client_id, &parent_version_id],
WHERE client_id = $2 and (latest_version_id = $3 or latest_version_id = $4)",
&[
&version_id,
&self.client_id,
&parent_version_id,
&Uuid::nil(),
],
)
.await
.context("error updating latest_version_id")?;
@ -666,4 +694,22 @@ mod test {
})
.await
}
#[tokio::test]
/// When an add_version call specifies a `parent_version_id` that does not exist in the
/// DB, but no other versions exist, the call succeeds.
async fn test_add_version_no_history() -> anyhow::Result<()> {
with_db(async |connection_string, db_client| {
let storage = PostgresStorage::new(connection_string).await?;
let client_id = make_client(&db_client).await?;
let mut txn = storage.txn(client_id).await?;
let version_id = Uuid::new_v4();
let parent_version_id = Uuid::new_v4();
txn.add_version(version_id, parent_version_id, b"v1".to_vec())
.await?;
Ok(())
})
.await
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "taskchampion-sync-server"
version = "0.7.0-pre"
version = "0.7.2-pre"
authors = ["Dustin J. Mitchell <dustin@mozilla.com>"]
edition = "2021"
publish = false

View File

@ -1,6 +1,6 @@
[package]
name = "taskchampion-sync-server-storage-sqlite"
version = "0.7.0-pre"
version = "0.7.2-pre"
authors = ["Dustin J. Mitchell <dustin@mozilla.com>"]
edition = "2021"
description = "SQLite backend for TaskChampion-sync-server"
@ -9,7 +9,7 @@ repository = "https://github.com/GothenburgBitFactory/taskchampion-sync-server"
license = "MIT"
[dependencies]
taskchampion-sync-server-core = { path = "../core", version = "0.7.0-pre" }
taskchampion-sync-server-core = { path = "../core", version = "0.7.2-pre" }
async-trait.workspace = true
uuid.workspace = true
anyhow.workspace = true

View File

@ -276,11 +276,12 @@ impl StorageTxn for Txn {
SET
latest_version_id = ?,
versions_since_snapshot = versions_since_snapshot + 1
WHERE client_id = ? and latest_version_id = ?",
WHERE client_id = ? and (latest_version_id = ? or latest_version_id = ?)",
params![
StoredUuid(version_id),
StoredUuid(self.client_id),
StoredUuid(parent_version_id)
StoredUuid(parent_version_id),
StoredUuid(Uuid::nil())
],
)
.context("Error updating client for new version")?;
@ -489,4 +490,21 @@ mod test {
Ok(())
}
#[tokio::test]
/// When an add_version call specifies a `parent_version_id` that does not exist in the
/// DB, but no other versions exist, the call succeeds.
async fn test_add_version_no_history() -> anyhow::Result<()> {
let tmp_dir = TempDir::new()?;
let storage = SqliteStorage::new(tmp_dir.path())?;
let client_id = Uuid::new_v4();
let mut txn = storage.txn(client_id).await?;
txn.new_client(Uuid::nil()).await?;
let version_id = Uuid::new_v4();
let parent_version_id = Uuid::new_v4();
txn.add_version(version_id, parent_version_id, b"v1".to_vec())
.await?;
Ok(())
}
}