1 Commits
Author SHA1 Message Date
Joachim Schlöffel 666347b10f upgrade seaweedfs to 4.41 and patch gitea's new checksum
Build Alpine Packages / build-and-publish (v3.24, 3.24) (pull_request) Failing after 34m0s
2026-08-13 10:59:39 +02:00
77 changed files with 658 additions and 2057 deletions
+50 -145
View File
@@ -1,43 +1,47 @@
name: Build Alpine Packages
on:
schedule:
- cron: "17 5 * * 1"
push:
branches:
- master
- main
tags:
- "*"
pull_request:
workflow_dispatch:
env:
ALPINE_VERSION: "3.24"
ALPINE_ARCHES: "x86_64 aarch64"
ALPINE_REGISTRY_BRANCH: "v3.24"
ALPINE_REGISTRY_REPOSITORY: "${{ vars.PACKAGE_NAME }}"
INSTANCE_URL: "${{ vars.INSTANCE_URL }}"
PACKAGE_OWNER: "${{ vars.PACKAGE_OWNER }}"
PACKAGE_USER: "${{ secrets.PACKAGE_USER }}"
PACKAGE_TOKEN: "${{ secrets.PACKAGE_TOKEN }}"
PACKAGER: "${{ gitea.repository_owner }}"
ALPINE_RUST_CACHE_ROOT: "/cache/public-alpine-packages/v3.24/rust"
TRIVY_VERSION: "0.74.0"
TRIVY_SHA256: "2ae6fe3ee734b7fdf11335663e18c75ea12dccc76062f09f164a3b0f8be4371a"
jobs:
preflight:
build-and-publish:
runs-on: ubuntu-latest
timeout-minutes: 180
strategy:
matrix:
include:
- alpine_version: "3.24"
alpine_registry_branch: "v3.24"
container:
image: "alpine:3.24"
outputs:
packages_selected: "${{ steps.package-selection.outputs.packages_selected }}"
selected_packages: "${{ steps.package-selection.outputs.selected_packages }}"
greptimedb_selected: "${{ steps.package-selection.outputs.greptimedb_selected }}"
image: "alpine:${{ matrix.alpine_version }}"
env:
ALPINE_VERSION: "${{ matrix.alpine_version }}"
ALPINE_ARCHES: "x86_64 aarch64"
ALPINE_REGISTRY_BRANCH: "${{ matrix.alpine_registry_branch }}"
ALPINE_REGISTRY_REPOSITORY: "${{ vars.PACKAGE_NAME }}"
INSTANCE_URL: "${{ vars.INSTANCE_URL }}"
PACKAGE_OWNER: "${{ vars.PACKAGE_OWNER }}"
PACKAGE_USER: "${{ secrets.PACKAGE_USER }}"
PACKAGE_TOKEN: "${{ secrets.PACKAGE_TOKEN }}"
PACKAGER: "${{ gitea.repository_owner }}"
ALPINE_APK_REPO_CACHE: "/cache/public-alpine-packages/${{ matrix.alpine_registry_branch }}/apk-repo"
CARGO_HOME: "/cache/public-alpine-packages/${{ matrix.alpine_registry_branch }}/greptimedb/cargo"
RUSTUP_HOME: "/cache/public-alpine-packages/${{ matrix.alpine_registry_branch }}/greptimedb/rustup"
CARGO_TARGET_DIR: "/cache/public-alpine-packages/${{ matrix.alpine_registry_branch }}/greptimedb/target"
steps:
- name: Prepare Environment
run: |
printf '%s\n' 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk add --no-cache --update atools-apkbuild-lint bash ca-certificates curl git jq nodejs shellcheck tar
apk add --no-cache --update abuild-rootbld alpine-sdk atools-apkbuild-lint bash ca-certificates curl doas git nodejs rsync shellcheck sudo tar
mkdir -p "$ALPINE_APK_REPO_CACHE" "$CARGO_HOME" "$RUSTUP_HOME" "$CARGO_TARGET_DIR"
chown -R 1000:1000 /cache/public-alpine-packages/${{ matrix.alpine_registry_branch }}
- name: Checkout
uses: actions/checkout@v3
@@ -59,142 +63,43 @@ jobs:
fi
- name: Prepare package cache
id: package-selection
run: scripts/apk/ci-package-cache.sh prepare
- name: Validate selected package matrix
if: github.event_name != 'schedule'
run: |
for package in ${ALPINE_PACKAGES}; do
case "${package}" in
seaweedfs|greptimedb|lavinmq|gitea|nifi|rclone-openrc) ;;
*)
printf 'selected package is missing from the CI build matrix: %s\n' "${package}" >&2
exit 1
;;
esac
done
scripts/apk/ci-package-cache.sh prepare
build:
needs: preflight
if: needs.preflight.outputs.packages_selected == 'true'
runs-on: ubuntu-latest
timeout-minutes: 180
strategy:
fail-fast: false
matrix:
package: [seaweedfs, greptimedb, lavinmq, gitea, nifi, rclone-openrc]
container:
image: "alpine:3.24"
env:
ALPINE_PACKAGE: "${{ matrix.package }}"
steps:
- name: Prepare Environment
run: |
printf '%s\n' 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk add --no-cache --update abuild-rootbld alpine-sdk bash ca-certificates doas git nodejs sudo
mkdir -p "$ALPINE_RUST_CACHE_ROOT"
chown -R 1000:1000 /cache/public-alpine-packages/v3.24
- name: Checkout
uses: actions/checkout@v3
- name: Build package
if: contains(needs.preflight.outputs.selected_packages, matrix.package)
- name: Build packages
if: github.event_name != 'schedule'
run: |
scripts/apk/ci-build.sh
scripts/apk/ci-package-cache.sh sync
scripts/apk/export-ci-assets.sh
scripts/apk/list-packages.sh
- name: Check artifact upload support
if: contains(needs.preflight.outputs.selected_packages, matrix.package)
if: github.event_name != 'schedule'
id: artifact-upload
run: |
test -n "${ACTIONS_RUNTIME_TOKEN:-}" || {
echo "artifact upload support is required for split package builds" >&2
exit 1
}
- name: Upload package artifacts
if: contains(needs.preflight.outputs.selected_packages, matrix.package)
uses: actions/upload-artifact@v3
with:
name: alpine-package-${{ matrix.package }}-${{ github.sha }}
path: packages/local/
retention-days: 1
verify-and-publish:
needs: [preflight, build]
if: needs.preflight.outputs.packages_selected == 'true'
runs-on: ubuntu-latest
timeout-minutes: 180
container:
image: "alpine:3.24"
env:
ALPINE_PACKAGES: "${{ needs.preflight.outputs.selected_packages }}"
steps:
- name: Prepare Environment
run: |
printf '%s\n' 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk add --no-cache --update abuild-rootbld alpine-sdk bash ca-certificates curl doas docker-cli git jq nodejs rsync shellcheck sudo tar
trivy_archive="trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz"
curl -fsSL -o "/tmp/${trivy_archive}" "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/${trivy_archive}"
echo "${TRIVY_SHA256} /tmp/${trivy_archive}" | sha256sum -c -
tar -xzf "/tmp/${trivy_archive}" -C /usr/local/bin trivy
- name: Checkout
uses: actions/checkout@v3
- name: Prepare registry fallback
run: |
selected_packages="$ALPINE_PACKAGES"
scripts/apk/ci-package-cache.sh prepare
printf 'ALPINE_PACKAGES=%s\n' "$selected_packages" >> "$GITHUB_ENV"
- name: Download package artifacts
uses: actions/download-artifact@v3
with:
path: packages/worker-artifacts
- name: Merge package artifacts
run: scripts/apk/merge-ci-artifacts.sh
- name: Export GreptimeDB CI assets
if: needs.preflight.outputs.greptimedb_selected == 'true'
run: scripts/apk/export-ci-assets.sh
- name: Upload generated CI assets
if: needs.preflight.outputs.greptimedb_selected == 'true'
uses: actions/upload-artifact@v3
with:
name: greptimedb-musl-binaries-v3.24
path: packages/ci-assets/
- name: Upload local Alpine registry
uses: actions/upload-artifact@v3
with:
name: alpine-local-registry-v3.24-${{ github.sha }}
path: packages/local/
retention-days: 30
- name: Smoke test
run: scripts/apk/ci-smoke.sh
- name: Generate security reports
run: |
scripts/apk/security-report.sh
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
find packages/security-reports -name summary.md -type f -print | sort | while IFS= read -r summary; do
cat "$summary"
done >> "$GITHUB_STEP_SUMMARY"
if [ -n "${ACTIONS_RUNTIME_TOKEN:-}" ]; then
echo "available=true" >> "$GITHUB_OUTPUT"
else
echo "available=false" >> "$GITHUB_OUTPUT"
fi
- name: Upload security reports
- name: Upload generated CI assets
if: github.event_name != 'schedule' && steps.artifact-upload.outputs.available == 'true'
uses: actions/upload-artifact@v3
with:
name: apk-security-reports-v3.24
path: packages/security-reports/
name: greptimedb-musl-binaries-${{ matrix.alpine_registry_branch }}
path: packages/ci-assets/
- name: Smoke test
if: github.event_name != 'schedule'
run: scripts/apk/ci-smoke.sh
- name: Runtime test
run: ALPINE_RUNTIME_TEST_MODE=docker scripts/apk/runtime-test.sh
if: github.event_name != 'schedule'
run: scripts/apk/runtime-test.sh
- name: Publish Alpine packages
if: github.ref == 'refs/heads/main'
if: github.event_name != 'pull_request' && github.event_name != 'schedule'
run: scripts/apk/publish-gitea.sh
-5
View File
@@ -1,11 +1,6 @@
.cache/
.vscode/
packages/
packaging/alpine/*/*/pkg/
packaging/alpine/*/*/src/
packaging/alpine/*/*/tmp/
packaging/alpine/*/*/*.apk
packaging/alpine/*/*/*.tar.*
!packaging/alpine/*/*/*-vendor.tar.gz
!packaging/alpine/local/lavinmq/lavinmq-*-shards.tar.gz
!packaging/alpine/local/lavinmq/lavinmq-*-assets.tar.gz
+7 -30
View File
@@ -19,12 +19,10 @@ https://code.factoring.digital/api/packages/public/alpine/v3.24/alpine-packages
| Package | APK Name | Package Version | Package Type | Purpose |
|-----------------------------------------------------------|--------------|-----------------|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| [SeaweedFS](packaging/alpine/local/seaweedfs/README.md) | `seaweedfs` | `4.48` | Binary repackaging of official upstream release tarballs | Ships current SeaweedFS features with Alpine OpenRC role splits. |
| [GreptimeDB](packaging/alpine/local/greptimedb/README.md) | `greptimedb` | `1.2.1` | Source build from upstream release | Provides a current GreptimeDB build and component OpenRC packages before it is available from Alpine community. |
| [LavinMQ](packaging/alpine/local/lavinmq/README.md) | `lavinmq` | `2.10.1` | Source build from upstream release | Provides a current LavinMQ build on Alpine 3.24 with matching Crystal support. |
| [Gitea](packaging/alpine/local/gitea/README.md) | `gitea` | `28.2.0` | Binary repackaging of official upstream release binaries | Ships current Gitea releases with the expected Alpine runtime layout and OpenRC service. |
| [Apache NiFi](packaging/alpine/local/nifi/README.md) | `nifi` | `2.12.0` | Binary repackaging of the official Standard distribution | Provides Apache NiFi 2 with a secure default configuration and OpenRC service. |
| [rclone OpenRC](packaging/alpine/local/rclone-openrc/README.md) | `rclone-openrc` | `0.1.0` | OpenRC integration for Alpine's rclone package | Provides reusable, instance-capable OpenRC supervision for rclone commands. |
| [SeaweedFS](packaging/alpine/local/seaweedfs/README.md) | `seaweedfs` | `4.40` | Binary repackaging of official upstream release tarballs | Ships current SeaweedFS features with Alpine OpenRC role splits. |
| [GreptimeDB](packaging/alpine/local/greptimedb/README.md) | `greptimedb` | `1.1.4` | Source build from upstream release | Provides a current GreptimeDB build and component OpenRC packages before it is available from Alpine community. |
| [LavinMQ](packaging/alpine/local/lavinmq/README.md) | `lavinmq` | `2.9.1` | Source build from upstream release | Provides a current LavinMQ build on Alpine 3.24 with matching Crystal support. |
| [Gitea](packaging/alpine/local/gitea/README.md) | `gitea` | `1.27.0` | Binary repackaging of official upstream release binaries | Ships current Gitea releases with the expected Alpine runtime layout and OpenRC service. |
## Use In Production
@@ -94,8 +92,7 @@ apk:lint-shell Run ShellCheck for packaging automation
apk:packages List built Alpine packages and dependencies
apk:publish-check Run lint, multi-arch build, package listing, and smoke test
apk:publish-gitea Publish built packages to the Gitea Alpine package registry
apk:outdated Check packaged upstream versions and release summaries
apk:security-report Generate Trivy and CycloneDX reports for built packages
apk:outdated Check packaged upstream versions against latest GitHub releases
apk:shell Open an Alpine package build shell in Docker
apk:smoke Install-test built packages from the local repository in Docker
apk:test-install Test README installation instructions in a fresh Alpine container
@@ -169,9 +166,6 @@ weed version
apk add greptimedb greptimedb-docs greptimedb-standalone-openrc
greptime --version
apk add rclone-openrc
rclone version
```
Run package-local runtime tests:
@@ -237,27 +231,10 @@ versions fail the command:
APK_UPDATE_CHECK_MODE=fail mise run apk:outdated
```
When an update is available, the command also lists compact release-note
summaries for every release between the packaged and latest versions.
### Security Reports and Roadmap
The [project review and development roadmap](docs/project-review.md) tracks
release-reliability goals. Generate advisory Trivy and CycloneDX reports for
built packages with:
```sh
ALPINE_PACKAGE=seaweedfs mise run apk:security-report
```
Reports are written to `packages/security-reports/` and are uploaded by CI for
each selected package build. Local runs scan the newest compatible package set
available in the signed local repository.
### Gitea Workflow
The smoke test installs rebuilt artifacts from the local repository and uses
the published registry as a fallback for unchanged packages.
`.gitea/workflows/build.yml` builds and publishes `v3.24`. Pull requests
build only.
Repository variables:
-44
View File
@@ -1,44 +0,0 @@
# Project Review and Development Roadmap
## Current State
This repository packages four upstream services for Alpine 3.24, with source
builds, binary repackages, OpenRC integration, Docker-based local builds, and
CI publication to the Gitea Alpine registry. Package selection avoids rebuilding
unchanged versions already present in the registry.
The main release risks are missing retained build artifacts, permissive duplicate
publish handling, rolling toolchain inputs, and limited end-to-end service
validation. Documentation and test defaults must remain synchronized with each
`APKBUILD` version.
## Prioritized Goals
1. **Reproducible, auditable releases.** Split build and publish work so publish
consumes a retained APK artifact plus a checksum manifest; verify registry
contents after upload and reject mismatched duplicate versions.
2. **Build security visibility.** Generate an installed-rootfs CycloneDX SBOM
and advisory Trivy report for every package and architecture selected by CI.
Retain reports as Gitea workflow artifacts.
3. **Service-level confidence.** Add bounded readiness checks for Gitea,
LavinMQ, and GreptimeDB; retain SeaweedFS role startup coverage.
4. **Automation correctness.** Add fixture-based tests for package selection,
APKINDEX parsing, metadata/version drift, and registry error paths.
5. **Developer feedback and cost.** Record build durations/cache outcomes,
keep package-scoped validation, and add a scheduled update-report workflow.
## Security Reports
`mise run apk:security-report` scans the installed root filesystem for each
selected local package. It writes advisory reports under:
```text
packages/security-reports/<package>/<architecture>/
├── trivy.json
├── sbom.cdx.json
└── summary.md
```
The scan includes the package, its selected subpackages, and resolved runtime
dependencies from the signed local repository. Findings do not block a build yet; report generation,
package installation, and report validation do.
-140
View File
@@ -1,140 +0,0 @@
# @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html
lockfile_version = 1
[[tools.act]]
version = "0.2.89"
backend = "aqua:nektos/act"
specifiers = ["latest"]
[tools.act."platforms.linux-arm64"]
checksum = "sha256:daa8679ba9615a74d2d0cec321dc593f21948a2a11bb65862b063d8b930f4bcb"
url = "https://github.com/nektos/act/releases/download/v0.2.89/act_Linux_arm64.tar.gz"
url_api = "https://api.github.com/repos/nektos/act/releases/assets/434891274"
[tools.act."platforms.linux-arm64-musl"]
checksum = "sha256:daa8679ba9615a74d2d0cec321dc593f21948a2a11bb65862b063d8b930f4bcb"
url = "https://github.com/nektos/act/releases/download/v0.2.89/act_Linux_arm64.tar.gz"
url_api = "https://api.github.com/repos/nektos/act/releases/assets/434891274"
[tools.act."platforms.linux-x64"]
checksum = "sha256:0191d6f1f3b716b5c55820032605d05fc3c1cdbf581ebeff655019e5dd1524c0"
url = "https://github.com/nektos/act/releases/download/v0.2.89/act_Linux_x86_64.tar.gz"
url_api = "https://api.github.com/repos/nektos/act/releases/assets/434891246"
[tools.act."platforms.linux-x64-musl"]
checksum = "sha256:0191d6f1f3b716b5c55820032605d05fc3c1cdbf581ebeff655019e5dd1524c0"
url = "https://github.com/nektos/act/releases/download/v0.2.89/act_Linux_x86_64.tar.gz"
url_api = "https://api.github.com/repos/nektos/act/releases/assets/434891246"
[tools.act."platforms.macos-arm64"]
checksum = "sha256:48ae218af96725f7635a66de2b87e1e346893b02add0f16b92f560296b2151fc"
url = "https://github.com/nektos/act/releases/download/v0.2.89/act_Darwin_arm64.tar.gz"
url_api = "https://api.github.com/repos/nektos/act/releases/assets/434891257"
[tools.act."platforms.macos-x64"]
checksum = "sha256:41b31488e7c254baec31cce12c7dade3e35973b8a31b9486206ad43f233d814e"
url = "https://github.com/nektos/act/releases/download/v0.2.89/act_Darwin_x86_64.tar.gz"
url_api = "https://api.github.com/repos/nektos/act/releases/assets/434891248"
[tools.act."platforms.windows-x64"]
checksum = "sha256:0f8cf866ad7e32421a219fc551a0a0ea5d12ead464de12ebfeafd334a5973b50"
url = "https://github.com/nektos/act/releases/download/v0.2.89/act_Windows_x86_64.zip"
url_api = "https://api.github.com/repos/nektos/act/releases/assets/434891261"
[[tools.docker-cli]]
version = "29.9.1"
backend = "aqua:docker/cli"
specifiers = ["latest"]
[[tools.jq]]
version = "1.8.2"
backend = "aqua:jqlang/jq"
specifiers = ["latest"]
[tools.jq."platforms.linux-arm64"]
checksum = "sha256:8b85c817833814ddca00a144c33705546355afccf0cf39b188f3cdb48b852309"
url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-arm64"
url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012756"
provenance = "github-attestations"
[tools.jq."platforms.linux-arm64-musl"]
checksum = "sha256:8b85c817833814ddca00a144c33705546355afccf0cf39b188f3cdb48b852309"
url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-arm64"
url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012756"
provenance = "github-attestations"
[tools.jq."platforms.linux-x64"]
checksum = "sha256:b1c22172dd303f3be49e935aa56aa48a8b7a46e0bc838b4997d3bb451495870f"
url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-amd64"
url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012752"
provenance = "github-attestations"
[tools.jq."platforms.linux-x64-musl"]
checksum = "sha256:b1c22172dd303f3be49e935aa56aa48a8b7a46e0bc838b4997d3bb451495870f"
url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-amd64"
url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012752"
provenance = "github-attestations"
[tools.jq."platforms.macos-arm64"]
checksum = "sha256:2d75340ba57a4b4b4c8708a21c2dc8e958a48aaa8bba13b27f77f6e4c0eca07e"
url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-macos-arm64"
url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012783"
provenance = "github-attestations"
[tools.jq."platforms.macos-x64"]
checksum = "sha256:e94b266e3c26690550006abe63152b782280f4e14374accdf04cbde844f00bc0"
url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-macos-amd64"
url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012782"
provenance = "github-attestations"
[tools.jq."platforms.windows-x64"]
checksum = "sha256:a6fc67fedaf9128a3309a1e2ebb8b986aeccf70122ee46d2cb4849e423f0c627"
url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-windows-amd64.exe"
url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012788"
provenance = "github-attestations"
[[tools.shellcheck]]
version = "0.11.0"
backend = "aqua:koalaman/shellcheck"
specifiers = ["latest"]
[tools.shellcheck."platforms.linux-arm64"]
checksum = "sha256:12b331c1d2db6b9eb13cfca64306b1b157a86eb69db83023e261eaa7e7c14588"
url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.aarch64.tar.xz"
url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056934"
[tools.shellcheck."platforms.linux-arm64-musl"]
checksum = "sha256:12b331c1d2db6b9eb13cfca64306b1b157a86eb69db83023e261eaa7e7c14588"
url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.aarch64.tar.xz"
url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056934"
[tools.shellcheck."platforms.linux-x64"]
checksum = "sha256:8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198"
url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz"
url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056942"
[tools.shellcheck."platforms.linux-x64-musl"]
checksum = "sha256:8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198"
url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz"
url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056942"
[tools.shellcheck."platforms.macos-arm64"]
checksum = "sha256:56affdd8de5527894dca6dc3d7e0a99a873b0f004d7aabc30ae407d3f48b0a79"
url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.darwin.aarch64.tar.xz"
url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056932"
[tools.shellcheck."platforms.macos-x64"]
checksum = "sha256:3c89db4edcab7cf1c27bff178882e0f6f27f7afdf54e859fa041fca10febe4c6"
url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.darwin.x86_64.tar.xz"
url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056930"
[tools.shellcheck."platforms.windows-x64"]
checksum = "sha256:8a4e35ab0b331c85d73567b12f2a444df187f483e5079ceffa6bda1faa2e740e"
url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.zip"
url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056944"
[[tools.trivy]]
version = "0.76.0"
backend = "aqua:aquasecurity/trivy"
specifiers = ["latest"]
-6
View File
@@ -1,9 +1,7 @@
[tools]
act = "latest"
docker-cli = "latest"
jq = "latest"
shellcheck = "latest"
trivy = "latest"
[tasks."apk:build"]
description = "Build the Alpine package in Docker for the default architecture"
@@ -70,10 +68,6 @@ run = "scripts/apk/list-packages.sh"
description = "Check packaged upstream versions against latest GitHub releases"
run = "scripts/apk/outdated.sh"
[tasks."apk:security-report"]
description = "Generate Trivy and CycloneDX reports for built selected packages"
run = "scripts/apk/security-report.sh"
[tasks."apk:publish-check"]
description = "Run lint, multi-arch build, package listing, and smoke test"
run = "scripts/apk/publish-check.sh"
+6 -17
View File
@@ -1,7 +1,7 @@
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
pkgname=gitea
pkgver=28.2.0
pkgrel=0
pkgver=1.27.1
pkgrel=2
pkgdesc="Self-hosted Git service written in Go"
url="https://about.gitea.com/"
arch="x86_64 aarch64"
@@ -14,7 +14,6 @@ pkgusers="gitea"
pkggroups="www-data"
subpackages="
$pkgname-doc
$pkgname-logrotate:_logrotate:noarch
$pkgname-openrc:_openrc:noarch
"
options="!check !strip !tracedeps"
@@ -34,7 +33,6 @@ source="
$pkgname-src-$pkgver.tar.gz::https://github.com/go-gitea/gitea/releases/download/v$pkgver/gitea-src-$pkgver.tar.gz
gitea.ini
gitea.initd
gitea.logrotate
"
builddir="$srcdir/gitea-src-$pkgver"
@@ -70,19 +68,10 @@ _openrc() {
install -Dm755 "$srcdir"/gitea.initd "$subpkgdir"/etc/init.d/gitea
}
_logrotate() {
pkgdesc="Log rotation configuration for $pkgname"
depends="$pkgname=$pkgver-r$pkgrel logrotate"
install -Dm644 "$srcdir"/gitea.logrotate \
"$subpkgdir"/etc/logrotate.d/$pkgname
}
sha512sums="
a6ebe8f400d7ccbc4b98f314a2f21695e012d3ddd78f9b94583fe912f93ed078da5ef34c25ff2f5a0fd2d8ae6b531b25c6c1627fde09f17e9624bb9a9d5113fb gitea-28.2.0-linux-amd64.xz
e95cac30cad61cad06dee885fdb88676198663b25c70816860152ae85497332e03aa87bff2c1f58f84fcd0b46bb9b3f978617f972dd94dc506b1493f36da7f47 gitea-28.2.0-linux-arm64.xz
7bf890a3572f2992f2056f9e846732a267e2eb4a178212927fda98ed47b4ca09e9ecb748c2b424c4a90911689fe451c51f0bf987b02a49d751fc472a1d84d3fd gitea-src-28.2.0.tar.gz
4e20b24c34af01a27589a13d9140d559909cc44507febe5de692d7bc154d65f4b01b79d2f1dcce9fed77b60ac3b1a52cc0ec72161e5a2484a4c718d26d3c630d gitea.ini
103a3af76a84d9a093aaed09f03519ae1f698609f3374d64bc0c3aaed00296e5bea8382e8b5a0115c56875d64b8dd8e69dea43093ecebcd87fd5298e533b6fa2 gitea-1.27.1-linux-amd64.xz
ffb9d13be03ada20a8b8d59c6e7885b4ba57a27f3f487920a61b2491e56c06eb8d4f21ff6fb32ea598535b3af66bb15347ed3e07df4eaf532ed4c63909e4caee gitea-1.27.1-linux-arm64.xz
19e9893a2e15de188ad4fb17f52c49c87884ff5c14d2fadf59213887f262f7200ae0a86af4d3c9488d1cded54864e08423b5058e60c694fbb235e8693736436d gitea-src-1.27.1.tar.gz
431184faffa8996873d92d7b0d16bc4b1a0178d264cd2928d1f49b13ad3e6470d9ede7a18c12112deeeb38f0647ccc0b012e98bcbd96e7b8496a3dc18f5b1fb7 gitea.ini
9474d707df8b049c93ec4642f71195adff699e1e812f315cac4295b3ab29eeb9ba8b83bf3307c50b04e072a4a9dc4c4f84ac490ee22291bd50015009795c1598 gitea.initd
456a565123b46c0c3a36adbde4c881ee04557a2f1ba492a76205c28f72598bf3b7b96192ddeae4f9ab197fdc75bb5e10a3421574e1bf831192220b4540bb39fc gitea.logrotate
"
-7
View File
@@ -19,13 +19,6 @@ rc-update add gitea default
rc-service gitea start
```
Install daily rotation for the OpenRC service log, retaining 14 compressed
archives:
```sh
apk add gitea-logrotate
```
Refresh checksums:
```sh
+1 -2
View File
@@ -1,5 +1,4 @@
# Configuration cheat sheet: https://docs.gitea.com/administration/config-cheat-sheet/
# Example configuration: https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini
# Configuration cheat sheet: https://docs.gitea.io/en-us/config-cheat-sheet/
RUN_USER = gitea
RUN_MODE = prod
@@ -1,10 +0,0 @@
/var/log/gitea/http.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
copytruncate
su gitea www-data
}
@@ -5,7 +5,7 @@ repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." &&
# shellcheck source=scripts/apk/test-install-lib.sh
. "${repo_root}/scripts/apk/test-install-lib.sh"
apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-gitea}" "${PACKAGE_VERSION:-28.0.0-r1}" <<'SCRIPT'
apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-gitea}" "${PACKAGE_VERSION:-1.27.0-r1}" <<'SCRIPT'
set -e
if [ -n "${ALPINE_REPOSITORY_URL}" ]; then
@@ -29,7 +29,7 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-gitea}" "${PACKAGE_VERSION:
printf "%s\n" /repo >> /etc/apk/repositories
fi
apk update
apk add --upgrade "${PACKAGE_NAME}" "${PACKAGE_NAME}-doc" "${PACKAGE_NAME}-logrotate" "${PACKAGE_NAME}-openrc"
apk add --upgrade "${PACKAGE_NAME}" "${PACKAGE_NAME}-doc" "${PACKAGE_NAME}-openrc"
installed_after="$(apk list -I "${PACKAGE_NAME}" | awk "{print \$1}")"
printf "Installed package after local upgrade: %s\n" "${installed_after}"
test "${installed_after}" = "${PACKAGE_NAME}-${PACKAGE_VERSION}"
@@ -45,9 +45,6 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-gitea}" "${PACKAGE_VERSION:
test -d /usr/share/webapps/gitea/public
test -d /usr/share/webapps/gitea/templates
test -f /etc/init.d/gitea
test -f /etc/logrotate.d/gitea
apk info -e logrotate
logrotate -d /etc/logrotate.conf
gitea --version
+13 -42
View File
@@ -1,7 +1,7 @@
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
# Maintainer: Joachim Schlöffel <mjoachim.schloeffel@financial-service-plus.de>
pkgname=greptimedb
pkgver=1.2.1
pkgrel=5
pkgver=1.1.4
pkgrel=0
pkgdesc="Cloud-native observability database for metrics, logs, and traces"
url="https://github.com/GreptimeTeam/greptimedb"
arch="x86_64"
@@ -12,17 +12,14 @@ makedepends="
clang
cmake
coreutils
cargo-auditable
git
curl
lld
linux-headers
make
mold
nodejs
openssl-dev
openssl-libs-static
perl
pnpm
protobuf
protobuf-dev
rustup
@@ -31,14 +28,12 @@ makedepends="
zstd-dev
zstd-static
"
checkdepends="cargo-nextest"
install="$pkgname.pre-install"
subpackages="
$pkgname-datanode-openrc:_openrc_datanode:noarch
$pkgname-docs:_docs:noarch
$pkgname-flownode-openrc:_openrc_flownode:noarch
$pkgname-frontend-openrc:_openrc_frontend:noarch
$pkgname-logrotate:_logrotate:noarch
$pkgname-metasrv-openrc:_openrc_metasrv:noarch
$pkgname-standalone-openrc:_openrc_standalone:noarch
"
@@ -46,7 +41,7 @@ options="net"
_dashboard_version="v0.12.0"
source="
$pkgname-$pkgver.tar.gz::https://github.com/GreptimeTeam/greptimedb/archive/refs/tags/v$pkgver.tar.gz
dashboard-$_dashboard_version.tar.gz::https://github.com/GreptimeTeam/dashboard/archive/refs/tags/$_dashboard_version.tar.gz
dashboard-$_dashboard_version.tar.gz::https://github.com/GreptimeTeam/dashboard/releases/download/$_dashboard_version/build.tar.gz
datanode.toml
flownode.toml
frontend.toml
@@ -54,7 +49,6 @@ source="
greptimedb.flownode.confd
greptimedb.frontend.confd
greptimedb.initd
greptimedb.logrotate
greptimedb.metasrv.confd
greptimedb.standalone.confd
metasrv.toml
@@ -70,45 +64,31 @@ export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-2}"
export CARGO_PROFILE_NIGHTLY_CODEGEN_UNITS="${CARGO_PROFILE_NIGHTLY_CODEGEN_UNITS:-16}"
export CARGO_PROFILE_NIGHTLY_DEBUG="${CARGO_PROFILE_NIGHTLY_DEBUG:-false}"
export CARGO_PROFILE_NIGHTLY_LTO="${CARGO_PROFILE_NIGHTLY_LTO:-thin}"
export CARGO_PROFILE_TEST_DEBUG="${CARGO_PROFILE_TEST_DEBUG:-false}"
export LIBRARY_PATH="/usr/lib"
export RUSTFLAGS="${RUSTFLAGS:-} -C link-arg=-fuse-ld=mold"
prepare() {
default_prepare
if [ ! -d "$builddir"/src/servers/dashboard/dist ]; then
mv "$srcdir"/dist "$builddir"/src/servers/dashboard/dist
fi
rustup-init \
-y \
--no-modify-path \
--profile minimal \
--default-toolchain "$_rust_toolchain"
"$CARGO_HOME"/bin/rustup run "$_rust_toolchain" cargo fetch \
--locked
local _dashboard_builddir="$srcdir"/dashboard-${_dashboard_version#v}
(
cd "$_dashboard_builddir"
pnpm install --frozen-lockfile --store-dir "$srcdir"/pnpm-store
pnpm run build:docker
)
rm -rf "$builddir"/src/servers/dashboard/dist
cp -a "$_dashboard_builddir"/dist "$builddir"/src/servers/dashboard/
}
build() {
"$CARGO_HOME"/bin/rustup run "$_rust_toolchain" cargo auditable build \
"$CARGO_HOME"/bin/rustup run "$_rust_toolchain" cargo build \
--profile "$_cargo_profile" \
--frozen \
--locked \
--bin greptime \
--features servers/dashboard
}
check() {
"$CARGO_HOME"/bin/rustup run "$_rust_toolchain" cargo nextest run \
-p cmd \
--lib \
--frozen
"$CARGO_TARGET_DIR"/"$_cargo_profile"/greptime --version
}
package() {
@@ -138,14 +118,6 @@ _openrc_frontend() { _openrc_service frontend; }
_openrc_metasrv() { _openrc_service metasrv; }
_openrc_standalone() { _openrc_service standalone; }
_logrotate() {
pkgdesc="Log rotation configuration for $pkgname"
depends="$pkgname=$pkgver-r$pkgrel logrotate"
install -Dm644 "$srcdir"/greptimedb.logrotate \
"$subpkgdir"/etc/logrotate.d/$pkgname
}
_docs() {
pkgdesc="$pkgdesc (configuration examples and reference)"
depends=""
@@ -155,16 +127,15 @@ _docs() {
}
sha512sums="
fc580f6e34df84b4f37219047d751968324c356f3cad352d1515abb4b441515a1ad98f0d01e2de33aac5129a2d7a5335edc4d8888923da7683a084a484769bea greptimedb-1.2.1.tar.gz
3f853b6767a86cfa97ec640a17de59b2e798561c9402026e9b3a749907780b9b686149dba8a932b5d61ae538c430deab2410248e5c9e6e1961909000445ee2ee dashboard-v0.12.0.tar.gz
d60080a82a1dba52ab28d33ba1d9109bd047a6e598dbad17a3d92c82c6aad20b7fffd35cc20571829d8869360040af61195eeb97a14e08d8289e70663ee08664 greptimedb-1.1.4.tar.gz
4260acae5bed00a693dceffe9f53d0f8b25fd677b15638e951cf973dc29681f4bacde352c661a12bd78af7be9181a3740812f814fc3c4c8c87ea4eee6ee07e2d dashboard-v0.12.0.tar.gz
29cc3376753487b216748e3f85e12639830e1ac4a763e94f330f87c3651a8ef9de35732958311c0049e1b7cbb4e90a9e602b3aff43297fe088c5ce795a110a79 datanode.toml
52790808cb4f5cf0220ac2ab169b623fe76b6318d27d7f003e1197e850373cb915bfd40556098bcb7650f293d751039cb3bccbf9107bb160b8284887794ba975 flownode.toml
e3e19ab3c7a345ecf8cf0a507f7fc95dd3b036a4a797385cf77fcf1999f2e4f053042c7bbda8de73ed43ff72e87aad81e4ac6d4a34d01773bbc1f6d0d967d9f7 frontend.toml
313ed7d9ccd174b1869f3009e174266cdc414599e0b0f8307c8aaf2b73841eb36ce4c1b2f6244a0358b5a587a4edaa621b781fbd767835088b3fa13623fcc0df greptimedb.datanode.confd
daf8efacc8bf2b74abd9f4900f889585295b57333a8a562a722de0596d35f25d5f9149e0879f4140bfdf727caa59c3f55b1380212722df92c588d912275530b8 greptimedb.flownode.confd
e3e61b1df00f8172a3b1d4a0d37ed2574a8c5cd27676b4e2ce14d15ad8933d233baabe8da374f715d00cfaee26f665244c1ba00f70197fcc713c4e9af9c3229e greptimedb.frontend.confd
f72f52aa8277fc56eb071b5118990b8f4e09d143634c2f7fc54ed1f5ff065631c8630c45fe90d3db1f3ea0540c1ab3154a383d2000b4c5978e889ca02a1b6564 greptimedb.initd
775b4db7e7bc6127376b22fed8330b952c5027e3bfbfa29bb6ae034e6c75e7fed8ddfc0ad9761f369acd37398dfbd145cfea210828f2fc0bec9be92b051e6a75 greptimedb.logrotate
c00740aee566b161bbe3610e0e0d6e8340022055750e6778772262474ffd6484d9f58be2fd498beafe28d0943e259e2277930af691bedea7650726e6c8998881 greptimedb.initd
df495367d85844dcba99e5aa01e5a23fd14799b7521a72d9ea00d29fc0e5fbc5c5d06ee88e88d9637e260f8337249a39d2b0115de58da4899824d20bd844254a greptimedb.metasrv.confd
882a79e969cac42adfada22060e6507fb687755a6d266d6728154b3e4da5777d2eaf5ad9bc331ed050448249ca609e6a61977b624d9faf25d83ed975345452cf greptimedb.standalone.confd
8120ec338ebe1330d43b20d9b34a8f5f778ea13cb056febd3c8e9dc189d0de2380b90e5474a0990294d7004827c6133d44d2dd3e32d463b9259c47c82592d257 metasrv.toml
+4 -14
View File
@@ -1,22 +1,14 @@
# GreptimeDB Alpine Package
Builds `greptime` and its embedded dashboard from their upstream source
releases, and packages OpenRC service subpackages plus `/etc/greptimedb`
defaults.
Builds `greptime` from the upstream source release and packages OpenRC service
subpackages plus `/etc/greptimedb` defaults.
Build command:
```sh
cargo auditable build --profile nightly --frozen --locked --bin greptime --features servers/dashboard
cargo build --profile nightly --locked --bin greptime --features servers/dashboard
```
GreptimeDB requires the nightly pinned in its source release
(`nightly-2026-03-21`). The package uses Rustup to install that toolchain and
uses locked Cargo and pnpm dependency resolution, so `options="net"` is
intentional. Cargo dependencies are fetched before compilation; the Rust build
then runs frozen. The dashboard is built from the matching `v0.12.0` source tag
with its checked-in `pnpm-lock.yaml`.
## Runtime Layout
Installs `/usr/bin/greptime` and component OpenRC packages:
@@ -28,8 +20,6 @@ Installs `/usr/bin/greptime` and component OpenRC packages:
- `greptimedb-datanode-openrc`: `greptime datanode start`
- `greptimedb-flownode-openrc`: `greptime flownode start`
- `greptimedb-frontend-openrc`: `greptime frontend start`
- `greptimedb-logrotate`: daily rotation for the OpenRC service logs, retaining
14 compressed archives
Default TOML files are installed in `/etc/greptimedb`. Standalone ports:
@@ -102,4 +92,4 @@ ALPINE_REPOSITORY_KEY_URL=https://code.factoring.digital/api/packages/public/alp
mise run apk:test-install
```
Full builds and the targeted upstream Nextest check take close to an hour.
Full builds take close to an hour.
@@ -6,7 +6,6 @@ description="GreptimeDB ${service_name} service"
command="/usr/bin/greptime"
command_user="${GREPTIMEDB_USER:-greptimedb}:${GREPTIMEDB_GROUP:-greptimedb}"
command_background="yes"
retry="TERM/30/KILL/5"
pidfile="/run/greptimedb/${RC_SVCNAME}.pid"
output_log="${GREPTIMEDB_LOG:-/var/log/greptimedb/${RC_SVCNAME}.log}"
error_log="${GREPTIMEDB_ERRLOG:-/var/log/greptimedb/${RC_SVCNAME}.log}"
@@ -1,10 +0,0 @@
/var/log/greptimedb/greptimedb.*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
copytruncate
su greptimedb greptimedb
}
@@ -21,14 +21,3 @@ greptime --version
rc-update add greptimedb.standalone default || true
test -L /etc/runlevels/default/greptimedb.standalone
rc-service greptimedb.standalone start
for _attempt in $(seq 1 30); do
if wget -qO- http://127.0.0.1:4000/status >/dev/null; then
break
fi
sleep 1
done
wget -qO- http://127.0.0.1:4000/status >/dev/null
wget -qO- http://127.0.0.1:4000/dashboard/ | grep -qi '<!doctype html>'
rc-service greptimedb.standalone stop
@@ -26,7 +26,6 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-greptimedb}" "${PACKAGE_VER
"${PACKAGE_NAME}-docs" \
"${PACKAGE_NAME}-flownode-openrc" \
"${PACKAGE_NAME}-frontend-openrc" \
"${PACKAGE_NAME}-logrotate" \
"${PACKAGE_NAME}-metasrv-openrc" \
"${PACKAGE_NAME}-standalone-openrc"
@@ -35,8 +34,5 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-greptimedb}" "${PACKAGE_VER
ls -1 /etc/greptimedb
test -f "/usr/share/doc/${PACKAGE_NAME}/config/config.md"
test -f "/usr/share/doc/${PACKAGE_NAME}/config/standalone.example.toml"
test -f /etc/logrotate.d/greptimedb
apk info -e logrotate
logrotate -d /etc/logrotate.conf
find /etc/init.d -maxdepth 1 -name "greptimedb.*" -print | sort
SCRIPT
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
package_dir="${PACKAGE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
printf 'No generated sources for %s\n' "${package_dir}"
+11 -29
View File
@@ -1,14 +1,15 @@
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
pkgname=lavinmq
pkgver=2.10.2
pkgrel=1
pkgver=2.9.2
pkgrel=2
pkgdesc="High-performance AMQP and MQTT message queue server"
url="https://github.com/cloudamqp/lavinmq"
arch="x86_64"
license="Apache-2.0"
depends="ca-certificates /bin/sh"
makedepends="
crystal>=1.21.0
crystal>=1.20.1
curl
gc-dev
help2man
libevent-dev
@@ -26,34 +27,27 @@ pkgusers="lavinmq"
pkggroups="lavinmq"
subpackages="
$pkgname-doc
$pkgname-logrotate:_logrotate:noarch
$pkgname-openrc:_openrc:noarch
"
options="net"
source="
$pkgname-$pkgver.tar.gz::https://github.com/cloudamqp/lavinmq/archive/refs/tags/v$pkgver.tar.gz
$pkgname-$pkgver-shards.tar.gz
$pkgname-$pkgver-assets.tar.gz
lavinmq.confd
lavinmq.initd
lavinmq.logrotate
use-vendored-build-inputs.patch
"
prepare() {
default_prepare
tar -xzf "$srcdir/$pkgname-$pkgver-shards.tar.gz" -C "$builddir"
mkdir -p "$builddir/.alpine-assets"
tar -xzf "$srcdir/$pkgname-$pkgver-assets.tar.gz" -C "$builddir/.alpine-assets"
}
export CRYSTAL_CACHE_DIR="${CRYSTAL_CACHE_DIR:-$srcdir/crystal-cache}"
export SHARDS_CACHE_PATH="${SHARDS_CACHE_PATH:-$srcdir/shards-cache}"
build() {
crystal --version
make
make man
}
check() {
crystal spec spec/config_spec.cr
bin/lavinmq -v
bin/lavinmqctl --version
bin/lavinmqperf --version
}
package() {
@@ -73,20 +67,8 @@ _openrc() {
"$subpkgdir"/etc/conf.d/lavinmq
}
_logrotate() {
pkgdesc="Log rotation configuration for $pkgname"
depends="$pkgname=$pkgver-r$pkgrel logrotate"
install -Dm644 "$srcdir"/lavinmq.logrotate \
"$subpkgdir"/etc/logrotate.d/$pkgname
}
sha512sums="
35757407adb6fdd6378c65cde229471bd362b6a7fdc13279658312ef8a7304c0557619a1394a0b4cf33ef25ffb6c039f65c217f2af37bf12fc01b73d84e55e69 lavinmq-2.10.2.tar.gz
d0dfdd5c0e474024f57deb9e31c76e3f176e798c8d21dea53d3aea1b05436bd03fa34e69ccddf322bc89adedce5f379df5a316cddbbdfe12520e5bf672ad8228 lavinmq-2.10.2-shards.tar.gz
ae3cea2534b211abbcbd1e4fcb6da73dfaf383a19aef1c45f367cba77492cc20a7ce8283fc42f26c0a023149114c369bed307fb8cde0b8f27fba61165092e986 lavinmq-2.10.2-assets.tar.gz
2c9c2740db2f09cefa0f45b20354ba42dc6d83079d078398c370c8b9378c76c16f6f7a4495fbb74a6059f8b418526a95f09a5d94ab32ba97b1e44ed318f1c6af lavinmq-2.9.2.tar.gz
62a609d50f28db960098c4c84ce4f1dad78413366a9a9aca18fe321114d687be3bf7b71924d4ace69bd74383c5ac40d2ee09ae0eef9c1bfe653b97448e42e110 lavinmq.confd
1853196e70297b5c4a2207fde50df735620cf6d99c4994644fd676bffaf863d67300ad7ae771c4bbb86fce1a0485c2a7968cf912c5f5bb878e08b15e5a28ba1b lavinmq.initd
9999dd6a96bd29a3d0bda1b2110af940b15acf1250a0f3ba6c93d16bd62063ab1c1dfa4c237da99bbb401150517abde59e2c7275f4b72c3eb7c90e1ce61d43b9 lavinmq.logrotate
e7617099f745ecbf2f0686830d0a1b28044741ebd543798505b5b3c08f1be96b6cc478eb18f6785af49b100c2f49d837775f0721ac27519ddf3f081e681c581c use-vendored-build-inputs.patch
"
+3 -32
View File
@@ -1,9 +1,7 @@
# LavinMQ Alpine Package
Builds LavinMQ from the upstream source release for `x86_64` and packages the
OpenRC service plus `/etc/lavinmq` defaults. The locked Shards dependencies and
frontend assets are versioned, checksummed source inputs, so the build does not
need network access.
OpenRC service plus `/etc/lavinmq` defaults.
Build command:
@@ -11,9 +9,8 @@ Build command:
make
```
LavinMQ 2.10.1 requires Crystal 1.21.0 or newer. The package uses Alpine
edge's native Crystal package, avoiding a glibc toolchain in the Alpine musl
build.
LavinMQ 2.9.1 requires Crystal 1.20.1 or newer, so build with Alpine 3.24 or
newer.
## Runtime Layout
@@ -38,38 +35,12 @@ rc-update add lavinmq default
rc-service lavinmq start
```
Install daily rotation for the OpenRC service log, retaining 14 compressed
archives:
```sh
apk add lavinmq-logrotate
```
Wrapper settings in `/etc/conf.d/lavinmq`:
- `LAVINMQ_CONFIG`: config file path passed with `--config`
- `LAVINMQ_DATA_DIR`: data directory passed with `-D`
- `LAVINMQ_OPTS`: extra LavinMQ arguments appended after package defaults
## Updating LavinMQ
1. In `APKBUILD`, set `pkgver` to the new upstream version and reset `pkgrel`
to `0`.
2. Generate the versioned, locked Shards and frontend-asset archives:
```sh
ALPINE_PACKAGE=lavinmq mise run apk:update-generated
```
The hook uses the upstream `shard.lock` and `Makefile`, so it also refreshes
the bundled inputs when either dependency list changes.
3. From the repository root, refresh checksums and build the package:
```sh
ALPINE_PACKAGE=lavinmq mise run apk:checksum
ALPINE_PACKAGE=lavinmq mise run apk:build
```
## Package Commands
Refresh checksums:
@@ -1,10 +0,0 @@
/var/log/lavinmq/lavinmq.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
copytruncate
su lavinmq lavinmq
}
@@ -20,7 +20,7 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-lavinmq}" "${PACKAGE_VERSIO
printf "%s\n" /repo >> /etc/apk/repositories
fi
apk update
apk add "${PACKAGE_NAME}" "${PACKAGE_NAME}-doc" "${PACKAGE_NAME}-logrotate" "${PACKAGE_NAME}-openrc"
apk add "${PACKAGE_NAME}" "${PACKAGE_NAME}-doc" "${PACKAGE_NAME}-openrc"
test -x /usr/bin/lavinmq
test -x /usr/bin/lavinmqctl
@@ -30,9 +30,6 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-lavinmq}" "${PACKAGE_VERSIO
test "$(stat -c "%U:%G %a" /var/lib/lavinmq)" = "lavinmq:lavinmq 750"
test -f /etc/conf.d/lavinmq
test -f /etc/init.d/lavinmq
test -f /etc/logrotate.d/lavinmq
apk info -e logrotate
logrotate -d /etc/logrotate.conf
test -f /usr/share/doc/lavinmq/README.md
test -f /usr/share/doc/lavinmq/changelog
@@ -1,55 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
package_dir="${PACKAGE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
repo_root="${REPO_ROOT:-$(cd "${package_dir}/../../../.." && pwd)}"
pkgver="$(awk -F= '$1 == "pkgver" { print $2; exit }' "${package_dir}/APKBUILD")"
distfiles_dir="${repo_root}/.cache/apk-distfiles"
shards_cache_dir="${repo_root}/.cache/shards"
source_archive="${distfiles_dir}/lavinmq-${pkgver}.tar.gz"
shards_archive="${package_dir}/lavinmq-${pkgver}-shards.tar.gz"
assets_archive="${package_dir}/lavinmq-${pkgver}-assets.tar.gz"
tmpdir="$(mktemp -d)"
assets_dir="${tmpdir}/assets"
cleanup() {
rm -rf "${tmpdir}"
}
trap cleanup EXIT
mkdir -p "${distfiles_dir}" "${shards_cache_dir}"
if [[ ! -f "${source_archive}" ]]; then
curl --fail --location --retry 3 --silent --show-error \
--output "${source_archive}" \
"https://github.com/cloudamqp/lavinmq/archive/refs/tags/v${pkgver}.tar.gz"
fi
tar -xzf "${source_archive}" -C "${tmpdir}"
source_dir="${tmpdir}/lavinmq-${pkgver}"
if [[ ! -d "${source_dir}" ]]; then
printf 'unexpected LavinMQ source archive layout: %s\n' "${source_archive}" >&2
exit 1
fi
# shard.lock pins the Crystal dependencies. `make js` fetches exactly the
# frontend assets declared by this upstream version's Makefile.
(
cd "${source_dir}"
SHARDS_CACHE_PATH="${shards_cache_dir}" shards install --production
make js
)
tar --create --gzip --file "${shards_archive}" \
--directory "${source_dir}" \
--sort=name --mtime='UTC 1970-01-01' --owner=0 --group=0 --numeric-owner \
lib
mkdir -p "${assets_dir}"
# The offline Makefile patch intentionally reads every asset from the root of
# .alpine-assets, including helpers.segment.js which upstream stores in chunks/.
find "${source_dir}/static/js/lib" -type f -exec cp -p {} "${assets_dir}/" \;
tar --create --gzip --file "${assets_archive}" \
--directory "${assets_dir}" \
--sort=name --mtime='UTC 1970-01-01' --owner=0 --group=0 --numeric-owner \
.
printf 'Updated %s and %s\n' "${shards_archive##*/}" "${assets_archive##*/}"
@@ -1,36 +0,0 @@
--- a/Makefile
+++ b/Makefile
@@ -8,0 +9 @@
+LAVINMQ_ASSET_DIR ?= .alpine-assets
@@ -55,2 +56,2 @@
-lib: shard.yml shard.lock
- shards install --production
+lib:
+ test -d lib
@@ -62,3 +63 @@
- curl --fail --retry 5 -sL https://github.com/chartjs/Chart.js/releases/download/v4.0.1/chart.js-4.0.1.tgz | \
- tar -zxOf- package/dist/chart.js > $@
- [ "038d0a4f9c61f0b35ff70f883e7591403a349542625a4caaf48caa141adedfd5 *$@" = "$$(openssl dgst -sha256 -r $@)" ]
+ install -Dm644 "$(LAVINMQ_ASSET_DIR)/chart.js" "$@"
@@ -67,3 +66 @@
- curl --fail --retry 5 -sL https://github.com/chartjs/Chart.js/releases/download/v4.0.1/chart.js-4.0.1.tgz | \
- tar -zxOf- package/dist/chunks/helpers.segment.js > $@
- [ "b4746b748fe583a18ef921e341b8b65166c2ebd0b737fde6527b254baaeb1aa1 *$@" = "$$(openssl dgst -sha256 -r $@)" ]
+ install -Dm644 "$(LAVINMQ_ASSET_DIR)/helpers.segment.js" "$@"
@@ -72,2 +69 @@
- curl --fail --retry 5 -sLo $@ https://moment.github.io/luxon/es6/luxon.mjs
- [ "b495ad5cabea3439d04387e6622f2c3fa81d319424d9d76d9e7f874ac5a0807a *$@" = "$$(openssl dgst -sha256 -r $@)" ]
+ install -Dm644 "$(LAVINMQ_ASSET_DIR)/luxon.js" "$@"
@@ -76,3 +72 @@
- curl --fail --retry 5 -sLo $@ https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.3.1/dist/chartjs-adapter-luxon.esm.js
- sed -i'' -e "s|\(import { _adapters } from\).*|\1 './chart.js'|; s|\(import { DateTime } from\).*|\1 './luxon.js'|" $@
- [ "17d7b6567d656a004f86b6b5cbdbe64cb308e9a2ebfa7675caa79ba0bc72ef91 *$@" = "$$(openssl dgst -sha256 -r $@)" ]
+ install -Dm644 "$(LAVINMQ_ASSET_DIR)/chartjs-adapter-luxon.esm.js" "$@"
@@ -81,2 +75 @@
- curl --fail --retry 5 -sLo $@ https://unpkg.com/@stoplight/elements@8.2.0/web-components.min.js
- [ "598862da6d551769ebad9d61d4e3037535de573a13d3e0bd1ded4c5fc65c5885 *$@" = "$$(openssl dgst -sha256 -r $@)" ]
+ install -Dm644 "$(LAVINMQ_ASSET_DIR)/elements-8.2.0.js" "$@"
@@ -85,2 +78 @@
- curl --fail --retry 5 -sLo $@ https://unpkg.com/@stoplight/elements@8.2.0/styles.min.css
- [ "119784e23ffc39b6fa3fdb3df93f391f8250e8af141b78dfc3b6bed86079f93b *$@" = "$$(openssl dgst -sha256 -r $@)" ]
+ install -Dm644 "$(LAVINMQ_ASSET_DIR)/elements-8.2.0.css" "$@"
-75
View File
@@ -1,75 +0,0 @@
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
pkgname=nifi
pkgver=2.12.0
pkgrel=1
pkgdesc="Reliable system for processing and distributing data"
url="https://nifi.apache.org/"
arch="x86_64 aarch64"
license="Apache-2.0"
depends="openjdk21-jre-headless"
makedepends="unzip"
install="$pkgname.pre-install"
pkgusers="nifi"
pkggroups="nifi"
subpackages="
$pkgname-openrc:_openrc:noarch
"
options="!check !strip !tracedeps"
source="
$pkgname-$pkgver-bin.zip::https://dlcdn.apache.org/nifi/$pkgver/nifi-$pkgver-bin.zip
nifi.confd
nifi.initd
nifi.wrapper
"
package() {
local _dir
install -d "$pkgdir"/usr/lib/nifi "$pkgdir"/etc/nifi
cp -a "$builddir"/. "$pkgdir"/usr/lib/nifi/
chmod -R a+rX "$pkgdir"/usr/lib/nifi
cp -a "$pkgdir"/usr/lib/nifi/conf/. "$pkgdir"/etc/nifi/
rm -r "$pkgdir"/usr/lib/nifi/conf
ln -s /etc/nifi "$pkgdir"/usr/lib/nifi/conf
install -d -m 0750 -o nifi -g nifi "$pkgdir"/var/lib/nifi
for _dir in \
assets \
connector_assets \
content_repository \
database_repository \
diagnostics \
extensions \
flowfile_repository \
nar_repository \
provenance_repository \
state \
status_repository \
work; do
install -d -m 0750 -o nifi -g nifi "$pkgdir"/var/lib/nifi/$_dir
ln -s /var/lib/nifi/$_dir "$pkgdir"/usr/lib/nifi/$_dir
done
install -d -m 0750 -o nifi -g nifi "$pkgdir"/var/log/nifi
ln -s /var/log/nifi "$pkgdir"/usr/lib/nifi/logs
ln -s /run/nifi "$pkgdir"/usr/lib/nifi/run
chown -R nifi:nifi "$pkgdir"/etc/nifi
chmod 0750 "$pkgdir"/etc/nifi
install -Dm755 "$srcdir"/nifi.wrapper "$pkgdir"/usr/bin/nifi
}
_openrc() {
pkgdesc="$pkgdesc (OpenRC service)"
depends="$pkgname=$pkgver-r$pkgrel openrc"
install -Dm755 "$srcdir"/nifi.initd "$subpkgdir"/etc/init.d/nifi
install -Dm644 "$srcdir"/nifi.confd "$subpkgdir"/etc/conf.d/nifi
}
sha512sums="
5891039ccf15234bb21c2d1ce65027357ca7603ad8fdfc946dd4b6499ab8061fb07a6a56f8e8c5bb7635d446354ca7cc76ba40e55921818931f193a75f247334 nifi-2.12.0-bin.zip
fd576c2d2333aa79f7dac90e83f9cf6e0faed9748ebce0dfc1c18bcd1da0ec1d0da90d4004055bbddcb0f011a0e9efdc08f0eed2f3c19d49b1746019f2be1da9 nifi.confd
9f8a005fcd6a6f75a553321c27c672c4c202e8b86ff5fa0a1bd5eb0e7305592e67d8dc6a915d1f1bc01b39916b0fb0e61478cb6ae5aee4ae8b3be36c80c5662a nifi.initd
7764c6a53f0fb109ecde4959b438a0eeb669b00eafdbdb2abe5255f4053a237d4e97349594b3bf053abd55a96f8e217aa0cf0fec59a7c14f1db2490e747f713e nifi.wrapper
"
-50
View File
@@ -1,50 +0,0 @@
# Apache NiFi Alpine Package
Repackages Apache NiFi 2.12.0 Standard for Alpine. The package requires Java
21 and retains NiFi 2's secure default: HTTPS listens on `127.0.0.1:8443` and
uses generated single-user credentials.
## Install
```sh
apk add nifi nifi-openrc
rc-update add nifi default
rc-service nifi start
```
Open `https://127.0.0.1:8443/nifi` and retrieve the generated credentials:
```sh
grep 'Generated \(Username\|Password\)' /var/log/nifi/nifi-app.log
```
Set fixed single-user credentials as the service account:
```sh
doas -u nifi nifi set-single-user-credentials '<username>' '<password>'
rc-service nifi restart
```
## Runtime Layout
```text
/usr/bin/nifi Administration command wrapper
/usr/lib/nifi NiFi binaries and bundled NARs
/etc/nifi Mutable NiFi configuration and authorization state
/var/lib/nifi Repositories, state, extensions, and work files
/var/log/nifi Application logs
/etc/conf.d/nifi OpenRC account defaults
/etc/init.d/nifi OpenRC service
```
Edit `/etc/nifi/nifi.properties` to bind a different HTTPS address, configure
TLS, or select LDAP, OIDC, or another supported authentication provider.
## Package Commands
```sh
ALPINE_PACKAGE=nifi mise run apk:checksum
ALPINE_PACKAGE=nifi mise run apk:build
ALPINE_PACKAGE=nifi SKIP_BUILD=1 mise run apk:test-install
ALPINE_PACKAGE=nifi mise run apk:runtime-test
```
-3
View File
@@ -1,3 +0,0 @@
# Defaults for Apache NiFi.
NIFI_USER="nifi"
NIFI_GROUP="nifi"
-26
View File
@@ -1,26 +0,0 @@
#!/sbin/openrc-run
description="Apache NiFi dataflow service"
supervisor=supervise-daemon
name=nifi
command="/usr/lib/nifi/bin/nifi.sh"
command_args="run"
command_user="${NIFI_USER:-nifi}:${NIFI_GROUP:-nifi}"
directory="/usr/lib/nifi"
pidfile="/run/nifi/nifi.pid"
supervise_daemon_args="--chdir /usr/lib/nifi --env HOME=/var/lib/nifi --pidfile ${pidfile}"
depend() {
need net
use dns logger
}
start_pre() {
local service_owner="${NIFI_USER:-nifi}:${NIFI_GROUP:-nifi}"
checkpath -d -m 0750 -o "$service_owner" \
/run/nifi \
/var/lib/nifi \
/var/log/nifi
}
@@ -1,7 +0,0 @@
#!/bin/sh
addgroup -S nifi 2>/dev/null
adduser -S -D -H -h /var/lib/nifi -s /sbin/nologin \
-G nifi -g nifi nifi 2>/dev/null
exit 0
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
exec /usr/lib/nifi/bin/nifi.sh "$@"
@@ -1,34 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
apk add nifi nifi-openrc curl
test -x /usr/bin/nifi
test -x /usr/lib/nifi/bin/nifi.sh
test -d /etc/nifi
test -L /usr/lib/nifi/conf
test "$(readlink /usr/lib/nifi/conf)" = /etc/nifi
test -d /var/lib/nifi
test -d /var/log/nifi
test -f /etc/init.d/nifi
test -f /etc/conf.d/nifi
test -d /usr/lib/nifi/docs
test "$(stat -c '%U:%G %a' /var/lib/nifi)" = "nifi:nifi 750"
rc-update add nifi default || true
test -L /etc/runlevels/default/nifi
rc-service nifi start
for _attempt in $(seq 1 300); do
if curl --fail --insecure --silent --show-error \
https://localhost:8443/nifi/ >/dev/null; then
break
fi
sleep 1
done
curl --fail --insecure --silent --show-error https://localhost:8443/nifi/ >/dev/null
grep -q 'Generated Username' /var/log/nifi/nifi-app.log
grep -q 'Generated Password' /var/log/nifi/nifi-app.log
rc-service nifi status
rc-service nifi stop
@@ -1,39 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
# shellcheck source=scripts/apk/test-install-lib.sh
. "${repo_root}/scripts/apk/test-install-lib.sh"
apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-nifi}" "${PACKAGE_VERSION:-2.12.0-r0}" <<'SCRIPT'
set -e
if [ -n "${ALPINE_REPOSITORY_URL}" ]; then
if [ -n "${ALPINE_REPOSITORY_KEY_URL}" ]; then
apk add --no-cache curl >/dev/null
cd /etc/apk/keys
curl -fsSLOJ "${ALPINE_REPOSITORY_KEY_URL}"
fi
printf "%s\n" "${ALPINE_REPOSITORY_URL}" >> /etc/apk/repositories
else
cp "/repo/${ALPINE_ARCH}"/*.rsa.pub /etc/apk/keys/
printf "%s\n" /repo >> /etc/apk/repositories
fi
apk update
apk add "${PACKAGE_NAME}" "${PACKAGE_NAME}-openrc"
test -x /usr/bin/nifi
test -x /usr/lib/nifi/bin/nifi.sh
test -d /etc/nifi
test -L /usr/lib/nifi/conf
test "$(readlink /usr/lib/nifi/conf)" = /etc/nifi
test -d /var/lib/nifi
test -d /var/log/nifi
test -f /etc/init.d/nifi
test -f /etc/conf.d/nifi
test -d /usr/lib/nifi/docs
test "$(stat -c '%U:%G %a' /var/lib/nifi)" = "nifi:nifi 750"
rc-update add nifi default
test -L /etc/runlevels/default/nifi
SCRIPT
@@ -1,3 +0,0 @@
provider="github"
repo="apache/nifi"
version_prefix="rel/nifi-"
@@ -1,29 +0,0 @@
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
pkgname=rclone-openrc
pkgver=0.1.0
pkgrel=1
pkgdesc="Generic, instance-capable OpenRC service for rclone"
url="https://rclone.org/"
arch="noarch"
license="MIT"
depends="openrc rclone"
install="$pkgname.pre-install"
pkgusers="rclone"
pkggroups="rclone"
options="!check"
source="
rclone.confd
rclone.initd
"
package() {
install -d -m 0750 -o root -g rclone "$pkgdir"/etc/rclone
install -d -m 0750 -o rclone -g rclone "$pkgdir"/var/lib/rclone/cache
install -Dm644 "$srcdir"/rclone.confd "$pkgdir"/etc/conf.d/rclone
install -Dm755 "$srcdir"/rclone.initd "$pkgdir"/etc/init.d/rclone
}
sha512sums="
91a05da2c5740a810faf0226ab5fcb3d92a9db56b42c10decaed91481d3129cfc37f5f726a6dc1b5b1246ad4d1386cbe918e109f152969912ea670dbff35fe70 rclone.confd
e92ce86aa21ce1a94beb8304c806b4c0045d412477d7a232e37b0f28354af3060de054c5ae3d1ea353b92d19137a0cfa00b0891b0e179aa32bc6b2c7ecdfc7ea rclone.initd
"
@@ -1,59 +0,0 @@
# rclone OpenRC Alpine Package
Provides a generic, instance-capable OpenRC service for Alpine's `rclone`
package. It does not repackage the rclone binary.
## Install
```sh
apk add rclone-openrc
```
The package creates the unprivileged `rclone` account, `/etc/rclone` for
configuration and credentials, and `/var/lib/rclone/cache` for rclone state.
It deliberately does not create remotes, credentials, authorized-key files, or
SSH host keys; provision those as machine-specific secrets.
## Create an Instance
Copy the template and symlink the generic service under an instance name:
```sh
cp /etc/conf.d/rclone /etc/conf.d/rclone.sftp
ln -s rclone /etc/init.d/rclone.sftp
```
For an SFTP server, configure `/etc/conf.d/rclone.sftp`:
```sh
RCLONE_COMMAND="serve sftp"
RCLONE_REMOTE="/srv/storage"
RCLONE_ARGS="
--addr :2022
--authorized-keys /etc/rclone/authorized_keys
--key /etc/rclone/ssh_host_ed25519_key
--log-level INFO
"
```
Then enable and start it:
```sh
rc-update add rclone.sftp default
rc-service rclone.sftp start
```
Other instances, such as `rclone.webdav` or `rclone.rcd`, use their own
`/etc/conf.d/rclone.<name>` file with the same generic init script. The service
runs rclone in the foreground under `supervise-daemon`, which restarts it after
an unexpected exit. Set `RCLONE_RESPAWN_MAX` to a positive value to limit
restart attempts.
## Package Commands
```sh
ALPINE_PACKAGE=rclone-openrc mise run apk:checksum
ALPINE_PACKAGE=rclone-openrc mise run apk:build
ALPINE_PACKAGE=rclone-openrc SKIP_BUILD=1 mise run apk:test-install
ALPINE_PACKAGE=rclone-openrc mise run apk:runtime-test
```
@@ -1,7 +0,0 @@
#!/bin/sh
addgroup -S rclone 2>/dev/null
adduser -S -D -H -h /var/lib/rclone -s /sbin/nologin \
-G rclone -g rclone rclone 2>/dev/null
exit 0
@@ -1,23 +0,0 @@
# Defaults for rclone OpenRC instances.
#
# To create an instance, copy this file to /etc/conf.d/rclone.<name> and create
# /etc/init.d/rclone.<name> as a symlink to /etc/init.d/rclone. For example:
#
# cp /etc/conf.d/rclone /etc/conf.d/rclone.sftp
# ln -s rclone /etc/init.d/rclone.sftp
#
# Each instance must set RCLONE_COMMAND. RCLONE_REMOTE is optional because
# commands such as "rcd" do not use a remote.
RCLONE_COMMAND=""
RCLONE_REMOTE=""
RCLONE_ARGS=""
RCLONE_CONFIG="/etc/rclone/rclone.conf"
RCLONE_CACHE_DIR="/var/lib/rclone/cache"
RCLONE_USER="rclone"
RCLONE_GROUP="rclone"
# Restart a long-running rclone command after an unexpected exit. Set
# RCLONE_RESPAWN_MAX to a positive number to limit restart attempts.
RCLONE_RESPAWN_DELAY="5"
RCLONE_RESPAWN_MAX="0"
@@ -1,31 +0,0 @@
#!/sbin/openrc-run
instance_name="${RC_SVCNAME#rclone.}"
description="rclone ${instance_name} service"
supervisor="supervise-daemon"
command="/usr/bin/rclone"
command_user="${RCLONE_USER:-rclone}:${RCLONE_GROUP:-rclone}"
pidfile="/run/rclone/${RC_SVCNAME}.pid"
respawn_delay="${RCLONE_RESPAWN_DELAY:-5}"
respawn_max="${RCLONE_RESPAWN_MAX:-0}"
supervise_daemon_args="--chdir /var/lib/rclone --pidfile ${pidfile}"
command_args="${RCLONE_COMMAND:-} ${RCLONE_REMOTE:-} --config ${RCLONE_CONFIG:-/etc/rclone/rclone.conf} --cache-dir ${RCLONE_CACHE_DIR:-/var/lib/rclone/cache} ${RCLONE_ARGS:-}"
depend() {
need net
use dns logger
}
start_pre() {
local service_owner="${RCLONE_USER:-rclone}:${RCLONE_GROUP:-rclone}"
if [ -z "${RCLONE_COMMAND:-}" ]; then
eerror "RCLONE_COMMAND is required; configure /etc/conf.d/${RC_SVCNAME}"
return 1
fi
checkpath -d -m 0750 -o "$service_owner" \
/run/rclone \
"${RCLONE_CACHE_DIR:-/var/lib/rclone/cache}"
}
@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
apk add rclone-openrc
test -x /usr/bin/rclone
test -f /etc/conf.d/rclone
test -f /etc/init.d/rclone
test "$(stat -c '%U:%G %a' /etc/rclone)" = "root:rclone 750"
test "$(stat -c '%U:%G %a' /var/lib/rclone/cache)" = "rclone:rclone 750"
cp /etc/conf.d/rclone /etc/conf.d/rclone.rcd
ln -s rclone /etc/init.d/rclone.rcd
sed -i 's|^RCLONE_COMMAND=""|RCLONE_COMMAND="rcd"|' /etc/conf.d/rclone.rcd
sed -i 's|^RCLONE_ARGS=""|RCLONE_ARGS="--rc-addr 127.0.0.1:5572 --rc-no-auth"|' /etc/conf.d/rclone.rcd
rc-update add rclone.rcd default || true
rc-service rclone.rcd start
rc-service rclone.rcd status
rc-service rclone.rcd stop
@@ -1,36 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
# shellcheck source=scripts/apk/test-install-lib.sh
. "${repo_root}/scripts/apk/test-install-lib.sh"
apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-rclone-openrc}" "${PACKAGE_VERSION:-}" <<'SCRIPT'
set -e
if [ -n "${ALPINE_REPOSITORY_URL}" ]; then
if [ -n "${ALPINE_REPOSITORY_KEY_URL}" ]; then
apk add --no-cache curl >/dev/null
cd /etc/apk/keys
curl -fsSLOJ "${ALPINE_REPOSITORY_KEY_URL}"
fi
printf "%s\n" "${ALPINE_REPOSITORY_URL}" >> /etc/apk/repositories
else
cp "/repo/${ALPINE_ARCH}"/*.rsa.pub /etc/apk/keys/
printf "%s\n" /repo >> /etc/apk/repositories
fi
apk update
apk add "${PACKAGE_NAME}"
test -x /usr/bin/rclone
test -f /etc/conf.d/rclone
test -f /etc/init.d/rclone
test -d /etc/rclone
test "$(stat -c '%U:%G %a' /etc/rclone)" = "root:rclone 750"
test "$(stat -c '%U:%G %a' /var/lib/rclone/cache)" = "rclone:rclone 750"
cp /etc/conf.d/rclone /etc/conf.d/rclone.sftp
ln -s rclone /etc/init.d/rclone.sftp
rc-update add rclone.sftp default
test -L /etc/runlevels/default/rclone.sftp
SCRIPT
+35 -69
View File
@@ -1,13 +1,12 @@
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
pkgname=seaweedfs
pkgver=4.48
pkgrel=4
pkgver=4.41
pkgrel=1
pkgdesc="Distributed storage system for object storage, file systems, and Iceberg tables"
url="https://github.com/seaweedfs/seaweedfs"
arch="x86_64 aarch64"
license="Apache-2.0"
depends="ca-certificates /bin/sh"
makedepends="build-base cargo go protobuf-dev rust"
provides="!$pkgname-openrc cmd:weed=$pkgver-r$pkgrel"
install="$pkgname.pre-install"
subpackages="
@@ -15,78 +14,66 @@ subpackages="
$pkgname-bash-completion:_bashcomp:noarch
$pkgname-doc
$pkgname-filer-openrc:_openrc_filer:noarch
$pkgname-logrotate:_logrotate:noarch
$pkgname-master-openrc:_openrc_master:noarch
$pkgname-s3-openrc:_openrc_s3:noarch
$pkgname-sftp-openrc:_openrc_sftp:noarch
$pkgname-volume-openrc:_openrc_volume:noarch
$pkgname-webdav-openrc:_openrc_webdav:noarch
$pkgname-worker-openrc:_openrc_worker:noarch
$pkgname-worker-lance:_worker_lance
$pkgname-worker-lance-openrc:_openrc_worker_lance:noarch
"
options="!strip !tracedeps net"
options="!check !strip !tracedeps"
case "$CARCH" in
x86_64)
_archive="$pkgname-$pkgver-linux-amd64.tar.gz"
;;
aarch64)
_archive="$pkgname-$pkgver-linux-arm64.tar.gz"
;;
esac
source="
$pkgname-$pkgver-src.tar.gz::https://github.com/seaweedfs/seaweedfs/archive/refs/tags/$pkgver.tar.gz
admin.toml
$pkgname-$pkgver-linux-amd64.tar.gz::https://github.com/seaweedfs/seaweedfs/releases/download/$pkgver/linux_amd64.tar.gz
$pkgname-$pkgver-linux-arm64.tar.gz::https://github.com/seaweedfs/seaweedfs/releases/download/$pkgver/linux_arm64.tar.gz
credential.toml
example-admin.toml
example-credential.toml
example-filer.toml
example-master.toml
example-volume.toml
example-notification.toml
example-replication.toml
example-security.toml
example-shell.toml
filer.toml
master.toml
notification.toml
replication.toml
security.toml
shell.toml
seaweedfs.admin.confd
seaweedfs.filer.confd
seaweedfs.initd
seaweedfs.logrotate
seaweedfs.master.confd
seaweedfs.s3.confd
seaweedfs.sftp.confd
seaweedfs.volume.confd
seaweedfs.webdav.confd
seaweedfs.worker.confd
seaweedfs.worker-lance.confd
weed.bash-completion
"
_worker_builddir="$srcdir/$pkgname-$pkgver/seaweed-worker"
builddir="$srcdir"
prepare() {
default_prepare
}
build() {
go build -mod=readonly -buildvcs=false -trimpath \
-tags "sqlite rclone gocdk" -o "$builddir/weed-bin" ./weed
cd "$_worker_builddir"
cargo build --locked --release -p weed-lance-worker
}
check() {
"$builddir/weed-bin" version
"$builddir/weed-bin" scaffold -config master >/dev/null
"${CARGO_TARGET_DIR:-$_worker_builddir/target}/release/weed-worker" --help >/dev/null
tar -xzf "$srcdir/$_archive" -C "$builddir"
}
package() {
install -Dm755 "$builddir"/weed-bin "$pkgdir"/usr/bin/weed
install -Dm755 "${CARGO_TARGET_DIR:-$_worker_builddir/target}/release/weed-worker" \
"$pkgdir"/usr/bin/weed-worker
install -Dm755 "$srcdir"/weed "$pkgdir"/usr/bin/weed
local _config
for _config in admin credential filer master security; do
for _config in credential filer master notification replication security shell; do
install -Dm644 "$srcdir"/$_config.toml \
"$pkgdir"/etc/seaweedfs/$_config.toml
done
for _config in admin credential filer master volume notification replication security shell; do
install -Dm644 "$srcdir"/example-$_config.toml \
"$pkgdir"/usr/share/doc/$pkgname/examples/$_config.toml
done
@@ -112,26 +99,6 @@ _openrc_volume() { _openrc_service volume; }
_openrc_webdav() { _openrc_service webdav; }
_openrc_worker() { _openrc_service worker; }
_logrotate() {
pkgdesc="Log rotation configuration for $pkgname"
depends="$pkgname=$pkgver-r$pkgrel logrotate"
install -Dm644 "$srcdir"/seaweedfs.logrotate \
"$subpkgdir"/etc/logrotate.d/$pkgname
}
_worker_lance() {
pkgdesc="SeaweedFS Lance table maintenance worker"
depends="$pkgname=$pkgver-r$pkgrel libgcc"
amove usr/bin/weed-worker
}
_openrc_worker_lance() {
_openrc_service worker-lance
depends="$pkgname-worker-lance=$pkgver-r$pkgrel $depends"
}
_bashcomp() {
pkgdesc="Bash completions for $pkgname"
depends=""
@@ -142,31 +109,30 @@ _bashcomp() {
}
sha512sums="
91a34fec9bb78832f421b54dd823adb1c1690b746083d947c5f72e4ad7670362512bbb920432f42342482774fd8be2b396645ff3bc764b10f328432601733fe3 seaweedfs-4.48-src.tar.gz
58be6587b082f45b4dd22ad8ebb1b8bf84cea2a7c0cb6b4ad4a749ac0bfdf92d10d22281a432f9e5a87afa0b940cd0172671a292fbe17803e56425cd940d47f9 admin.toml
7f77ad8787629e3defbc89e39e5432482aa50d87ddd723de927a9c6c77b14b1673cbf5b3fc3c18dd7d0eba26fbcd4220d2da6939ed097d0294b24ccd5c002635 credential.toml
507b389f6373b5f4d8ca69f27bc806b39bda8edf7f58e4f32720958e7782ee171dd0461bdecb285e5a8bf2cf4ea3d6cbe8b62ae6ac43c2a40d0eb053d50a22f8 example-admin.toml
51810779863e7b5578ef1a236af137f2ef79e44b7d8f10b5b36f6d45fa002ae8c6ad92f18e7fefdff8f7a4ec5c29acea13d757faf74e26f0a2e3914680a03092 seaweedfs-4.41-linux-amd64.tar.gz
20b7504c2efcfaab86e92ad336715f80e3653dc833e20c56f7cde545b57488374648d5155e47b4faaa95df92311a0675d368baa01e75a717c788a304655b29c7 seaweedfs-4.41-linux-arm64.tar.gz
b6ce09d6d83dd70e2797a185171eea3587436fb024a99b4998f714b713244d6f768ef59f67c9b7251650d4f19d414eea231eab92099763d85cd92e41cb2bdc3f credential.toml
7105de7053654b8c0502521ce58585915fc831c3152801e1db02b1c5214dc3c3ed31f4fc18000665d8338c7a10ffbf0d248368bef2ef3a6d37d46cd856398366 example-credential.toml
c6ec4fc7709c42dc6771b5039203c44cbd693742abcd7720936c00b1bd5f99bb2999bb1545680ae4418efedd65d71c234f4602f52ce9d58b1ff7ec53eafb1a1a example-filer.toml
59965fd2649a956677c6d4104ff07ff010d6edd1d3733eaa5c5bc01eabe54429c413e35d52ed4a4c0129bfa798e434828b32a5f0ef19dbbe4eab0199faa2738c example-master.toml
aea1b3114311304230cb30143825329ef7353a302d094c131ca4e049b847305e2143b76078e6574c6d7d4039c03a2e2d5a4925de80cd7cb2be75b2b522ce47f7 example-volume.toml
9e6401387698832cb4aae0876ef3e237c9b70af17db7563ed641ba40c81af99f1d6c22281bafa64fff7ee8d2c89f16ccac1322ea31c9a02b545faa4e09f08549 example-filer.toml
e5753bd0bcc60dc84428c40ba556c08acae61dec083a5b76640125f637532e7c5759a72cdfd95114222a7a0901a916ec3c4d12f306853cfca0fe9a0b1857893e example-master.toml
2c200c28172a5d0b1c80ab28e849287e7af8d103355638fd3183b8614d3e2b1b3482132522663f7c6d844e10e13b8c6e23fb5fba0dec2cc83de45c2f17b33477 example-notification.toml
328cfe43d0c2ebf5092a1178af45c37b07593085135c31649754f0df9fd4c043847c13b56c3c7c45194541db8082309c4845c825d7011e4c3e503b1e6576528d example-replication.toml
b7caad9dff0bb812d4046b8e0285ac4e88a7af3a742a168579df08762da735a025725f78286e17bdd4b19a966a3d7ab88e0e52efbb5cf1c69d7a4ff071390e0f example-security.toml
4b507540d57799e42ec0ee84073c6fa32c577a2f4a98bf66ee7302355080c63c65d70709115185debdee3c957e9294e79a8e461347d7148af7fdd368dc548af6 example-replication.toml
6951e1110d458238b0ef1905c4c6bb874d06f1c18b83dd8e1742534806b8db68b4410a664bf53085781e5d4d35e87941279d9c7398529ee707bb99def5055591 example-security.toml
70069f97edf261a2cd0669dd60adad80533609a25d7429254e0c3322d7e80337f5ff69a5581bc39e6a15442098d14d610ce5f0cb14f02c461c8d3dd440b22c56 example-shell.toml
130b9932f99d0a3ec3c30c74eaf1dc441c1a9252da30e2c5365084f2a0679f58531e6180689c24b71f92cf9a7966b02ea25ee31d356e7118cbb82743d0bfcbd9 filer.toml
088c3aebc142054af1b54a92a2c5bd30d53be61bdf382f7cae2efef2d917d7b57022d9b494a60f32c7bf56689d4ce2f971e19c98da1d87e27021a3e948035605 master.toml
79a078133c259473e601488cd1d8032b74c5fa32da6f34a4ed46efa9736bf5369365a77d775e3d78512b1060cd87012eb40226829eecb30544e1542d165af7d6 security.toml
be5771a5e1bf626c53f9dffbfa2a400d9b8f9626d55a7b61dcd853753561989427ba872a2638a5e6343f44dea6790678483bd29101d6495dbbfcd3029947b9a7 filer.toml
2cd6c73a5e23e0395b6f099dcc3acf9280cbb3e13f54408571e91741c4e6b0dad85f6d4e5a92f23ad541bad57ce295c28bb8450fe11da35acbd4da25848f61e5 master.toml
0a1b3d0fd1671744f96e7642fb9aee9b80debd0d9a82f586beb36fe32f9ad440332acd2a8b0ee0b210b912cb281d88ca56fd15e3a2ece61be9dcf96afc00a6f8 notification.toml
5a607ce6cdd11ffbe528b9a85e0012b48accefa6ccfeda9d6aa70d92ccf7f219e75c93cd2f1c36f3eb16204b3652a45dcd52ffcb64bceef91d081702b19cef3c replication.toml
d21981923b5964cf8365185a4f7c28a14e33ba6f60ad63e797e315544a6c22efdaa72814292824c07ef14554738769e0fd4c670fe797cf77b0226b2595a8b43b security.toml
7a91ce9da79b92e5ef42d4915f56a010bceaaa6c96dcef1f7b1821ee208d381aaa88b9cf495248276132e66d3215927f589b7fabc4eae2c2cb195645f904fac7 shell.toml
82e2793bf483ffb5b0c8fbe38e6c9df75afe01f824f8414cafd91e4bed5c79c13dae1ca659070401d4968d16ed4b26455b0c6208f777705527bceb2e5f286988 seaweedfs.admin.confd
5ad952c37c62a770327bd70f7349fa677406606f0b9bf03fdc8f6c6804701f1e77710ab20d6153f9e0cfb549ec161d68a3316abab9c59837bbe3f91ee99e5ce0 seaweedfs.filer.confd
19cbd65d701b0995e088f265d88f481f14e214ecbd8a783f7e7b17e811e421a28425f96d073757cc07fbb17e8eb084d14d41f46baee82ee13e043ce0c0c5bde9 seaweedfs.initd
816e763164c2cec66509c213ed56cb633f13d1daf48a511d1a9cfdf692a6ad945cf599cb0e706202b8fd522022ce512eae6170422e478abdf95334b0088ac4cc seaweedfs.logrotate
6c7ebdaf8f941868051a025fda36278bdf5e5438a2d478ca1cbe35064f933e7b07bf6d56bdd2268894f01c4e232e48f69099f793baeb2d6011063ac56a132fe4 seaweedfs.initd
57ba77519bb266f0117eaadae3af5ae6bc99bb653668ff526202f327df1c8d93973c0e19dae0c53a19e06389868043c04e53f16f01c851b77fe1387e92cc993b seaweedfs.master.confd
22a3ea6c83266a979ea7c848fc74b40fc0f2ade960b273fa11e63d4a72a1328bd688c9918be3e9234cfb19f889fd9c931388bb5c2863cea3500e534b8bd90282 seaweedfs.s3.confd
3e9c41bc61cdd9a4c53ece64d847eca26ab7d0ce0cc98e72462c3dbb225a40de10a02201362801015a9c629d77d5c0d54c7228e9d20111fb6f478b2267d2db98 seaweedfs.sftp.confd
262cc5132a70a43f9f154d24da16fe2f34f736c0bfdafd56cd341b7f34b48b82aa3a38a93d64206360c391e1167e2b665a3ade5c7eddfe4b322253521629f4e0 seaweedfs.volume.confd
84a9caa8f5203a31f2f96ef812dca8e4f7597f8f06ed3f55db38daff167448b0332564a421dcb356405d761c7a9e815656208d431e84b8106951554ab7ef2142 seaweedfs.webdav.confd
b586dfbdbcf17591366a7a62c4da6f2b13e1bd5dfb5b066beea114d01057eeb3d81172814655d812c48e02336277b3d70fa9f9550923cfe616e9dd8162661f51 seaweedfs.worker.confd
0a06a1ea007a6e4e0110a6208830f080685b81f6e1aae8453a75941ef54e4506155e4c7be125b2eed0b971050d0743118cf1454b6e9d01cf8eec02005125b6b2 seaweedfs.worker-lance.confd
2815330810545d17cffd993d93502c934c24af5aeff8f7096bcf0f020f895f1da50b74c356c028b67de552cbd8e4ccfa176636da2642feae99542035e4272171 weed.bash-completion
"
+6 -31
View File
@@ -1,24 +1,17 @@
# SeaweedFS Alpine Package
Builds SeaweedFS 4.48 from its upstream source release for `x86_64` and
`aarch64`. The package intentionally builds the upstream baseline feature set,
with the `sqlite`, `rclone`, and `gocdk` optional Go build tags enabled. Go and
Cargo dependencies are resolved from the versions pinned in the upstream
`go.sum` and `Cargo.lock` files.
Repackages official SeaweedFS 4.39 Linux release tarballs for `x86_64` and
`aarch64`.
## Package Commands
When updating SeaweedFS, generate the config scaffolds and refresh checksums:
Refresh generated sources:
```sh
ALPINE_PACKAGE=seaweedfs mise run apk:update-generated
ALPINE_PACKAGE=seaweedfs mise run apk:checksum
```
The refresh command generates every SeaweedFS scaffold configuration:
`admin`, `credential`, `filer`, `master`, `volume`, `notification`,
`replication`, `security`, and `shell`.
Build:
```sh
@@ -61,7 +54,6 @@ seaweedfs-webdav-openrc -> /etc/init.d/seaweedfs.webdav
seaweedfs-sftp-openrc -> /etc/init.d/seaweedfs.sftp
seaweedfs-admin-openrc -> /etc/init.d/seaweedfs.admin
seaweedfs-worker-openrc -> /etc/init.d/seaweedfs.worker
seaweedfs-worker-lance-openrc -> /etc/init.d/seaweedfs.worker-lance
```
Replace Alpine's old generic OpenRC package before installing a role split:
@@ -82,16 +74,13 @@ Runtime paths:
/etc/init.d/seaweedfs.*
```
Edit `/etc/conf.d/seaweedfs.<role>` for flags. The package supplies a small set
of safe defaults in `/etc/seaweedfs/`; the complete upstream-generated scaffold
configs are available at:
Edit `/etc/conf.d/seaweedfs.<role>` for flags and `/etc/seaweedfs/*.toml` for
SeaweedFS config. Upstream examples:
```text
/usr/share/doc/seaweedfs/examples/
```
Copy and customize a scaffold file only when enabling its related feature.
Enable services:
```sh
@@ -103,11 +92,6 @@ rc-service seaweedfs.volume start
rc-update add seaweedfs.filer default
rc-service seaweedfs.filer start
# Optional: Lance table maintenance (requires a Lance namespace endpoint)
apk add seaweedfs-worker-lance-openrc
rc-update add seaweedfs.worker-lance default
rc-service seaweedfs.worker-lance start
```
Check status:
@@ -131,15 +115,6 @@ Bash completion:
apk add bash-completion seaweedfs-bash-completion
```
Log rotation for the default OpenRC service logs:
```sh
apk add seaweedfs-logrotate
```
This rotates `/var/log/seaweedfs/seaweedfs.*.log` daily and retains 14
compressed archives.
## Upgrade Or Pin
Upgrade:
@@ -152,5 +127,5 @@ rc-service seaweedfs.master restart
Pin:
```sh
apk add seaweedfs=4.47-r3
apk add seaweedfs=4.39-r0
```
@@ -1,4 +0,0 @@
# Disable automatic maintenance until the cluster's storage and replication
# policy has been reviewed. This setting is persisted in the admin data directory.
[maintenance]
enabled = false
@@ -1,3 +1,19 @@
# Use the existing filer store for credentials by default.
[credential.filer_etc]
enabled = true
[credential.postgres]
enabled = false
hostname = "localhost"
port = 5432
username = "seaweedfs"
password = ""
database = "seaweedfs"
schema = "public"
sslmode = "disable"
table_prefix = "sw_"
connection_max_idle = 10
connection_max_open = 100
connection_max_lifetime_seconds = 3600
[credential.memory]
enabled = false
@@ -1,71 +0,0 @@
# Put this file in one of the locations, with descending priority
# ./admin.toml
# $HOME/.seaweedfs/admin.toml
# /etc/seaweedfs/admin.toml
# this file is read by "weed admin"
# Maintenance task settings declared here are applied every time the admin
# server starts, overriding values saved from the admin UI under
# <dataDir>/conf. Commented-out keys keep their saved or default values.
# Requires -dataDir.
# Each value can also be set via environment variable, e.g.
# export WEED_MAINTENANCE_VACUUM_GARBAGE_THRESHOLD=0.3
[s3]
# The address clients reach the S3 gateway at, including the scheme.
# The file browser uses it to offer copyable object URLs; without it,
# the copy action is hidden.
# public_endpoint = "https://s3.example.com"
[maintenance]
# toggle the entire maintenance system (task detection and execution)
# enabled = true
[maintenance.vacuum]
# enabled = true
# vacuum volumes with more deleted content than this ratio
# garbage_threshold = 0.3
# how often to scan for volumes needing vacuum
# scan_interval_seconds = 7200
# max_concurrent = 2
# only vacuum volumes older than this (rounded up to whole hours)
# min_volume_age_seconds = 86400
# max retry attempts for a failed vacuum job (admin runtime default)
# retry_limit = 1
# seconds to wait between retry attempts
# retry_backoff_seconds = 10
[maintenance.balance]
# enabled = true
# trigger balancing when volume distribution exceeds this ratio
# imbalance_threshold = 0.2
# scan_interval_seconds = 1800
# max_concurrent = 1
# minimum number of volume servers before balancing
# min_server_count = 2
# max retry attempts for a failed balance job
# retry_limit = 1
# seconds to wait between retry attempts
# retry_backoff_seconds = 15
[maintenance.erasure_coding]
# enabled = true
# only erasure code volumes this full
# fullness_ratio = 0.95
# only erasure code volumes not modified for this long
# quiet_for_seconds = 3600
# scan_interval_seconds = 3600
# max_concurrent = 1
# min_size_mb = 30
# only process volumes from these collections, comma separated, "*" and "?" wildcards
# and regex patterns allowed ("" = all collections)
# collection_filter = ""
# disk tags preferred for shard placement
# preferred_tags = ["fast", "ssd"]
# EC shard placement constraint, e.g. "020"; empty uses the master default replication
# replica_placement = ""
# max retry attempts for a failed erasure coding job
# retry_limit = 1
# seconds to wait between retry attempts
# retry_backoff_seconds = 30
@@ -68,7 +68,7 @@ port = 3306
username = "root"
password = ""
database = "" # create or use an existing database
connection_max_idle = 50
connection_max_idle = 10
connection_max_open = 50
connection_max_lifetime_seconds = 300
interpolateParams = false
@@ -97,7 +97,7 @@ port = 3306
username = "root"
password = ""
database = "" # create or use an existing database
connection_max_idle = 50
connection_max_idle = 10
connection_max_open = 50
connection_max_lifetime_seconds = 300
interpolateParams = false
@@ -106,9 +106,13 @@ enableUpsert = true
upsertQuery = """INSERT INTO `%s` (`dirhash`,`name`,`directory`,`meta`) VALUES (?,?,?,?) AS `new` ON DUPLICATE KEY UPDATE `meta` = `new`.`meta`"""
[postgres] # or cockroachdb, YugabyteDB
# createTable = true # auto-create filemeta with the default schema
# createTable = false # skip table creation (default; for restricted DB roles)
# createTable = """CREATE TABLE IF NOT EXISTS "%s" (...)""" # custom template
# CREATE TABLE IF NOT EXISTS filemeta (
# dirhash BIGINT,
# name VARCHAR(65535),
# directory VARCHAR(65535),
# meta bytea,
# PRIMARY KEY (dirhash, name)
# );
enabled = false
hostname = "localhost"
port = 5432
@@ -123,7 +127,7 @@ sslmode = "disable"
# sslkey = "/path/to/client.key" # client private key file
# sslrootcert = "/path/to/ca.crt" # CA certificate file
# sslcrl = "/path/to/client.crl" # Certificate Revocation List (CRL) (optional)
connection_max_idle = 50
connection_max_idle = 10
connection_max_open = 50
connection_max_lifetime_seconds = 300
# Set to true when using PgBouncer connection pooler
@@ -162,7 +166,7 @@ sslmode = "disable"
# sslkey = "/path/to/client.key" # client private key file
# sslrootcert = "/path/to/ca.crt" # CA certificate file
# sslcrl = "/path/to/client.crl" # Certificate Revocation List (CRL) (optional)
connection_max_idle = 50
connection_max_idle = 10
connection_max_open = 50
connection_max_lifetime_seconds = 300
# Set to true when using PgBouncer connection pooler
@@ -226,23 +230,6 @@ client_cert_path = ""
client_key_path = ""
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
superLargeDirectories = []
# Connection tuning, accepted by every redis filer store section. Each key keeps the go-redis
# default when left at 0, and a timeout cannot be turned off - a filer that never times out a read
# is what stalls a failover. Shorter read timeouts make the filer notice a dead redis sooner, which
# matters most for the sentinel store: every pooled connection to the old master has to time out
# before a failover is absorbed.
# max_retries = 0 # 0 is three retries, -1 disables retrying
# min_retry_backoff_millisecond = 0 # default 8
# max_retry_backoff_millisecond = 0 # default 512
# dial_timeout_millisecond = 0 # default 5000
# read_timeout_millisecond = 0 # default 3000
# write_timeout_millisecond = 0 # default 3000, follows read_timeout_millisecond
# pool_size = 0 # default 10 per CPU
# pool_timeout_millisecond = 0 # default read_timeout_millisecond + 1000
# min_idle_conns = 0
# max_idle_conns = 0
# conn_max_idle_time_seconds = 0 # default 1800
# conn_max_lifetime_seconds = 0 # default unlimited
[redis2_sentinel]
enabled = false
@@ -250,9 +237,6 @@ addresses = ["172.22.12.7:26379","172.22.12.8:26379","172.22.12.9:26379"]
masterName = "master"
username = ""
password = ""
# credentials used to authenticate against the sentinel nodes themselves (if they require auth)
sentinel_username = ""
sentinel_password = ""
database = 0
# prefix for filer redis keys
keyPrefix = ""
@@ -260,7 +244,6 @@ enable_tls = false
ca_cert_path = ""
client_cert_path = ""
client_key_path = ""
# see [redis2] for the connection tuning keys
[redis_cluster2]
enabled = false
@@ -281,7 +264,7 @@ ca_cert_path = ""
client_cert_path = ""
client_key_path = ""
# allows reads from slave servers or the master, but all writes still go to the master
useReadOnly = false
readOnly = false
# automatically use the closest Redis server for reads
routeByLatency = false
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
@@ -52,7 +52,6 @@ copy_2 = 6 # create 2 x 6 = 12 actual volumes
copy_3 = 3 # create 3 x 3 = 9 actual volumes
copy_other = 1 # create n x 1 = n actual volumes
threshold = 0.9 # create threshold
reservation_timeout = "5m"# capacity reservation timeout before unreleased reservations expire
disable = false # disables volume growth if true
# configuration flags for replication
@@ -59,17 +59,7 @@ is_incremental = false
# experimental, let me know if it works
enabled = false
account_name = ""
# leave account_key empty to authenticate with Entra ID instead of a shared key,
# picking up a workload identity or managed identity from the environment. The
# identity needs a data-plane role such as Storage Blob Data Contributor.
account_key = ""
# optional user-assigned identity, when account_key is empty. Workload identity
# takes its tenant and token from AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE,
# which the Azure workload identity webhook projects into the pod.
client_id = ""
# blob service url, for accounts outside the public cloud. Empty resolves to
# https://<account_name>.blob.core.windows.net/
endpoint = ""
container = "mycontainer" # an existing container
directory = "/" # destination directory
is_incremental = false
@@ -77,12 +77,6 @@ expires_after_seconds = 10 # seconds
# All gRPC TLS authentications are mutual (mTLS)
# The values for ca, cert, and key are paths to the certificate/key files
# The host name is not checked, so the certificate files can be shared
# Each [grpc.<component>] section also accepts optional client_cert/client_key,
# presented when that component dials other servers. Set them when your CA
# issues separate serverAuth-only and clientAuth-only certificates; when unset,
# the component reuses cert/key for both directions.
# If client and server certificates come from different issuing CAs, put both
# CA certificates in the ca PEM file.
[grpc]
ca = ""
# Set wildcard domain for enable TLS authentication by common names
@@ -93,8 +87,6 @@ allowed_wildcard_domain = "" # .mycompany.com
[grpc.volume]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
# Master server gRPC options (server-side)
@@ -102,8 +94,6 @@ allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.master]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
# Filer server gRPC options (server-side)
@@ -111,8 +101,6 @@ allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.filer]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
# S3 server gRPC options (server-side)
@@ -120,43 +108,31 @@ allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.s3]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.msg_broker]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.msg_agent]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.admin]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.worker]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.mq]
cert = ""
key = ""
client_cert = ""
client_key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
# gRPC client configuration for outgoing gRPC connections
@@ -232,15 +208,6 @@ kek = ""
# Cannot be used while /etc/s3/sse_kek exists on the filer — delete it first.
key = ""
# Trusted reverse proxies allowed to set X-Forwarded-For / X-Real-Ip for
# aws:SourceIp condition evaluation in S3 bucket and IAM policies. When the
# direct TCP peer is in this list, forwarded headers are honored; otherwise
# the direct peer address is used (matching AWS S3 semantics). Leave empty to
# always use the direct peer, which is the safe default.
# Can also be set via env var: WEED_S3_TRUSTED_PROXIES_WHITE_LIST
[s3.trusted_proxies]
white_list = "" # comma separated; bare IPs or CIDRs, e.g. "10.10.10.0/24"
# white list. It's checking request ip address.
[guard]
white_list = ""
@@ -1,30 +0,0 @@
# Put this file to one of the location, with descending priority
# ./volume.toml
# $HOME/.seaweedfs/volume.toml
# /etc/seaweedfs/volume.toml
# this file is read by volume servers
[volume.disk.io]
# Disk IO probing is disabled by default. When enabled, a volume server can
# stop advertising a disk after sustained IO errors or latency degradation.
probe = false
timeout = "2s"
interval = "60s"
window = "1m"
min.samples = 10
max.stat.failures = 5
recovery.coef = 0.5
[volume.disk.io.slow]
percent = 20
[volume.disk.io.error]
percent = 10
# slow threshold per disk type, matched against each -dir's -disk tag.
# a disk whose type is not listed here uses the hdd threshold.
[volume.disk.io.slow.latency]
hdd = "500ms"
ssd = "100ms"
nvme = "50ms"
+43 -1
View File
@@ -1,4 +1,46 @@
# Store standalone filer metadata in the package-managed data directory.
[filer.options]
recursive_delete = false
[leveldb2]
enabled = true
dir = "/var/lib/seaweedfs/filer/meta"
[sqlite]
enabled = false
dbFile = "/var/lib/seaweedfs/filer/filer.db"
[mysql]
enabled = false
dsn = "root@tcp(localhost:3306)/seaweedfs?collation=utf8mb4_bin"
enable_tls = false
hostname = "localhost"
port = 3306
username = "root"
password = ""
database = ""
connection_max_idle = 10
connection_max_open = 50
connection_max_lifetime_seconds = 300
interpolateParams = false
enableUpsert = true
[postgres]
enabled = false
hostname = "localhost"
port = 5432
username = "postgres"
password = ""
database = "postgres"
schema = ""
sslmode = "disable"
connection_max_idle = 10
connection_max_open = 50
connection_max_lifetime_seconds = 300
pgbouncer_compatible = false
enableUpsert = true
[redis2]
enabled = false
address = "localhost:6379"
password = ""
database = 0
+25 -1
View File
@@ -1,3 +1,27 @@
# Disable scheduled maintenance until it is explicitly configured.
[master.maintenance]
scripts = ""
sleep_minutes = 17
[master.sequencer]
type = "raft"
sequencer_snowflake_id = 0
[storage.backend.s3.default]
enabled = false
aws_access_key_id = ""
aws_secret_access_key = ""
region = "us-east-2"
bucket = ""
endpoint = ""
storage_class = "STANDARD_IA"
[master.volume_growth]
copy_1 = 7
copy_2 = 6
copy_3 = 3
copy_other = 1
threshold = 0.9
disable = false
[master.replication]
treat_replication_as_minimums = false
@@ -0,0 +1,42 @@
[notification.log]
enabled = false
[notification.kafka]
enabled = false
hosts = ["localhost:9092"]
topic = "seaweedfs_filer"
offsetFile = "/var/lib/seaweedfs/filer/last.offset"
offsetSaveIntervalSeconds = 10
sasl_enabled = false
sasl_mechanism = "PLAIN"
sasl_username = ""
sasl_password = ""
tls_enabled = false
tls_ca_cert = ""
tls_client_cert = ""
tls_client_key = ""
tls_insecure_skip_verify = false
[notification.aws_sqs]
enabled = false
aws_access_key_id = ""
aws_secret_access_key = ""
region = "us-east-2"
sqs_queue_name = ""
[notification.google_pub_sub]
enabled = false
google_application_credentials = ""
project_id = ""
topic = ""
[notification.webhook]
enabled = false
endpoint = ""
bearer_token = ""
timeout_seconds = 10
max_retries = 3
backoff_seconds = 3
max_backoff_seconds = 30
workers = 5
buffer_size = 10000
@@ -0,0 +1,29 @@
[source.filer]
enabled = false
grpcAddress = "localhost:18888"
directory = "/buckets"
excludeDirectories = "/buckets/tmp"
[sink.local]
enabled = false
directory = "/var/lib/seaweedfs/backup"
is_incremental = false
[sink.filer]
enabled = false
grpcAddress = "localhost:18888"
directory = "/backup"
replication = ""
collection = ""
ttlSec = 0
is_incremental = false
[sink.s3]
enabled = false
aws_access_key_id = ""
aws_secret_access_key = ""
region = "us-east-2"
bucket = ""
directory = "/"
endpoint = ""
is_incremental = false
@@ -6,26 +6,20 @@ apk add seaweedfs \
bash-completion \
seaweedfs-master-openrc \
seaweedfs-volume-openrc \
seaweedfs-filer-openrc \
seaweedfs-worker-lance-openrc
seaweedfs-filer-openrc
test -x /usr/bin/weed
test -d /etc/seaweedfs
test -f /etc/seaweedfs/master.toml
test -f /etc/seaweedfs/filer.toml
test -f /etc/seaweedfs/admin.toml
test -f /etc/conf.d/seaweedfs.master
test -f /etc/conf.d/seaweedfs.volume
test -f /etc/conf.d/seaweedfs.filer
test -f /etc/init.d/seaweedfs.master
test -f /etc/init.d/seaweedfs.volume
test -f /etc/init.d/seaweedfs.filer
test -f /etc/init.d/seaweedfs.worker-lance
test -x /usr/bin/weed-worker
/usr/bin/weed-worker --help >/dev/null
test -d /usr/share/doc/seaweedfs/examples
test -f /usr/share/doc/seaweedfs/examples/master.toml
test -f /usr/share/doc/seaweedfs/examples/volume.toml
test -f /usr/share/bash-completion/completions/weed
weed version
@@ -41,8 +35,3 @@ rc-service seaweedfs.filer start
rc-service seaweedfs.master status
rc-service seaweedfs.volume status
rc-service seaweedfs.filer status
# SeaweedFS needs more than OpenRC's default stop timeout to finish its
# graceful volume-server shutdown. Keep the restart path covered.
rc-service seaweedfs.volume restart
rc-service seaweedfs.volume status
@@ -15,27 +15,18 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-seaweedfs}" "${PACKAGE_VERS
apk add seaweedfs \
seaweedfs-master-openrc \
seaweedfs-volume-openrc \
seaweedfs-filer-openrc \
seaweedfs-logrotate \
seaweedfs-worker-lance-openrc
seaweedfs-filer-openrc
test -x /usr/bin/weed
test -d /etc/seaweedfs
test -f /etc/seaweedfs/master.toml
test -f /etc/seaweedfs/filer.toml
test -f /etc/seaweedfs/admin.toml
test -f /etc/conf.d/seaweedfs.master
test -f /etc/conf.d/seaweedfs.volume
test -f /etc/conf.d/seaweedfs.filer
test -f /etc/init.d/seaweedfs.master
test -f /etc/init.d/seaweedfs.volume
test -f /etc/init.d/seaweedfs.filer
test -f /etc/init.d/seaweedfs.worker-lance
test -f /etc/logrotate.d/seaweedfs
apk info -e logrotate
logrotate -d /etc/logrotate.conf
test -x /usr/bin/weed-worker
/usr/bin/weed-worker --help >/dev/null
weed version
@@ -50,6 +41,5 @@ apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-seaweedfs}" "${PACKAGE_VERS
apk info -e seaweedfs-bash-completion
test -d /usr/share/doc/seaweedfs/examples
test -f /usr/share/doc/seaweedfs/examples/master.toml
test -f /usr/share/doc/seaweedfs/examples/volume.toml
test -f /usr/share/bash-completion/completions/weed
SCRIPT
@@ -2,31 +2,34 @@
set -euo pipefail
package_dir="${PACKAGE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
configs=(admin credential filer master volume notification replication security shell)
configs=(credential filer master notification replication security shell)
pkgver="$(
awk -F= '$1 == "pkgver" { print $2; exit }' "${package_dir}/APKBUILD"
)"
tmpdir="$(mktemp -d)"
repo_root="${REPO_ROOT:-$(cd "${package_dir}/../../../.." && pwd)}"
source_archive="${repo_root}/.cache/apk-distfiles/seaweedfs-${pkgver}-src.tar.gz"
cleanup() {
rm -rf "${tmpdir}"
}
trap cleanup EXIT
if [[ ! -f "${source_archive}" ]]; then
source_archive="${tmpdir}/seaweedfs-${pkgver}-src.tar.gz"
curl -fsSL \
-o "${source_archive}" \
"https://github.com/seaweedfs/seaweedfs/archive/refs/tags/${pkgver}.tar.gz"
fi
tar -xzf "${source_archive}" -C "${tmpdir}"
source_dir="${tmpdir}/seaweedfs-${pkgver}"
(
cd "${source_dir}"
go build -mod=readonly -buildvcs=false -trimpath -o "${tmpdir}/weed" ./weed
)
case "$(uname -m)" in
x86_64)
archive="linux_amd64.tar.gz"
;;
aarch64|arm64)
archive="linux_arm64.tar.gz"
;;
*)
printf 'unsupported host architecture for SeaweedFS generated sources: %s\n' "$(uname -m)" >&2
exit 2
;;
esac
curl -fsSL \
-o "${tmpdir}/${archive}" \
"https://github.com/seaweedfs/seaweedfs/releases/download/${pkgver}/${archive}"
tar -xzf "${tmpdir}/${archive}" -C "${tmpdir}" weed
for config in "${configs[@]}"; do
"${tmpdir}/weed" scaffold -config "${config}" 2>/dev/null \
@@ -6,9 +6,6 @@ description="SeaweedFS ${service_name} service"
command="/usr/bin/weed"
command_user="${SEAWEEDFS_USER:-seaweedfs}:${SEAWEEDFS_GROUP:-seaweedfs}"
command_background="yes"
# SeaweedFS performs a graceful shutdown, including a 10-second final heartbeat.
# The OpenRC default stop timeout can expire before that work has completed.
retry="TERM/30/KILL/5"
pidfile="/run/seaweedfs/${RC_SVCNAME}.pid"
output_log="${SEAWEEDFS_LOG:-/var/log/seaweedfs/${RC_SVCNAME}.log}"
error_log="${SEAWEEDFS_ERRLOG:-/var/log/seaweedfs/${RC_SVCNAME}.log}"
@@ -49,10 +46,6 @@ build_command_args() {
data_dir="${SEAWEEDFS_DATA_DIR:-/var/lib/seaweedfs/worker}"
command_args="$command_args -admin=${SEAWEEDFS_ADMIN:-localhost:23646} -workingDir=${data_dir}"
;;
worker-lance)
command="/usr/bin/weed-worker"
command_args="--admin ${SEAWEEDFS_ADMIN:-localhost:23646} --namespace ${SEAWEEDFS_LANCE_NAMESPACE:-http://localhost:9101}"
;;
esac
command_args="$command_args ${SEAWEEDFS_OPTS:-}"
@@ -69,7 +62,7 @@ depend() {
s3|webdav|sftp)
after seaweedfs.filer
;;
worker|worker-lance)
worker)
after seaweedfs.admin
;;
esac
@@ -1,10 +0,0 @@
/var/log/seaweedfs/seaweedfs.*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
copytruncate
su seaweedfs seaweedfs
}
@@ -1,4 +0,0 @@
# Lance maintenance worker. It is optional and requires a Lance namespace.
SEAWEEDFS_ADMIN="localhost:23646"
SEAWEEDFS_LANCE_NAMESPACE="http://localhost:9101"
SEAWEEDFS_OPTS=""
+102 -1
View File
@@ -1,3 +1,104 @@
# Do not expose the administrative UI by default.
[cors.allowed_origins]
values = "*"
[jwt.signing]
key = ""
expires_after_seconds = 10
[access]
ui = false
[filer.expose_directory_metadata]
enabled = true
[jwt.signing.read]
key = ""
expires_after_seconds = 10
[jwt.filer_signing]
key = ""
expires_after_seconds = 10
[jwt.filer_signing.read]
key = ""
expires_after_seconds = 10
[grpc]
ca = ""
allowed_wildcard_domain = ""
[grpc.volume]
cert = ""
key = ""
allowed_commonNames = ""
[grpc.master]
cert = ""
key = ""
allowed_commonNames = ""
[grpc.filer]
cert = ""
key = ""
allowed_commonNames = ""
[grpc.s3]
cert = ""
key = ""
allowed_commonNames = ""
[grpc.admin]
cert = ""
key = ""
allowed_commonNames = ""
[grpc.worker]
cert = ""
key = ""
allowed_commonNames = ""
[grpc.client]
cert = ""
key = ""
[https.client]
enabled = false
cert = ""
key = ""
ca = ""
insecure_skip_verify = false
[https.volume]
cert = ""
key = ""
ca = ""
[https.master]
cert = ""
key = ""
ca = ""
[https.filer]
cert = ""
key = ""
ca = ""
[https.admin]
cert = ""
key = ""
ca = ""
[admin]
user = ""
password = ""
[admin.readonly]
user = ""
password = ""
[s3.sse]
kek = ""
key = ""
[guard]
white_list = ""
@@ -0,0 +1,8 @@
[cluster]
default = "c1"
[cluster.c1]
master = "localhost:9333" # comma-separated master servers
[cluster.c2]
master = ""
-3
View File
@@ -4,9 +4,6 @@ FROM alpine:${ALPINE_VERSION}
ARG BUILDER_UID=1000
ARG BUILDER_GID=1000
RUN printf '%s\n' 'https://dl-cdn.alpinelinux.org/alpine/edge/community' \
>> /etc/apk/repositories
RUN apk add --no-cache \
abuild-rootbld \
alpine-sdk \
+2 -24
View File
@@ -10,7 +10,6 @@ arches="${ALPINE_ARCHES:-x86_64 aarch64}"
packager="${PACKAGER:-local}"
selected_packages="${ALPINE_PACKAGE:-${ALPINE_PACKAGES:-}}"
skip_build="${ALPINE_SKIP_BUILD:-0}"
rust_cache_root="${ALPINE_RUST_CACHE_ROOT:-}"
if [[ "${skip_build}" == "1" ]]; then
printf 'Skipping package build: restored package cache is complete\n'
@@ -25,7 +24,7 @@ if [[ "${1:-}" != "--as-builder" && "$(id -u)" == "0" ]]; then
printf 'permit nopass :wheel\n' > /etc/doas.d/wheel.conf
printf '%%wheel ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/wheel
chown -R builder:builder "${repo_root}"
exec su builder -c "ALPINE_ARCHES='${arches}' ALPINE_REPO_NAME='${repo_name}' ALPINE_PACKAGES='${selected_packages}' PACKAGER='${packager}' ALPINE_RUST_CACHE_ROOT='${rust_cache_root}' '${BASH_SOURCE[0]}' --as-builder"
exec su builder -c "ALPINE_ARCHES='${arches}' ALPINE_REPO_NAME='${repo_name}' ALPINE_PACKAGES='${selected_packages}' PACKAGER='${packager}' '${BASH_SOURCE[0]}' --as-builder"
fi
export PACKAGER="${packager}"
@@ -50,13 +49,7 @@ if [[ ! -e "${HOME}/.abuild/abuild.conf" && -d "${repo_root}/.cache/abuild" ]];
fi
if ! compgen -G "${HOME}/.abuild/*.rsa" > /dev/null; then
# APK signatures identify their public key by filename. Matrix workers can
# otherwise generate different builder-<timestamp>.rsa keys with the same
# name when they start during the same second, making their artifacts
# impossible to merge. Use the selected package only while generating the
# key so the package metadata retains the configured PACKAGER value.
key_identity="${ALPINE_PACKAGE:-ci}"
PACKAGER="CI key <ci-${key_identity}@local.invalid>" abuild-keygen -a -n
abuild-keygen -a -n
fi
doas cp "${HOME}"/.abuild/*.rsa.pub /etc/apk/keys/
@@ -79,21 +72,6 @@ while IFS= read -r package_dir; do
printf 'Building %s for %s\n' "$(basename "${package_dir}")" "${arch}"
(
package_name="$(apk_package_name "${package_dir}")"
if [[ -n "${rust_cache_root}" ]]; then
case "${package_name}" in
greptimedb)
export CARGO_HOME="${rust_cache_root}/greptimedb/cargo"
export RUSTUP_HOME="${rust_cache_root}/greptimedb/rustup"
export CARGO_TARGET_DIR="${rust_cache_root}/greptimedb/target"
;;
seaweedfs)
export CARGO_HOME="${rust_cache_root}/seaweedfs/cargo"
export CARGO_TARGET_DIR="${rust_cache_root}/seaweedfs/target"
unset RUSTUP_HOME
;;
esac
fi
cd "${package_dir}"
ALPINE_ARCH="${arch}" CARCH="${arch}" abuild -r
)
+200 -124
View File
@@ -5,169 +5,245 @@ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=scripts/apk/package-lib.sh
. "${repo_root}/scripts/apk/package-lib.sh"
repo_name="${ALPINE_REPO_NAME:-local}"
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
branch="${ALPINE_REGISTRY_BRANCH:-v${ALPINE_VERSION:-3.24}}"
repository="${ALPINE_REGISTRY_REPOSITORY:-${PACKAGE_NAME:-main}}"
instance_url="${INSTANCE_URL:-}"
owner="${PACKAGE_OWNER:-}"
cache_root="${ALPINE_APK_REPO_CACHE:-/cache/public-alpine-packages/${ALPINE_REGISTRY_BRANCH:-local}/apk-repo}"
repo_dest="${repo_root}/packages/${repo_name}"
command_name="${1:-prepare}"
registry_cache="${CI_REGISTRY_CACHE_DIR:-${repo_root}/.cache/ci-registry}"
require_registry_config() {
local name="$1" value="$2"
[[ -n "${value}" ]] && return
printf 'missing required CI registry setting: %s\n' "${name}" >&2
exit 2
all_packages() {
while IFS= read -r package_dir; do
apk_package_name "${package_dir}"
done < <(apk_all_package_dirs "${repo_root}")
}
registry_url() {
printf '%s/api/packages/%s/alpine/%s/%s\n' \
"${instance_url%/}" "${owner}" "${branch}" "${repository}"
mark_all_packages() {
local reason="$1"
printf 'Rebuilding all packages: %s\n' "${reason}" >&2
all_packages
}
registry_key_url() {
printf '%s/api/packages/%s/alpine/key\n' "${instance_url%/}" "${owner}"
diff_base() {
local before="${GITHUB_EVENT_BEFORE:-${CI_COMMIT_BEFORE_SHA:-}}"
local base_ref="${GITHUB_BASE_REF:-}"
if [[ -n "${base_ref}" ]] && git rev-parse --verify "origin/${base_ref}" >/dev/null 2>&1; then
printf '%s...HEAD\n' "origin/${base_ref}"
return
fi
if [[ -n "${before}" && ! "${before}" =~ ^0+$ ]] && git rev-parse --verify "${before}^{commit}" >/dev/null 2>&1; then
printf '%s..HEAD\n' "${before}"
return
fi
if git rev-parse --verify "HEAD^" >/dev/null 2>&1; then
printf 'HEAD^..HEAD\n'
return
fi
return 1
}
download_registry_metadata() {
local arch url key_dir http_status
changed_packages() {
local base
local changed_paths
local changed_path
local package
declare -A selected=()
require_registry_config INSTANCE_URL "${instance_url}"
require_registry_config PACKAGE_OWNER "${owner}"
declare -gA registry_index_available=()
mkdir -p "${registry_cache}"
url="$(registry_url)"
for arch in ${arches}; do
if http_status="$(curl --fail --silent --location \
--output "${registry_cache}/${arch}.APKINDEX.tar.gz" \
--write-out '%{http_code}' \
"${url}/${arch}/APKINDEX.tar.gz")"; then
registry_index_available["${arch}"]=1
continue
fi
if [[ "${http_status}" == 404 ]]; then
registry_index_available["${arch}"]=0
printf 'Registry index is absent: %s/%s/APKINDEX.tar.gz; treating it as empty\n' \
"${url}" "${arch}" >&2
continue
fi
printf 'failed to download registry index (%s): %s/%s/APKINDEX.tar.gz\n' \
"${http_status:-curl error}" "${url}" "${arch}" >&2
return 1
done
key_dir="${registry_cache}/keys"
mkdir -p "${key_dir}"
find "${key_dir}" -maxdepth 1 -type f -name '*.rsa.pub' -delete
curl --fail --silent --show-error --location \
--remote-name --remote-header-name --output-dir "${key_dir}" \
"$(registry_key_url)"
registry_key_path="$(find "${key_dir}" -maxdepth 1 -type f -name '*.rsa.pub' -print -quit)"
if [[ -z "${registry_key_path}" ]]; then
printf 'registry signing key was not downloaded: %s\n' "$(registry_key_url)" >&2
exit 1
if ! base="$(diff_base)"; then
mark_all_packages "no usable git diff base"
return
fi
if ! changed_paths="$(git diff --name-only "${base}")"; then
mark_all_packages "git diff failed for ${base}"
return
fi
while IFS= read -r changed_path; do
[[ -n "${changed_path}" ]] || continue
case "${changed_path}" in
scripts/apk/*|.gitea/workflows/build.yml|mise.toml)
mark_all_packages "shared build logic changed"
return
;;
packaging/alpine/local/*)
package="${changed_path#packaging/alpine/local/}"
package="${package%%/*}"
selected["${package}"]=1
;;
esac
done <<< "${changed_paths}"
for package in "${!selected[@]}"; do
printf '%s\n' "${package}"
done | sort
}
restore_cache() {
if [[ -d "${cache_root}" ]]; then
mkdir -p "${repo_dest}"
cp -a "${cache_root}/." "${repo_dest}/"
printf 'Restored Alpine package repository cache from %s\n' "${cache_root}"
else
printf 'No Alpine package repository cache found at %s\n' "${cache_root}"
fi
}
load_registry_index() {
local arch package_name package_version registry_key comparison
declare -gA registry_latest_versions=()
package_apk_names() {
local package_dir="$1"
local arch="$2"
for arch in ${arches}; do
[[ "${registry_index_available[${arch}]:-0}" == 1 ]] || continue
while IFS=$'\t' read -r package_name package_version; do
[[ -n "${package_name}" && -n "${package_version}" ]] || continue
registry_key="${arch}|${package_name}"
if [[ -z "${registry_latest_versions[${registry_key}]:-}" ]]; then
registry_latest_versions["${registry_key}"]="${package_version}"
continue
fi
comparison="$(apk version -t "${package_version}" "${registry_latest_versions[${registry_key}]}")"
if [[ "${comparison}" == ">" ]]; then
registry_latest_versions["${registry_key}"]="${package_version}"
fi
done < <(
tar -xOzf "${registry_cache}/${arch}.APKINDEX.tar.gz" APKINDEX | awk '
/^P:/ { package = substr($0, 3); next }
/^V:/ { if (package != "") print package "\t" substr($0, 3); package = "" }
'
)
done
apk_package_apk_names "${package_dir}" "${arch}"
}
registry_upgrade_packages() {
local package_dir package_name arch candidate_spec candidate_version published_version comparison selected
package_cache_complete() {
local package_dir="$1"
local package_name
local arch
local apk_name
package_name="$(apk_package_name "${package_dir}")"
for arch in ${arches}; do
case "${arch}" in
x86_64|aarch64) ;;
*) printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2; exit 2 ;;
esac
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
continue
fi
while IFS= read -r apk_name; do
if [[ ! -f "${repo_dest}/${arch}/${apk_name}" ]]; then
printf 'Cache miss for %s: missing %s/%s\n' "${package_name}" "${arch}" "${apk_name}" >&2
return 1
fi
done < <(package_apk_names "${package_dir}" "${arch}")
done
return 0
}
select_missing_packages() {
local package_dir
local package_name
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
package_name="$(apk_package_name "${package_dir}")"
selected=0
for arch in ${arches}; do
apk_package_supports_arch "${package_dir}" "${arch}" || continue
IFS= read -r candidate_spec < <(apk_package_versioned_names "${package_dir}" "${arch}")
candidate_version="${candidate_spec#*=}"
published_version="${registry_latest_versions[${arch}|${package_name}]:-}"
if [[ -z "${published_version}" ]]; then
selected=1
printf 'Registry miss: %s (%s, %s)\n' "${package_name}" "${arch}" "${candidate_spec}" >&2
continue
fi
comparison="$(apk version -t "${candidate_version}" "${published_version}")"
if [[ "${comparison}" == ">" ]]; then
selected=1
printf 'Registry upgrade: %s (%s, %s -> %s)\n' \
"${package_name}" "${arch}" "${published_version}" "${candidate_version}" >&2
else
printf 'Registry current: %s (%s, source %s; published %s)\n' \
"${package_name}" "${arch}" "${candidate_version}" "${published_version}" >&2
fi
done
[[ "${selected}" == 1 ]] && printf '%s\n' "${package_name}"
if ! package_cache_complete "${package_dir}"; then
printf '%s\n' "${package_name}"
fi
done < <(apk_all_package_dirs "${repo_root}")
}
prune_stale_apks() {
local package_dir
local arch
local apk_name
local current_apk
declare -A expected_apks=()
if [[ ! -d "${repo_dest}" ]]; then
return
fi
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
for arch in ${arches}; do
case "${arch}" in
x86_64|aarch64) ;;
*) printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2; exit 2 ;;
esac
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
continue
fi
while IFS= read -r apk_name; do
expected_apks["${repo_dest}/${arch}/${apk_name}"]=1
done < <(package_apk_names "${package_dir}" "${arch}")
done
done < <(apk_all_package_dirs "${repo_root}")
shopt -s nullglob
for current_apk in "${repo_dest}"/*/*.apk; do
if [[ -z "${expected_apks[${current_apk}]:-}" ]]; then
rm -f "${current_apk}"
printf 'Pruned stale cached APK: %s\n' "${current_apk#"${repo_root}/"}"
fi
done
shopt -u nullglob
}
prepare() {
local selected_packages
local selected
declare -A selected_map=()
download_registry_metadata
load_registry_index
while IFS= read -r selected; do
[[ -n "${selected}" ]] && selected_map["${selected}"]=1
done < <(registry_upgrade_packages)
restore_cache
prune_stale_apks
ALPINE_PACKAGES="$(for selected in "${!selected_map[@]}"; do printf '%s\n' "${selected}"; done | sort | xargs)"
if [[ -n "${ALPINE_PACKAGES}" ]]; then
ALPINE_SKIP_BUILD=0
printf 'Selected packages for rebuild: %s\n' "${ALPINE_PACKAGES}"
while IFS= read -r selected; do
[[ -n "${selected}" ]] || continue
selected_map["${selected}"]=1
done < <(changed_packages)
while IFS= read -r selected; do
[[ -n "${selected}" ]] || continue
selected_map["${selected}"]=1
done < <(select_missing_packages)
selected_packages="$(
for selected in "${!selected_map[@]}"; do
printf '%s\n' "${selected}"
done | sort | xargs
)"
if [[ -n "${selected_packages}" ]]; then
printf 'Selected packages for rebuild: %s\n' "${selected_packages}"
export ALPINE_PACKAGES="${selected_packages}"
export ALPINE_SKIP_BUILD=0
else
ALPINE_SKIP_BUILD=1
printf 'No packages selected for rebuild: registry has equal or newer package versions\n'
printf 'No packages selected for rebuild\n'
export ALPINE_PACKAGES=""
export ALPINE_SKIP_BUILD=1
fi
if [[ -n "${GITHUB_ENV:-}" ]]; then
{
printf 'ALPINE_PACKAGES=%s\n' "${ALPINE_PACKAGES}"
printf 'ALPINE_SKIP_BUILD=%s\n' "${ALPINE_SKIP_BUILD}"
printf 'ALPINE_REGISTRY_URL=%s\n' "$(registry_url)"
printf 'ALPINE_REGISTRY_KEY=%s\n' "${registry_key_path}"
} >> "${GITHUB_ENV}"
fi
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
printf 'selected_packages=%s\n' "${ALPINE_PACKAGES}" >> "${GITHUB_OUTPUT}"
if [[ -n "${ALPINE_PACKAGES}" ]]; then
printf 'packages_selected=true\n' >> "${GITHUB_OUTPUT}"
else
printf 'packages_selected=false\n' >> "${GITHUB_OUTPUT}"
fi
if [[ " ${ALPINE_PACKAGES} " == *" greptimedb "* ]]; then
printf 'greptimedb_selected=true\n' >> "${GITHUB_OUTPUT}"
else
printf 'greptimedb_selected=false\n' >> "${GITHUB_OUTPUT}"
fi
}
sync_cache() {
if [[ ! -d "${repo_dest}" ]]; then
printf 'missing package repository: %s\n' "${repo_dest}" >&2
exit 1
fi
prune_stale_apks
mkdir -p "${cache_root}"
rsync -a --delete "${repo_dest}/" "${cache_root}/"
printf 'Updated Alpine package repository cache at %s\n' "${cache_root}"
}
case "${command_name}" in
prepare) prepare ;;
*) printf 'usage: %s prepare\n' "$0" >&2; exit 2 ;;
prepare)
prepare
;;
sync)
sync_cache
;;
*)
printf 'usage: %s [prepare|sync]\n' "$0" >&2
exit 2
;;
esac
+5 -53
View File
@@ -2,62 +2,19 @@
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=scripts/apk/package-lib.sh
. "${repo_root}/scripts/apk/package-lib.sh"
repo_name="${ALPINE_REPO_NAME:-local}"
arch="${ALPINE_ARCH:-$(apk --print-arch)}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb lavinmq lavinmq-openrc gitea gitea-openrc rclone-openrc}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb lavinmq lavinmq-openrc gitea gitea-openrc}"
repo_dir="${repo_root}/packages/${repo_name}/${arch}"
registry_url="${ALPINE_REGISTRY_URL:-}"
registry_key="${ALPINE_REGISTRY_KEY:-}"
read -r -a package_list <<< "${packages}"
declare -A source_packages=()
local_repo_complete=0
while IFS= read -r package_dir; do
while IFS= read -r spec; do
source_packages["${spec%%=*}"]=1
done < <(apk_package_versioned_names "${package_dir}" "${arch}")
done < <(apk_all_package_dirs "${repo_root}")
for package in "${package_list[@]}"; do
if [[ -z "${source_packages[${package}]:-}" ]]; then
printf 'smoke package is not defined by a source APKBUILD: %s\n' "${package}" >&2
exit 2
fi
done
if [[ -d "${repo_dir}" ]]; then
local_repo_complete=1
for package in "${package_list[@]}"; do
if ! compgen -G "${repo_dir}/${package}-*.apk" >/dev/null; then
local_repo_complete=0
break
fi
done
fi
if [[ -d "${repo_dir}" ]]; then
cp "${repo_dir}"/*.rsa.pub /etc/apk/keys/
echo "${repo_root}/packages/${repo_name}" >> /etc/apk/repositories
fi
if [[ -n "${registry_url}" && "${local_repo_complete}" == 0 ]]; then
if [[ ! -f "${registry_key}" ]]; then
printf 'missing Alpine registry signing key: %s\n' "${registry_key:-<unset>}" >&2
exit 1
fi
cp "${registry_key}" /etc/apk/keys/
echo "${registry_url}" >> /etc/apk/repositories
elif [[ -n "${registry_url}" ]]; then
printf 'Using the complete local Alpine repository; registry fallback is not needed\n'
fi
if [[ ! -d "${repo_dir}" && -z "${registry_url}" ]]; then
printf 'missing local repository and no registry fallback: packages/%s/%s\n' "${repo_name}" "${arch}" >&2
if [[ ! -d "${repo_dir}" ]]; then
printf 'missing local repository: packages/%s/%s\n' "${repo_name}" "${arch}" >&2
exit 1
fi
cp "${repo_dir}"/*.rsa.pub /etc/apk/keys/
echo "${repo_root}/packages/${repo_name}" >> /etc/apk/repositories
apk update
apk add "${package_list[@]}"
if command -v weed >/dev/null 2>&1; then
@@ -77,11 +34,6 @@ if command -v gitea >/dev/null 2>&1; then
test -f /etc/gitea/app.ini
test -d /var/lib/gitea
fi
if command -v rclone >/dev/null 2>&1; then
rclone version
test -f /etc/conf.d/rclone
test -f /etc/init.d/rclone
fi
if ls /etc/init.d/seaweedfs.* >/dev/null 2>&1; then
find /etc/init.d -maxdepth 1 -name 'seaweedfs.*' -print | sort
fi
-103
View File
@@ -1,103 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
repo_name="${ALPINE_REPO_NAME:-local}"
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
artifact_root="${APK_CI_ARTIFACTS_DIR:-${repo_root}/packages/worker-artifacts}"
package_root="${APK_CI_PACKAGE_ROOT:-${repo_root}/packages/${repo_name}}"
keys_root="$(mktemp -d)"
cleanup() {
rm -rf "${keys_root}"
}
trap cleanup EXIT
require_command() {
command -v "$1" >/dev/null 2>&1 || {
printf 'missing required command: %s\n' "$1" >&2
exit 2
}
}
copy_key() {
local key="$1"
local destination="$2"
local key_name
key_name="$(basename "${key}")"
if [[ -e "${destination}/${key_name}" ]]; then
if cmp -s "${key}" "${destination}/${key_name}"; then
return
fi
printf 'conflicting public keys named %s\n' "${key_name}" >&2
exit 1
fi
cp "${key}" "${destination}/${key_name}"
}
require_command abuild-keygen
require_command abuild-sign
require_command apk
if [[ ! -d "${artifact_root}" ]]; then
printf 'missing worker artifacts directory: %s\n' "${artifact_root}" >&2
exit 1
fi
rm -rf "${package_root}"
mkdir -p "${package_root}" "${HOME}/.abuild"
if ! compgen -G "${HOME}/.abuild/*.rsa" > /dev/null; then
abuild-keygen -a -n
fi
shopt -s nullglob
merge_private_keys=("${HOME}"/.abuild/*.rsa)
merge_public_keys=("${HOME}"/.abuild/*.rsa.pub)
shopt -u nullglob
if [[ "${#merge_private_keys[@]}" -ne 1 || "${#merge_public_keys[@]}" -ne 1 ]]; then
printf 'expected exactly one merge signing key in %s/.abuild\n' "${HOME}" >&2
exit 1
fi
for arch in ${arches}; do
destination="${package_root}/${arch}"
keys_dir="${keys_root}/${arch}"
mkdir -p "${destination}"
while IFS= read -r -d '' apk; do
cp "${apk}" "${destination}/"
done < <(find "${artifact_root}" -type f -path "*/${arch}/*.apk" -print0)
shopt -s nullglob
apks=("${destination}"/*.apk)
shopt -u nullglob
if [[ "${#apks[@]}" -eq 0 ]]; then
rmdir "${destination}"
continue
fi
while IFS= read -r -d '' key; do
copy_key "${key}" "${destination}"
mkdir -p "${keys_dir}"
copy_key "${key}" "${keys_dir}"
done < <(find "${artifact_root}" -type f -path "*/${arch}/*.rsa.pub" -print0)
if ! compgen -G "${keys_dir}/*.rsa.pub" > /dev/null; then
printf 'missing worker signing key for %s artifacts\n' "${arch}" >&2
exit 1
fi
copy_key "${merge_public_keys[0]}" "${destination}"
(
cd "${destination}"
apk --keys-dir "${keys_dir}" index --rewrite-arch "${arch}" -o APKINDEX.tar.gz ./*.apk
abuild-sign -k "${merge_private_keys[0]}" APKINDEX.tar.gz
)
done
if ! compgen -G "${package_root}"/*/*.apk > /dev/null; then
printf 'no APK files found in worker artifacts: %s\n' "${artifact_root}" >&2
exit 1
fi
+5 -86
View File
@@ -13,59 +13,17 @@ fi
github_latest_release() {
local repo="$1"
local api_url="https://api.github.com/repos/${repo}/releases/latest"
local response
response="$(curl -fsSL \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"https://api.github.com/repos/${repo}/releases/latest" 2>/dev/null)" || return 1
printf '%s\n' "${response}" | jq -er '.tag_name'
}
"${api_url}" 2>/dev/null)" || return 1
github_release_rows() {
local repo="$1"
local current_tag="$2"
local page=1
local response
local release_count
while :; do
response="$(curl -fsSL \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"https://api.github.com/repos/${repo}/releases?per_page=100&page=${page}" 2>/dev/null)" || return 1
release_count="$(printf '%s\n' "${response}" | jq -er 'if type == "array" then length else error("expected release array") end')" || return 1
[[ "${release_count}" -gt 0 ]] || return 0
printf '%s\n' "${response}" | jq -r '
.[]
| select(.draft | not)
| select(.prerelease | not)
| [
.tag_name,
(.published_at // "-"),
(.name // .tag_name),
.html_url,
(
(.body // "")
| gsub("[\\r\\n\\t]+"; " ")
| gsub("[`*_>#]"; "")
| gsub(" +"; " ")
| gsub("^ +"; "")
| gsub(" +$"; "")
| if length > 240 then .[0:237] + "..." else . end
)
]
| @tsv
'
if printf '%s\n' "${response}" | jq -e --arg tag "${current_tag}" '
any(.[]; .tag_name == $tag and (.draft | not) and (.prerelease | not))
' >/dev/null; then
return 0
fi
page=$((page + 1))
done
printf '%s\n' "${response}" \
| sed -n 's/^[[:space:]]*"tag_name":[[:space:]]*"\([^"]*\)".*/\1/p' \
| head -n 1
}
apkbuild_value() {
@@ -146,7 +104,6 @@ printf '%-14s %-14s %-14s %-18s %s\n' "PACKAGE" "CURRENT" "LATEST" "STATUS" "UPS
has_update=0
has_unknown=0
release_details=""
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
@@ -164,40 +121,6 @@ while IFS= read -r package_dir; do
if version_is_newer "${latest_version}" "${current_version}"; then
status="update-available"
has_update=1
package_details="${package_name}: ${current_version} -> ${latest_version}"
case "${version_prefix}" in
none|"") current_tag="${current_version}" ;;
*) current_tag="${version_prefix}${current_version}" ;;
esac
if release_rows="$(github_release_rows "${repo}" "${current_tag}")" && [[ -n "${release_rows}" ]]; then
current_tag_found=0
while IFS=$'\t' read -r release_tag published_at release_name release_url release_excerpt; do
[[ -n "${release_tag}" ]] || continue
release_version="$(normalize_version "${release_tag}" "${version_prefix}")"
if [[ "${release_tag}" == "${current_tag}" ]]; then
current_tag_found=1
fi
if version_is_newer "${release_version}" "${current_version}"; then
package_details+=$'\n'
package_details+=" ${release_version} (${published_at}) — ${release_name}"
package_details+=$'\n'
package_details+=" ${release_url}"
if [[ -n "${release_excerpt}" ]]; then
package_details+=$'\n'
package_details+=" ${release_excerpt}"
fi
fi
done <<< "${release_rows}"
if [[ "${current_tag_found}" == 0 ]]; then
package_details+=$'\n'
package_details+=" Note: current release tag ${current_tag} was not found; listed releases compare newer than ${current_version}."
fi
else
package_details+=$'\n'
package_details+=" Note: release details could not be fetched."
fi
release_details+=$'\n'
release_details+="${package_details}"
else
status="current"
fi
@@ -216,10 +139,6 @@ while IFS= read -r package_dir; do
"${upstream_url}"
done < <(apk_package_dirs "${repo_root}")
if [[ -n "${release_details}" ]]; then
printf '\nRelease details:%s\n' "${release_details}"
fi
if [[ "${mode}" == "fail" && ( "${has_update}" -ne 0 || "${has_unknown}" -ne 0 ) ]]; then
exit 1
fi
+1 -27
View File
@@ -106,8 +106,7 @@ apk_package_apk_names() {
local pkgrel
local subpackage
local subpackages
# shellcheck disable=SC2034 # APKBUILD reads CARCH while sourced below.
local CARCH="${arch}"
export CARCH="${arch}"
cd "${package_dir}" || exit 1
# shellcheck source=/dev/null
. ./APKBUILD
@@ -120,31 +119,6 @@ apk_package_apk_names() {
)
}
apk_package_versioned_names() {
local package_dir="$1"
local arch="$2"
(
set +u
local pkgname
local pkgver
local pkgrel
local subpackage
local subpackages
# shellcheck disable=SC2034 # APKBUILD reads CARCH while sourced below.
local CARCH="${arch}"
cd "${package_dir}" || exit 1
# shellcheck source=/dev/null
. ./APKBUILD
printf '%s=%s-r%s\n' "${pkgname}" "${pkgver}" "${pkgrel}"
for subpackage in ${subpackages:-}; do
subpackage="${subpackage%%:*}"
printf '%s=%s-r%s\n' "${subpackage}" "${pkgver}" "${pkgrel}"
done
)
}
apk_container_package_dir() {
local repo_root="$1"
local package_dir="$2"
-1
View File
@@ -10,4 +10,3 @@ mise run apk:lint-shell
mise run apk:build-all
mise run apk:packages
mise run apk:smoke
mise run apk:security-report
-183
View File
@@ -1,183 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=scripts/apk/package-lib.sh
. "${repo_root}/scripts/apk/package-lib.sh"
repo_name="${ALPINE_REPO_NAME:-local}"
alpine_version="${ALPINE_VERSION:-3.24}"
arches="${ALPINE_SECURITY_ARCHES:-${ALPINE_ARCHES:-x86_64}}"
reports_dir="${APK_SECURITY_REPORTS_DIR:-${repo_root}/packages/security-reports}"
trivy_bin="${TRIVY_BIN:-trivy}"
# The GCR pull-through mirror can serve a manifest whose layer has already
# expired, returning 404 rather than letting Trivy continue to its fallback.
# Use the publisher's registry directly; callers may still select an internal
# mirror by setting TRIVY_DB_REPOSITORY.
trivy_db_repository="${TRIVY_DB_REPOSITORY:-ghcr.io/aquasecurity/trivy-db:2}"
require_command() {
command -v "$1" >/dev/null 2>&1 || {
printf 'missing required command: %s\n' "$1" >&2
exit 2
}
}
platform_for_arch() {
case "$1" in
x86_64) printf '%s\n' 'linux/amd64' ;;
aarch64) printf '%s\n' 'linux/arm64' ;;
*) printf 'unsupported Alpine architecture: %s\n' "$1" >&2; return 2 ;;
esac
}
install_rootfs() {
local rootfs="$1"
local arch="$2"
shift 2
local -a specs=("$@")
local -a apk_args=(--root "${rootfs}/installed" --initdb --no-scripts --arch "${arch}")
local key_dir repo_file native_arch
key_dir="${rootfs}/keys"
repo_file="${rootfs}/repositories"
mkdir -p "${key_dir}"
cp /etc/apk/keys/*.pub "${key_dir}/"
cp "${repo_root}/packages/${repo_name}/${arch}"/*.rsa.pub "${key_dir}/"
{
printf 'https://dl-cdn.alpinelinux.org/alpine/v%s/main\n' "${alpine_version}"
printf 'https://dl-cdn.alpinelinux.org/alpine/v%s/community\n' "${alpine_version}"
printf 'file://%s/packages/%s\n' "${repo_root}" "${repo_name}"
} > "${repo_file}"
if [[ "$(id -u)" != 0 ]]; then
apk_args+=(--usermode)
fi
native_arch="$(apk --print-arch)"
if [[ "${arch}" != "${native_arch}" ]]; then
# A native Alpine image does not necessarily carry the current signing keys
# for another architecture. Bootstrap that architecture's alpine-keys over
# HTTPS, then use the refreshed key set for the actual dependency install.
apk "${apk_args[@]}" --keys-dir "${key_dir}" --repositories-file "${repo_file}" \
--allow-untrusted add --no-cache alpine-keys
cp "${rootfs}/installed/etc/apk/keys/"*.pub "${key_dir}/"
fi
apk "${apk_args[@]}" --keys-dir "${key_dir}" --repositories-file "${repo_file}" \
add --no-cache "${specs[@]}"
}
install_rootfs_docker() {
local rootfs="$1"
local arch="$2"
shift 2
local platform
platform="$(platform_for_arch "${arch}")"
docker run --rm --platform "${platform}" \
--user "$(id -u):$(id -g)" \
-e REPO_NAME="${repo_name}" \
-e ALPINE_ARCH="${arch}" \
-e ALPINE_VERSION="${alpine_version}" \
-v "${repo_root}:/work:ro" \
-v "${rootfs}:/scan" \
"alpine:${alpine_version}" \
sh -ec '
mkdir -p /scan/keys
cp /etc/apk/keys/*.pub /scan/keys/
cp /work/packages/"$REPO_NAME"/"$ALPINE_ARCH"/*.rsa.pub /scan/keys/
{
printf "https://dl-cdn.alpinelinux.org/alpine/v%s/main\\n" "$ALPINE_VERSION"
printf "https://dl-cdn.alpinelinux.org/alpine/v%s/community\\n" "$ALPINE_VERSION"
printf "file:///work/packages/%s\\n" "$REPO_NAME"
} > /scan/repositories
apk --root /scan/installed --usermode --initdb --no-scripts --arch "$ALPINE_ARCH" \
--keys-dir /scan/keys --repositories-file /scan/repositories \
add --no-cache "$@"
' security-report "$@"
}
write_summary() {
local report="$1"
local summary="$2"
local package_name="$3"
local arch="$4"
local total
total="$(jq '[.Results[]?.Vulnerabilities[]?] | length' "${report}")"
{
printf '# %s (%s) security report\n\n' "${package_name}" "${arch}"
printf 'Installed APK rootfs scanned with Trivy. Findings are advisory.\n\n'
printf '| Severity | Count |\n| --- | ---: |\n'
for severity in CRITICAL HIGH MEDIUM LOW UNKNOWN; do
printf '| %s | %s |\n' "${severity}" \
"$(jq --arg severity "${severity}" '[.Results[]?.Vulnerabilities[]? | select(.Severity == $severity)] | length' "${report}")"
done
printf '\nTotal vulnerabilities: %s\n' "${total}"
} > "${summary}"
}
print_report() {
local report_dir="$1"
local package_name="$2"
local arch="$3"
printf '\nSecurity reports for %s (%s):\n' "${package_name}" "${arch}"
printf ' Trivy: file://%s/trivy.json\n' "${report_dir}"
printf ' SBOM: file://%s/sbom.cdx.json\n' "${report_dir}"
printf ' Summary: file://%s/summary.md\n' "${report_dir}"
cat "${report_dir}/summary.md"
printf '\n'
}
require_command "${trivy_bin}"
require_command jq
if ! command -v apk >/dev/null 2>&1; then
require_command docker
fi
tmpdir="$(mktemp -d)"
cleanup() {
rm -rf "${tmpdir}"
}
trap cleanup EXIT
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
package_name="$(apk_package_name "${package_dir}")"
for arch in ${arches}; do
apk_package_supports_arch "${package_dir}" "${arch}" || continue
repo_dir="${repo_root}/packages/${repo_name}/${arch}"
if [[ ! -f "${repo_dir}/APKINDEX.tar.gz" ]] || ! compgen -G "${repo_dir}/*.rsa.pub" >/dev/null; then
printf 'missing signed local repository for %s: %s\n' "${package_name}" "${repo_dir}" >&2
exit 1
fi
mapfile -t specs < <(
apk_package_versioned_names "${package_dir}" "${arch}" | sed 's/=.*//'
)
specs=(alpine-baselayout "${specs[@]}")
report_dir="${reports_dir}/${package_name}/${arch}"
rootfs="${tmpdir}/${package_name}-${arch}"
mkdir -p "${report_dir}" "${rootfs}"
printf 'Generating security reports for %s (%s)\n' "${package_name}" "${arch}"
if command -v apk >/dev/null 2>&1; then
install_rootfs "${rootfs}" "${arch}" "${specs[@]}"
else
install_rootfs_docker "${rootfs}" "${arch}" "${specs[@]}"
fi
"${trivy_bin}" filesystem --db-repository "${trivy_db_repository}" --distro "alpine/${alpine_version}" --scanners vuln --format json --no-progress \
--output "${report_dir}/trivy.json" "${rootfs}/installed"
"${trivy_bin}" filesystem --db-repository "${trivy_db_repository}" --distro "alpine/${alpine_version}" --scanners vuln --format cyclonedx --no-progress \
--output "${report_dir}/sbom.cdx.json" "${rootfs}/installed"
jq -e 'type == "object" and has("ArtifactName")' "${report_dir}/trivy.json" >/dev/null
jq -e '.bomFormat == "CycloneDX"' "${report_dir}/sbom.cdx.json" >/dev/null
write_summary "${report_dir}/trivy.json" "${report_dir}/summary.md" "${package_name}" "${arch}"
print_report "${report_dir}" "${package_name}" "${arch}"
done
done < <(apk_package_dirs "${repo_root}")
+1 -6
View File
@@ -5,7 +5,7 @@ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
alpine_version="${ALPINE_VERSION:-3.24}"
platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
arch="${ALPINE_ARCH:-x86_64}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb lavinmq lavinmq-openrc gitea gitea-openrc rclone-openrc}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb lavinmq lavinmq-openrc gitea gitea-openrc}"
if [[ ! -d "${repo_root}/packages/local/${arch}" ]]; then
printf 'missing local repository: packages/local/%s\n' "${arch}" >&2
@@ -39,11 +39,6 @@ docker run --rm --platform "${platform}" \
test -f /etc/gitea/app.ini
test -d /var/lib/gitea
fi
if command -v rclone >/dev/null 2>&1; then
rclone version
test -f /etc/conf.d/rclone
test -f /etc/init.d/rclone
fi
if ls /etc/init.d/seaweedfs.* >/dev/null 2>&1; then
ls -1 /etc/init.d/seaweedfs.* | sort
fi
-1
View File
@@ -76,7 +76,6 @@ Examples:
apk add greptimedb greptimedb-docs greptimedb-standalone-openrc
apk add lavinmq lavinmq-openrc
apk add gitea gitea-openrc
apk add rclone-openrc
Entering ${TEST_SHELL}.