From 512901891a2cf304d2c71c9ad7522991c5835a48 Mon Sep 17 00:00:00 2001 From: MultiX0 Date: Fri, 4 Sep 2026 08:30:24 +0300 Subject: [PATCH 1/2] Pin the Flutter toolchain and give every CI job a timeout --- .github/workflows/ci.yml | 18 ++++++++++++++++++ .github/workflows/release.yml | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96ade76..64d83ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,12 @@ jobs: test: name: Build and test runs-on: ubuntu-latest + # every job carries one of these. GitHub's own default is six hours, which + # is not a timeout so much as a billing accident: a job that hangs runs all + # night and nobody hears about it until the morning. these numbers are + # roughly four times what the step actually takes, so a real slowdown still + # passes and a hang is reported while there is still a day left to fix it. + timeout-minutes: 15 steps: - uses: actions/checkout@v7 @@ -48,6 +54,7 @@ jobs: client: name: Client analyze and test runs-on: ubuntu-latest + timeout-minutes: 20 defaults: run: working-directory: localdrive @@ -56,6 +63,13 @@ jobs: - uses: subosito/flutter-action@v2 with: + # pinned for the same reason Go and Node are. `channel: stable` alone + # installs whatever shipped most recently, so the toolchain moves + # under the project between two runs of an unchanged commit. that is + # what broke this job: 3.47 landed, build_runner stopped terminating, + # and CI went from two minutes to the six hour ceiling without anyone + # touching the repository. bump this deliberately, not by waking up. + flutter-version: 3.44.9 channel: stable cache: true @@ -76,6 +90,7 @@ jobs: docs: name: Documentation and site build runs-on: ubuntu-latest + timeout-minutes: 15 defaults: run: working-directory: landing @@ -100,6 +115,7 @@ jobs: vulncheck: name: Vulnerability scan runs-on: ubuntu-latest + timeout-minutes: 15 steps: - uses: actions/checkout@v7 - uses: actions/setup-go@v7 @@ -115,6 +131,7 @@ jobs: image: name: Image build and scan runs-on: ubuntu-latest + timeout-minutes: 20 needs: test steps: - uses: actions/checkout@v7 @@ -137,6 +154,7 @@ jobs: cross-compile: name: The binary, for every target someone might run it on runs-on: ubuntu-latest + timeout-minutes: 15 strategy: matrix: include: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3379a4..f18ab25 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,6 +22,7 @@ jobs: server: name: Server (${{ matrix.name }}) runs-on: ubuntu-latest + timeout-minutes: 25 strategy: fail-fast: false matrix: @@ -75,6 +76,7 @@ jobs: android: name: Client (Android) runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v7 @@ -85,6 +87,11 @@ jobs: - uses: subosito/flutter-action@v2 with: + # kept in step with the CI workflow on purpose. an unpinned channel + # means the release artifacts are built by whichever toolchain was + # current that morning, so a tag cut twice does not produce the same + # binary and a broken Flutter release breaks publishing, not a PR. + flutter-version: 3.44.9 channel: stable cache: true @@ -164,11 +171,13 @@ jobs: windows-client: name: Client (Windows) runs-on: windows-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v7 - uses: subosito/flutter-action@v2 with: + flutter-version: 3.44.9 channel: stable cache: true @@ -215,11 +224,13 @@ jobs: linux-client: name: Client (Linux) runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v7 - uses: subosito/flutter-action@v2 with: + flutter-version: 3.44.9 channel: stable cache: true @@ -266,6 +277,7 @@ jobs: name: Publish needs: [server, android, windows-client, linux-client] runs-on: ubuntu-latest + timeout-minutes: 15 steps: - uses: actions/download-artifact@v8 with: From 30f4bd73a2971aab6d525a80ca4fa5f479a1f2f3 Mon Sep 17 00:00:00 2001 From: MultiX0 Date: Fri, 4 Sep 2026 08:40:30 +0300 Subject: [PATCH 2/2] Pin the Flutter toolchain, cap every job, and clear the image scan --- server/Dockerfile | 8 +++++++- server/go.mod | 2 +- server/go.sum | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index 49e0360..f8ab3f6 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -33,10 +33,16 @@ LABEL org.opencontainers.image.title="Local Drive" \ org.opencontainers.image.version="${VERSION}" \ org.opencontainers.image.licenses="MIT" +# the base image is a snapshot, so its packages are only as current as the day +# it was rebuilt. Alpine ships security fixes to the branch well before that +# happens, and without this upgrade the image carries whatever openssl the +# snapshot froze rather than the patched one sitting in the repository. +# # ffmpeg and poppler for thumbnails; the rest are the tools the drive helper # shells out to with fixed argument lists, and are only reachable in the # container that runs that mode -RUN apk add --no-cache \ +RUN apk upgrade --no-cache \ + && apk add --no-cache \ ffmpeg poppler-utils ca-certificates tzdata \ util-linux e2fsprogs e2fsprogs-extra xfsprogs btrfs-progs \ dosfstools exfatprogs ntfs-3g fuse3 \ diff --git a/server/go.mod b/server/go.mod index 3110708..4da3437 100644 --- a/server/go.mod +++ b/server/go.mod @@ -12,7 +12,7 @@ require ( github.com/pquerna/otp v1.5.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/tus/tusd/v2 v2.10.0 - golang.org/x/crypto v0.54.0 + golang.org/x/crypto v0.55.0 golang.org/x/image v0.45.0 golang.org/x/term v0.45.0 golang.org/x/time v0.15.0 diff --git a/server/go.sum b/server/go.sum index b15eab7..be09353 100644 --- a/server/go.sum +++ b/server/go.sum @@ -44,8 +44,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tus/tusd/v2 v2.10.0 h1:2yOGmkrDl9RQmRIt/00DR2WvYWOoiEu3CoygILb+WRw= github.com/tus/tusd/v2 v2.10.0/go.mod h1:T/OuJHIAC2NHpkEUyQyyaoWyDNRDcQVpJzWl8tX5GY4= -golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= -golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= +golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= golang.org/x/image v0.45.0 h1:FMb1nTbH5H9vF55SriQHgFw5GnNL9Jg6L25BwXKzhB0=