Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b5cc37ad4 | |||
| 3a169b2bcd | |||
| 50eb43971c | |||
| a08d6ce2c5 | |||
| 24d4fb5e55 | |||
| 8d34524aa0 | |||
| b254f6ea05 | |||
| 87270490de | |||
| f80e519349 | |||
| 9a4a53f487 | |||
| 32982228b0 |
@@ -0,0 +1,53 @@
|
||||
name: Release Binaries
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "[0-9]*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
steps:
|
||||
- name: Install build tools
|
||||
run: apk add --no-cache git gcc musl-dev
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: release-go-${{ hashFiles('go.sum') }}
|
||||
restore-keys: release-go-
|
||||
|
||||
- name: Install git-cliff
|
||||
run: |
|
||||
apk add --no-cache curl
|
||||
curl -sSL https://github.com/orhun/git-cliff/releases/latest/download/git-cliff-x86_64-unknown-linux-musl.tar.gz | tar xz
|
||||
mv git-cliff-*/git-cliff /usr/local/bin/
|
||||
git-cliff --version
|
||||
|
||||
- name: Generate release notes
|
||||
run: git-cliff --current --strip header -o /tmp/release-notes.md
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v7
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: "~> v2"
|
||||
args: release --clean --release-notes=/tmp/release-notes.md
|
||||
env:
|
||||
GORELEASER_FORCE_TOKEN: gitea
|
||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GITEA_API_URL: http://gitea:3000/api/v1
|
||||
@@ -0,0 +1,79 @@
|
||||
name: Release Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "[0-9]*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Image tag (e.g. 2026.06.1). Defaults to latest commit SHA."
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: docker-builder
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Resolve image tag
|
||||
id: meta
|
||||
run: |
|
||||
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
|
||||
echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
TAG="${{ github.event.inputs.tag }}"
|
||||
if [ -z "$TAG" ]; then
|
||||
TAG="${{ github.sha }}"
|
||||
fi
|
||||
else
|
||||
TAG="${{ github.ref_name }}"
|
||||
fi
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
sbom: true
|
||||
provenance: mode=max
|
||||
tags: |
|
||||
lerkolabs/uptop:${{ steps.meta.outputs.tag }}
|
||||
lerkolabs/uptop:latest
|
||||
lerkolabs/uptop:sha-${{ steps.meta.outputs.short_sha }}
|
||||
build-args: |
|
||||
VERSION=${{ steps.meta.outputs.tag }}
|
||||
COMMIT=${{ github.sha }}
|
||||
BUILD_DATE=${{ github.event.head_commit.timestamp }}
|
||||
|
||||
- name: Scan image for CVEs
|
||||
run: |
|
||||
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
|
||||
grype lerkolabs/uptop:${{ steps.meta.outputs.tag }} --fail-on critical --output table
|
||||
|
||||
- name: Update Docker Hub description
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
repository: lerkolabs/uptop
|
||||
|
||||
- name: Cleanup Docker artifacts
|
||||
if: always()
|
||||
run: |
|
||||
docker image prune -f
|
||||
docker builder prune -f --keep-storage=2GB
|
||||
@@ -1,75 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "[0-9]*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
steps:
|
||||
- name: Install build tools
|
||||
run: apk add --no-cache git gcc musl-dev
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: release-go-${{ hashFiles('go.sum') }}
|
||||
restore-keys: release-go-
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v7
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: "~> v2"
|
||||
args: release --clean
|
||||
env:
|
||||
GORELEASER_FORCE_TOKEN: gitea
|
||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GITEA_API_URL: http://gitea:3000/api/v1
|
||||
|
||||
docker:
|
||||
runs-on: docker-builder
|
||||
needs: [release]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
lerkolabs/uptop:${{ github.ref_name }}
|
||||
lerkolabs/uptop:latest
|
||||
build-args: |
|
||||
VERSION=${{ github.ref_name }}
|
||||
COMMIT=${{ github.sha }}
|
||||
BUILD_DATE=${{ github.event.head_commit.timestamp }}
|
||||
+2
-14
@@ -1,10 +1,3 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
||||
|
||||
### Go ###
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
@@ -24,16 +17,11 @@
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
||||
|
||||
/uptop
|
||||
/dist
|
||||
uptop.db*
|
||||
|
||||
.ssh
|
||||
|
||||
authorized_keys
|
||||
|
||||
tmp
|
||||
|
||||
*.local.json
|
||||
*.local.md
|
||||
*.local.md
|
||||
|
||||
+37
-6
@@ -33,10 +33,41 @@ archives:
|
||||
checksum:
|
||||
name_template: checksums.txt
|
||||
|
||||
nfpms:
|
||||
- package_name: uptop
|
||||
file_name_template: "{{ .ConventionalFileName }}"
|
||||
vendor: LerkoLabs
|
||||
homepage: https://gitea.lerkolabs.com/lerkolabs/uptop
|
||||
maintainer: Tyler Koenig <tyler@lerkolabs.com>
|
||||
description: Self-hosted uptime monitoring with a TUI over SSH
|
||||
license: MIT
|
||||
section: net
|
||||
priority: optional
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
bindir: /usr/bin
|
||||
contents:
|
||||
- src: ./LICENSE
|
||||
dst: /usr/share/doc/uptop/LICENSE
|
||||
type: doc
|
||||
|
||||
homebrew_casks:
|
||||
- name: uptop
|
||||
homepage: https://gitea.lerkolabs.com/lerkolabs/uptop
|
||||
description: Self-hosted uptime monitoring with a TUI over SSH
|
||||
directory: Casks
|
||||
skip_upload: true
|
||||
commit_msg_template: "update uptop to {{ .Tag }}"
|
||||
url:
|
||||
template: "https://gitea.lerkolabs.com/lerkolabs/uptop/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
|
||||
repository:
|
||||
owner: lerkolabs
|
||||
name: homebrew-tap
|
||||
git:
|
||||
url: "ssh://git@gitea.lerkolabs.com:2222/lerkolabs/homebrew-tap.git"
|
||||
private_key: "{{ if index .Env \"TAP_SSH_KEY\" }}{{ .Env.TAP_SSH_KEY }}{{ end }}"
|
||||
ssh_command: "ssh -o StrictHostKeyChecking=accept-new"
|
||||
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- "^docs:"
|
||||
- "^chore:"
|
||||
- "^style:"
|
||||
disable: true
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## [2026.06.1] — 2026-06-01
|
||||
|
||||
### Changed
|
||||
- Container runs as non-root user `uptop` (UID/GID 1000) instead of root (#44)
|
||||
- SSH host key relocated to `/data/.ssh/id_ed25519` for non-root compatibility (#44)
|
||||
- Release workflow prunes dangling images and build cache after Docker push (#44)
|
||||
|
||||
### Added
|
||||
- SBOM and provenance attestations on Docker images for supply chain compliance (#44)
|
||||
- Entrypoint script with volume writability check and migration guidance (#44)
|
||||
|
||||
### Breaking
|
||||
- Existing Docker volumes with root-owned files require migration before upgrading:
|
||||
`docker run --rm -v <volume>:/data alpine chown -R 1000:1000 /data`
|
||||
|
||||
## [2026.05.5] — 2026-05-29
|
||||
|
||||
### Added
|
||||
|
||||
+9
-6
@@ -1,5 +1,5 @@
|
||||
# --- Stage 1: Builder ---
|
||||
FROM golang:1.26-alpine3.23 AS builder
|
||||
FROM golang:1.26-alpine3.23@sha256:91eda9776261207ea25fd06b5b7fed8d397dd2c0a283e77f2ab6e91bfa71079d AS builder
|
||||
RUN apk add --no-cache gcc musl-dev
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum ./
|
||||
@@ -15,20 +15,23 @@ RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
go build -trimpath -ldflags="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${BUILD_DATE}" -o uptop ./cmd/uptop/main.go
|
||||
|
||||
# --- Stage 2: Runner ---
|
||||
FROM alpine:3.23
|
||||
FROM alpine:3.23@sha256:5b10f432ef3da1b8d4c7eb6c487f2f5a8f096bc91145e68878dd4a5019afde11
|
||||
WORKDIR /app
|
||||
RUN apk add --no-cache ca-certificates openssh-client
|
||||
RUN mkdir /data
|
||||
RUN apk add --no-cache ca-certificates && apk upgrade --no-cache
|
||||
RUN addgroup -g 1000 -S uptop && adduser -u 1000 -S uptop -G uptop
|
||||
RUN mkdir -p /data/.ssh && chown -R uptop:uptop /data
|
||||
|
||||
COPY --from=builder /app/uptop .
|
||||
COPY --chmod=755 docker-entrypoint.sh /usr/local/bin/
|
||||
|
||||
# Set Default Configuration via ENV
|
||||
# Docker users can override these in docker-compose.yml
|
||||
ENV LIPGLOSS_RENDERER_HAS_DARK_BACKGROUND=true
|
||||
ENV UPTOP_DB_TYPE=sqlite
|
||||
ENV UPTOP_DB_DSN=/data/uptop.db
|
||||
ENV UPTOP_KEYS=/data/authorized_keys
|
||||
ENV UPTOP_SSH_HOST_KEY=/data/.ssh/id_ed25519
|
||||
ENV UPTOP_PORT=23234
|
||||
|
||||
EXPOSE 23234
|
||||
USER uptop
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["./uptop"]
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
[changelog]
|
||||
header = """
|
||||
# Changelog\n
|
||||
"""
|
||||
body = """
|
||||
{% if version %}\
|
||||
## [{{ version }}] — {{ timestamp | date(format="%Y-%m-%d") }}
|
||||
{% else %}\
|
||||
## [Unreleased]
|
||||
{% endif %}\
|
||||
{% for group, commits in commits | group_by(attribute="group") %}
|
||||
### {{ group | striptags | trim }}
|
||||
{% for commit in commits %}
|
||||
- {{ commit.message | split(pat="\n") | first | trim }}\
|
||||
{% endfor %}
|
||||
{% endfor %}\n
|
||||
"""
|
||||
trim = true
|
||||
|
||||
[git]
|
||||
conventional_commits = true
|
||||
filter_unconventional = true
|
||||
split_commits = false
|
||||
protect_breaking_commits = false
|
||||
filter_commits = false
|
||||
tag_pattern = "[0-9]*"
|
||||
topo_order = false
|
||||
sort_commits = "oldest"
|
||||
|
||||
commit_parsers = [
|
||||
{ message = "^feat", group = "Added" },
|
||||
{ message = "^fix", group = "Fixed" },
|
||||
{ message = "^perf", group = "Changed" },
|
||||
{ message = "^refactor", group = "Changed" },
|
||||
{ message = "^security", group = "Security" },
|
||||
{ body = ".*security", group = "Security" },
|
||||
{ body = "BREAKING", group = "Breaking" },
|
||||
{ footer = "BREAKING.CHANGE", group = "Breaking" },
|
||||
{ message = "^docs", skip = true },
|
||||
{ message = "^style", skip = true },
|
||||
{ message = "^chore", skip = true },
|
||||
{ message = "^ci", skip = true },
|
||||
{ message = "^test", skip = true },
|
||||
{ message = "^build", skip = true },
|
||||
]
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ ! -w /data ]; then
|
||||
echo "ERROR: /data is not writable by uptop user (UID $(id -u))." >&2
|
||||
echo "" >&2
|
||||
echo "If upgrading from a previous version that ran as root:" >&2
|
||||
echo " docker run --rm -v <your_volume>:/data alpine chown -R 1000:1000 /data" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p /data/.ssh
|
||||
|
||||
exec "$@"
|
||||
@@ -53,7 +53,7 @@ require (
|
||||
golang.org/x/crypto v0.52.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||
golang.org/x/mod v0.35.0 // indirect
|
||||
golang.org/x/net v0.54.0 // indirect
|
||||
golang.org/x/net v0.55.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.45.0 // indirect
|
||||
golang.org/x/text v0.37.0 // indirect
|
||||
|
||||
@@ -107,8 +107,8 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
||||
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
|
||||
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
|
||||
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
|
||||
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
|
||||
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
Reference in New Issue
Block a user