From a8286f9ce2d3074c571b2487635e532b2cda415e Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Wed, 11 Feb 2026 11:34:27 -0500 Subject: [PATCH 1/6] fix: Fix gitea build & push image. --- .gitea/workflows/release.yaml | 9 +++++---- .github/workflows/release.yaml | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index 2ef3fc0..c5a710d 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -9,7 +9,8 @@ on: env: REGISTRY: git.housh.dev - IMAGE_NAME: ductcalc + USERNAME: michael + IMAGE_NAME: ${{ gitea.repository }} jobs: build-and-push-image: @@ -37,7 +38,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ env.USERNAME }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=semver,pattern={{version}} @@ -55,6 +56,6 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:build - cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.IMAGE_NAME }}:build + cache-from: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build + cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f8d27e1..87e3b83 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,6 +10,7 @@ on: env: REGISTRY: ghcr.io IMAGE_NAME: ductcalc + USERNAME: m-housh jobs: build-and-push-image: @@ -27,7 +28,7 @@ jobs: uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} - username: ${{ github.repository_owner }} + username: ${{ env.USERNAME }} password: ${{ secrets.CONTAINER_TOKEN }} - name: Set up Docker @@ -48,7 +49,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ env.USERNAME }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=semver,pattern={{version}} @@ -67,6 +68,6 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:buildcache - cache-to: type=registry,ref=${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:buildcache,mode=max + cache-from: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:buildcache + cache-to: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:buildcache,mode=max -- 2.49.1 From fbee56e4606e3be0b222991101c9be135403b601 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Wed, 11 Feb 2026 11:43:11 -0500 Subject: [PATCH 2/6] fix: Try without cache to ensure builds work. --- .gitea/workflows/release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index c5a710d..bcf0d7a 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -38,7 +38,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.USERNAME }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=semver,pattern={{version}} @@ -56,6 +56,6 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build - cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build + # cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:build + # cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.IMAGE_NAME }}:build -- 2.49.1 From 0f96c67058f75da7b802aa68de9e033210eed6b0 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Wed, 11 Feb 2026 11:56:29 -0500 Subject: [PATCH 3/6] fix: Try with inline cache mode. --- .gitea/workflows/release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index bcf0d7a..383ef33 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -38,7 +38,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ env.USERNAME }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=semver,pattern={{version}} @@ -56,6 +56,6 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - # cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:build - # cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.IMAGE_NAME }}:build + cache-from: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build + cache-to: mode=min,image-manifest=true,oci-mediatypes=true,type=inline,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build -- 2.49.1 From af4d4e393adc74140d79f013f025de8a030a8357 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Wed, 11 Feb 2026 12:05:18 -0500 Subject: [PATCH 4/6] fix: Try without inline cache. --- .gitea/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index 383ef33..c5a710d 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -57,5 +57,5 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build - cache-to: mode=min,image-manifest=true,oci-mediatypes=true,type=inline,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build + cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build -- 2.49.1 From f385fcdc28d9ed7b8d1473a7fb6c425280b76195 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Wed, 11 Feb 2026 12:15:46 -0500 Subject: [PATCH 5/6] fix: Reverts to inline on gitea, try non-inline on github. --- .gitea/workflows/release.yaml | 6 +++--- .github/workflows/release.yaml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index c5a710d..88d2e74 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -38,7 +38,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.USERNAME }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=semver,pattern={{version}} @@ -56,6 +56,6 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build - cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build + cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:build + cache-to: mode=min,image-manifest=true,oci-mediatypes=true,type=inline,ref=${{ env.IMAGE_NAME }}:build diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 87e3b83..0714770 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,7 +9,7 @@ on: env: REGISTRY: ghcr.io - IMAGE_NAME: ductcalc + IMAGE_NAME: ${{ github.repository }} USERNAME: m-housh jobs: @@ -69,5 +69,5 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:buildcache - cache-to: type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:buildcache,mode=max + cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.USERNAME }}/${{ env.IMAGE_NAME }}:build -- 2.49.1 From fe06508405938d8ea1297abf9e124c20ed6e8937 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Wed, 11 Feb 2026 16:44:39 -0500 Subject: [PATCH 6/6] feat: Store timestamps as strings in the database, which was causing postgres errors. --- .../Internal/ComponentLosses.swift | 4 +-- .../DatabaseClient/Internal/Equipment.swift | 4 +-- .../Internal/EquivalentLengths.swift | 4 +-- .../DatabaseClient/Internal/Migrations.swift | 2 +- .../DatabaseClient/Internal/Projects.swift | 4 +-- Sources/DatabaseClient/Internal/Rooms.swift | 4 +-- .../Internal/UserProfiles.swift | 4 +-- Sources/DatabaseClient/Internal/Users.swift | 8 ++--- Sources/ViewController/Views/Home.swift | 3 +- TODO.md | 1 + docker-compose.yaml | 31 +++++++++++++++++++ docker/docker-compose.yaml | 5 +-- 12 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 docker-compose.yaml diff --git a/Sources/DatabaseClient/Internal/ComponentLosses.swift b/Sources/DatabaseClient/Internal/ComponentLosses.swift index f936802..ee94719 100644 --- a/Sources/DatabaseClient/Internal/ComponentLosses.swift +++ b/Sources/DatabaseClient/Internal/ComponentLosses.swift @@ -66,8 +66,8 @@ extension ComponentPressureLoss { .id() .field("name", .string, .required) .field("value", .double, .required) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .field( "projectID", .uuid, .required, .references(ProjectModel.schema, "id", onDelete: .cascade) ) diff --git a/Sources/DatabaseClient/Internal/Equipment.swift b/Sources/DatabaseClient/Internal/Equipment.swift index 3a927c9..c43cd82 100644 --- a/Sources/DatabaseClient/Internal/Equipment.swift +++ b/Sources/DatabaseClient/Internal/Equipment.swift @@ -73,8 +73,8 @@ extension EquipmentInfo { .field("staticPressure", .double, .required) .field("heatingCFM", .int16, .required) .field("coolingCFM", .int16, .required) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .field( "projectID", .uuid, .required, .references(ProjectModel.schema, "id", onDelete: .cascade) ) diff --git a/Sources/DatabaseClient/Internal/EquivalentLengths.swift b/Sources/DatabaseClient/Internal/EquivalentLengths.swift index f076436..ddeada1 100644 --- a/Sources/DatabaseClient/Internal/EquivalentLengths.swift +++ b/Sources/DatabaseClient/Internal/EquivalentLengths.swift @@ -90,8 +90,8 @@ extension EquivalentLength { .field("type", .string, .required) .field("straightLengths", .array(of: .int)) .field("groups", .data) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .field( "projectID", .uuid, .required, .references(ProjectModel.schema, "id", onDelete: .cascade) ) diff --git a/Sources/DatabaseClient/Internal/Migrations.swift b/Sources/DatabaseClient/Internal/Migrations.swift index b5dd7ac..faf69b8 100644 --- a/Sources/DatabaseClient/Internal/Migrations.swift +++ b/Sources/DatabaseClient/Internal/Migrations.swift @@ -7,10 +7,10 @@ extension DatabaseClient.Migrations: DependencyKey { public static let liveValue = Self( all: { [ - Project.Migrate(), User.Migrate(), User.Token.Migrate(), User.Profile.Migrate(), + Project.Migrate(), ComponentPressureLoss.Migrate(), EquipmentInfo.Migrate(), Room.Migrate(), diff --git a/Sources/DatabaseClient/Internal/Projects.swift b/Sources/DatabaseClient/Internal/Projects.swift index f86cac5..cbb2f2d 100644 --- a/Sources/DatabaseClient/Internal/Projects.swift +++ b/Sources/DatabaseClient/Internal/Projects.swift @@ -120,8 +120,8 @@ extension Project { .field("state", .string, .required) .field("zipCode", .string, .required) .field("sensibleHeatRatio", .double) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .field("userID", .uuid, .required, .references(UserModel.schema, "id", onDelete: .cascade)) .unique(on: "userID", "name") .create() diff --git a/Sources/DatabaseClient/Internal/Rooms.swift b/Sources/DatabaseClient/Internal/Rooms.swift index 38115f7..47507b7 100644 --- a/Sources/DatabaseClient/Internal/Rooms.swift +++ b/Sources/DatabaseClient/Internal/Rooms.swift @@ -197,8 +197,8 @@ extension Room { .field("registerCount", .int8, .required) .field("delegatedToID", .uuid, .references(RoomModel.schema, "id")) .field("rectangularSizes", .array) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .field( "projectID", .uuid, .required, .references(ProjectModel.schema, "id", onDelete: .cascade) ) diff --git a/Sources/DatabaseClient/Internal/UserProfiles.swift b/Sources/DatabaseClient/Internal/UserProfiles.swift index 1cbbc2c..890fa88 100644 --- a/Sources/DatabaseClient/Internal/UserProfiles.swift +++ b/Sources/DatabaseClient/Internal/UserProfiles.swift @@ -81,8 +81,8 @@ extension User.Profile { .field("zipCode", .string, .required) .field("theme", .string) .field("userID", .uuid, .references(UserModel.schema, "id", onDelete: .cascade)) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .unique(on: "userID") .create() } diff --git a/Sources/DatabaseClient/Internal/Users.swift b/Sources/DatabaseClient/Internal/Users.swift index bb539a2..e90197a 100644 --- a/Sources/DatabaseClient/Internal/Users.swift +++ b/Sources/DatabaseClient/Internal/Users.swift @@ -76,8 +76,8 @@ extension User { .id() .field("email", .string, .required) .field("password_hash", .string, .required) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .unique(on: "email") .create() } @@ -97,8 +97,8 @@ extension User.Token { .id() .field("value", .string, .required) .field("user_id", .uuid, .required, .references(UserModel.schema, "id")) - .field("createdAt", .datetime) - .field("updatedAt", .datetime) + .field("createdAt", .string) + .field("updatedAt", .string) .unique(on: "value") .create() } diff --git a/Sources/ViewController/Views/Home.swift b/Sources/ViewController/Views/Home.swift index bf4462a..4857996 100644 --- a/Sources/ViewController/Views/Home.swift +++ b/Sources/ViewController/Views/Home.swift @@ -63,7 +63,8 @@ struct HomeView: HTML, Sendable { .class("btn btn-xl btn-primary mt-6"), .hx.get(route: .signup(.index)), .hx.target("body"), - .hx.swap(.outerHTML) + .hx.swap(.outerHTML), + .hx.pushURL(true) ) { "Get Started" } diff --git a/TODO.md b/TODO.md index 1caaa1e..a30798e 100644 --- a/TODO.md +++ b/TODO.md @@ -23,3 +23,4 @@ - [x] Privacy policy - [ ] Update README - [ ] Self hosting documentation +- [x] Check signup flow when using 'get-started' button from home page, it may need a push url. diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..dd980b5 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,31 @@ +services: + db: + image: docker.io/postgres:18 + restart: unless-stopped + env_file: .env + volumes: + - ./data:/var/lib/postgresql + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ductcalc"] + interval: 5s + timeout: 5s + retries: 5 + + app: + build: + dockerfile: docker/Dockerfile + context: . + restart: unless-stopped + env_file: .env + environment: + - POSTGRES_HOSTNAME=db + depends_on: + db: + condition: healthy + ports: + - 8081:8080 + healthcheck: + test: curl --fail --silent http://0.0.0.0:8080/health || exit 1 + interval: 1m + timeout: 10s + retries: 3 diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 5f7dd35..3ac1145 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -1,4 +1,3 @@ - services: db: image: docker.io/postgres:18 @@ -8,7 +7,9 @@ services: - ./data:/var/lib/postgresql app: - image: ghcr.io/m-housh/ductcalc:latest + build: + dockerfile: docker/Dockerfile + context: . restart: unless-stopped env_file: .env depends_on: -- 2.49.1