Compare commits
99
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f5d8f1c5c | ||
|
|
aaaf33ef8b | ||
|
|
766bb2bfa0 | ||
|
|
16197f7a6c | ||
|
|
7a9916ea17 | ||
|
|
a2761c0b1f | ||
|
|
29c79708f1 | ||
|
|
7bdcc83050 | ||
|
|
57fc0e658c | ||
|
|
c9543e113b | ||
|
|
450d4815dd | ||
|
|
53747a13cc | ||
|
|
13570ccbd9 | ||
|
|
f89ebac967 | ||
|
|
bded7c8adc | ||
|
|
158fd18984 | ||
|
|
fd0f484d4a | ||
|
|
1716f42970 | ||
|
|
37b6e4cf2c | ||
|
|
a97bafbd92 | ||
|
|
573608a04b | ||
|
|
b94463642a | ||
|
|
fc965e072c | ||
|
|
1c3994a7c4 | ||
|
|
e8333709a5 | ||
|
|
03daf40d6e | ||
|
|
40eaf081ad | ||
|
|
254fa76a7d | ||
|
|
0e6bc657a9 | ||
|
|
d21dadada7 | ||
|
|
b75fa2eac9 | ||
|
|
5e2093afec | ||
|
|
74a31e6f45 | ||
|
|
815a47e19f | ||
|
|
96bd8a20e0 | ||
|
|
0a9ed89a47 | ||
|
|
001bd51931 | ||
|
|
f01d209780 | ||
|
|
f5efea2160 | ||
|
|
e4093a3c9f | ||
|
|
d70e9ce84c | ||
|
|
fed4ad011d | ||
|
|
dae1f755a2 | ||
|
|
b3d5424349 | ||
|
|
13a2d0dd16 | ||
|
|
a2da4acc53 | ||
|
|
2825e1bfef | ||
|
|
fadbde6c6d | ||
|
|
ace376e5c1 | ||
|
|
f8189786c8 | ||
|
|
684b9ded73 | ||
|
|
4b30c5bb93 | ||
|
|
7119330286 | ||
|
|
b0ed3584a1 | ||
|
|
5dd92f94d5 | ||
|
|
fe180c01a7 | ||
|
|
6968a72209 | ||
|
|
ba56882ab8 | ||
|
|
f1af2660eb | ||
|
|
b5af335ec5 | ||
|
|
0384306d4e | ||
|
|
8275d25ae7 | ||
|
|
86460ee2ba | ||
|
|
8d98ccf093 | ||
|
|
479886d37d | ||
|
|
9b9473f497 | ||
|
|
53f2a988de | ||
|
|
e6d9b173f2 | ||
|
|
107e17b959 | ||
|
|
57bf04fa87 | ||
|
|
88abf51ca5 | ||
|
|
85122866ac | ||
|
|
89db986774 | ||
|
|
faf7d5e404 | ||
|
|
7781653941 | ||
|
|
b19a3288fd | ||
|
|
95834e55d5 | ||
|
|
95f8f1597a | ||
|
|
2be2a6d5b0 | ||
|
|
a812b075d0 | ||
|
|
6b8488d7cc | ||
|
|
368a112568 | ||
|
|
04b1244a8c | ||
|
|
de967b8d36 | ||
|
|
a3c4d09e65 | ||
|
|
dfd92c522b | ||
|
|
2c3107feb4 | ||
|
|
08e516475f | ||
|
|
9462c9a304 | ||
|
|
47c398a6ae | ||
|
|
e076b3249a | ||
|
|
1c4b598b5c | ||
|
|
4efe12f250 | ||
|
|
b329cd0ccc | ||
|
|
ca64a3e993 | ||
|
|
3049d872e0 | ||
|
|
bef07e3e22 | ||
|
|
05188cc390 | ||
|
|
74207600cc |
@@ -0,0 +1,5 @@
|
|||||||
|
.git
|
||||||
|
.cache
|
||||||
|
packages
|
||||||
|
packaging/**/pkg
|
||||||
|
packaging/**/src
|
||||||
+164
-24
@@ -3,58 +3,198 @@ name: Build Alpine Packages
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
|
||||||
- main
|
- main
|
||||||
tags:
|
tags:
|
||||||
- "*"
|
- "*"
|
||||||
pull_request:
|
pull_request:
|
||||||
workflow_dispatch:
|
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:
|
jobs:
|
||||||
build-and-publish:
|
preflight:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 180
|
||||||
container:
|
container:
|
||||||
image: alpine:3.23
|
image: "alpine:3.24"
|
||||||
env:
|
outputs:
|
||||||
ALPINE_VERSION: "3.23"
|
packages_selected: "${{ steps.package-selection.outputs.packages_selected }}"
|
||||||
ALPINE_ARCHES: "x86_64 aarch64"
|
selected_packages: "${{ steps.package-selection.outputs.selected_packages }}"
|
||||||
ALPINE_REGISTRY_BRANCH: "v3.23"
|
greptimedb_selected: "${{ steps.package-selection.outputs.greptimedb_selected }}"
|
||||||
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: "Joachim Schlöffel <me@joachim-schloeffel.com>"
|
|
||||||
CARGO_HOME: "/cache/public-alpine-packages/greptimedb/cargo"
|
|
||||||
RUSTUP_HOME: "/cache/public-alpine-packages/greptimedb/rustup"
|
|
||||||
CARGO_TARGET_DIR: "/cache/public-alpine-packages/greptimedb/target"
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare Environment
|
- name: Prepare Environment
|
||||||
run: |
|
run: |
|
||||||
apk add --no-cache --update abuild-rootbld alpine-sdk atools-apkbuild-lint bash ca-certificates curl doas git nodejs sudo tar
|
printf '%s\n' 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
|
||||||
mkdir -p "$CARGO_HOME" "$RUSTUP_HOME" "$CARGO_TARGET_DIR"
|
apk add --no-cache --update atools-apkbuild-lint bash ca-certificates curl git jq nodejs shellcheck tar
|
||||||
chown 1000:1000 /cache /cache/public-alpine-packages /cache/public-alpine-packages/greptimedb "$CARGO_HOME" "$RUSTUP_HOME" "$CARGO_TARGET_DIR"
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Build packages
|
- name: Select packages
|
||||||
run: |
|
run: |
|
||||||
scripts/apk/clean.sh
|
scripts/apk/clean.sh
|
||||||
find packaging/alpine/local -mindepth 2 -maxdepth 2 -name APKBUILD -exec apkbuild-lint {} +
|
find packaging/alpine/local -mindepth 2 -maxdepth 2 -name APKBUILD -exec apkbuild-lint {} +
|
||||||
|
scripts/apk/lint-shell.sh
|
||||||
|
scripts/apk/outdated.sh | tee update-check.txt
|
||||||
|
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
||||||
|
{
|
||||||
|
echo "## Upstream update check"
|
||||||
|
echo
|
||||||
|
echo '```text'
|
||||||
|
cat update-check.txt
|
||||||
|
echo '```'
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Prepare package cache
|
||||||
|
id: package-selection
|
||||||
|
run: scripts/apk/ci-package-cache.sh prepare
|
||||||
|
|
||||||
|
- name: Validate selected package matrix
|
||||||
|
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
|
||||||
|
|
||||||
|
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)
|
||||||
|
run: |
|
||||||
scripts/apk/ci-build.sh
|
scripts/apk/ci-build.sh
|
||||||
scripts/apk/export-ci-assets.sh
|
|
||||||
scripts/apk/list-packages.sh
|
scripts/apk/list-packages.sh
|
||||||
|
|
||||||
- name: Upload generated CI assets
|
- name: Check artifact upload support
|
||||||
|
if: contains(needs.preflight.outputs.selected_packages, matrix.package)
|
||||||
|
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
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: greptimedb-musl-binaries
|
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/
|
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
|
- name: Smoke test
|
||||||
run: scripts/apk/ci-smoke.sh
|
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"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Upload security reports
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: apk-security-reports-v3.24
|
||||||
|
path: packages/security-reports/
|
||||||
|
|
||||||
|
- name: Runtime test
|
||||||
|
run: ALPINE_RUNTIME_TEST_MODE=docker scripts/apk/runtime-test.sh
|
||||||
|
|
||||||
- name: Publish Alpine packages
|
- name: Publish Alpine packages
|
||||||
if: github.event_name != 'pull_request'
|
if: github.ref == 'refs/heads/main'
|
||||||
run: scripts/apk/publish-gitea.sh
|
run: scripts/apk/publish-gitea.sh
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
.cache/
|
.cache/
|
||||||
|
.vscode/
|
||||||
packages/
|
packages/
|
||||||
packaging/alpine/*/*/pkg/
|
packaging/alpine/*/*/pkg/
|
||||||
packaging/alpine/*/*/src/
|
packaging/alpine/*/*/src/
|
||||||
|
packaging/alpine/*/*/tmp/
|
||||||
packaging/alpine/*/*/*.apk
|
packaging/alpine/*/*/*.apk
|
||||||
packaging/alpine/*/*/*.tar.*
|
packaging/alpine/*/*/*.tar.*
|
||||||
|
!packaging/alpine/*/*/*-vendor.tar.gz
|
||||||
|
!packaging/alpine/local/lavinmq/lavinmq-*-shards.tar.gz
|
||||||
|
!packaging/alpine/local/lavinmq/lavinmq-*-assets.tar.gz
|
||||||
|
|||||||
@@ -1,171 +1,59 @@
|
|||||||
# Alpine Packages
|
# Alpine Packages
|
||||||
|
|
||||||
Alpine 3.23 packaging for internal packages.
|
Alpine stable packaging for internal packages. This repository carries selected
|
||||||
|
upstream releases ahead of Alpine community packages when we need newer
|
||||||
|
features, packaging fixes, or service layouts on the current Alpine branch.
|
||||||
|
|
||||||
This repository builds signed `x86_64` and `aarch64` APKs and publishes them to
|
Packages are either source builds or binary repackages:
|
||||||
the Gitea Alpine package registry under:
|
|
||||||
|
- Source builds compile upstream source releases inside the Alpine build
|
||||||
|
environment and link against Alpine libraries.
|
||||||
|
- Binary repackages wrap official upstream Linux release artifacts in Alpine
|
||||||
|
package metadata, OpenRC services, config defaults, and role subpackages.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
https://code.factoring.digital/api/packages/public/alpine/v3.23/alpine-packages
|
https://code.factoring.digital/api/packages/public/alpine/v3.24/alpine-packages
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Available 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. |
|
||||||
|
|
||||||
## Use In Production
|
## Use In Production
|
||||||
|
|
||||||
### Add The Package Repository
|
### Add The Package Repository
|
||||||
|
|
||||||
Install the registry signing key on each Alpine node:
|
Install the registry key:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSLo /etc/apk/keys/public-alpine.rsa.pub \
|
cd /etc/apk/keys
|
||||||
https://code.factoring.digital/api/packages/public/alpine/key
|
curl -fsSLOJ https://code.factoring.digital/api/packages/public/alpine/key
|
||||||
```
|
```
|
||||||
|
|
||||||
Add the package repository:
|
Add the repository for the node's Alpine branch:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
printf '%s\n' \
|
printf '%s\n' \
|
||||||
'https://code.factoring.digital/api/packages/public/alpine/v3.23/alpine-packages' \
|
'https://code.factoring.digital/api/packages/public/alpine/v3.24/alpine-packages' \
|
||||||
>> /etc/apk/repositories
|
>> /etc/apk/repositories
|
||||||
|
|
||||||
apk update
|
apk update
|
||||||
```
|
```
|
||||||
|
|
||||||
If a forked or future registry is private, include a Gitea user and package token in the
|
Private registry URL format:
|
||||||
repository URL:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
https://<user>:<token>@code.factoring.digital/api/packages/public/alpine/v3.23/alpine-packages
|
https://<user>:<token>@code.factoring.digital/api/packages/public/alpine/v3.24/alpine-packages
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install SeaweedFS Node Roles
|
## Contribution
|
||||||
|
|
||||||
Install the base package plus only the OpenRC role packages needed on that node.
|
|
||||||
|
|
||||||
For a single-node test or a compact small deployment:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk add seaweedfs \
|
|
||||||
seaweedfs-master-openrc \
|
|
||||||
seaweedfs-volume-openrc \
|
|
||||||
seaweedfs-filer-openrc
|
|
||||||
```
|
|
||||||
|
|
||||||
For separated production nodes, install only the role running there:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk add seaweedfs seaweedfs-master-openrc
|
|
||||||
apk add seaweedfs seaweedfs-volume-openrc
|
|
||||||
apk add seaweedfs seaweedfs-filer-openrc
|
|
||||||
```
|
|
||||||
|
|
||||||
Available OpenRC role packages:
|
|
||||||
|
|
||||||
```text
|
|
||||||
seaweedfs-master-openrc -> /etc/init.d/seaweedfs.master
|
|
||||||
seaweedfs-volume-openrc -> /etc/init.d/seaweedfs.volume
|
|
||||||
seaweedfs-filer-openrc -> /etc/init.d/seaweedfs.filer
|
|
||||||
seaweedfs-s3-openrc -> /etc/init.d/seaweedfs.s3
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
The package name is `seaweedfs`, matching Alpine aports. If a node already has
|
|
||||||
Alpine's old generic OpenRC package installed, remove it before installing a
|
|
||||||
role-specific split:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk del seaweedfs-openrc
|
|
||||||
apk add seaweedfs seaweedfs-master-openrc
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configure Services
|
|
||||||
|
|
||||||
Runtime files are installed in the usual Alpine locations:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/usr/bin/weed
|
|
||||||
/etc/seaweedfs/*.toml
|
|
||||||
/etc/conf.d/seaweedfs.*
|
|
||||||
/etc/init.d/seaweedfs.*
|
|
||||||
```
|
|
||||||
|
|
||||||
Edit `/etc/conf.d/seaweedfs.<role>` for command-line flags and
|
|
||||||
`/etc/seaweedfs/*.toml` for SeaweedFS config. The packaged defaults are short
|
|
||||||
and production-neutral; full upstream example configs are in:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/usr/share/doc/seaweedfs/examples/
|
|
||||||
```
|
|
||||||
|
|
||||||
Enable and start only the services needed on the node:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
rc-update add seaweedfs.master default
|
|
||||||
rc-service seaweedfs.master start
|
|
||||||
|
|
||||||
rc-update add seaweedfs.volume default
|
|
||||||
rc-service seaweedfs.volume start
|
|
||||||
|
|
||||||
rc-update add seaweedfs.filer default
|
|
||||||
rc-service seaweedfs.filer start
|
|
||||||
```
|
|
||||||
|
|
||||||
Check the installed binary and service state:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
weed version
|
|
||||||
rc-service seaweedfs.master status
|
|
||||||
```
|
|
||||||
|
|
||||||
### Optional Packages
|
|
||||||
|
|
||||||
Install docs and generated examples:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk add seaweedfs-doc
|
|
||||||
```
|
|
||||||
|
|
||||||
Install bash completion:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk add bash-completion seaweedfs-bash-completion
|
|
||||||
```
|
|
||||||
|
|
||||||
`seaweedfs-bash-completion` is also selected automatically when `seaweedfs` and
|
|
||||||
`bash-completion` are installed together.
|
|
||||||
|
|
||||||
### Upgrade Or Pin
|
|
||||||
|
|
||||||
Use normal Alpine package operations:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk upgrade seaweedfs
|
|
||||||
rc-service seaweedfs.master restart
|
|
||||||
```
|
|
||||||
|
|
||||||
Pin a specific package build when needed:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk add seaweedfs=4.31-r3
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install GreptimeDB
|
|
||||||
|
|
||||||
Install GreptimeDB:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apk add greptimedb
|
|
||||||
```
|
|
||||||
|
|
||||||
Check the installed binary:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
greptime --version
|
|
||||||
```
|
|
||||||
|
|
||||||
## Background And Contribution
|
|
||||||
|
|
||||||
### Package Layout
|
### Package Layout
|
||||||
|
|
||||||
@@ -175,24 +63,6 @@ Package sources live under:
|
|||||||
packaging/alpine/local/<pkgname>/
|
packaging/alpine/local/<pkgname>/
|
||||||
```
|
```
|
||||||
|
|
||||||
Currently packaged:
|
|
||||||
|
|
||||||
```text
|
|
||||||
seaweedfs SeaweedFS 4.31 release binary and OpenRC role splits
|
|
||||||
greptimedb GreptimeDB 1.0.2 built from source for x86_64
|
|
||||||
```
|
|
||||||
|
|
||||||
### SeaweedFS Package
|
|
||||||
|
|
||||||
The APKBUILD repackages the official SeaweedFS Linux release tarballs. It does
|
|
||||||
not build SeaweedFS from source. The package installs:
|
|
||||||
|
|
||||||
- `weed` as `/usr/bin/weed`
|
|
||||||
- minimal active config under `/etc/seaweedfs/`
|
|
||||||
- role-specific OpenRC subpackages
|
|
||||||
- upstream example configs under `/usr/share/doc/seaweedfs/examples/`
|
|
||||||
- generated bash completion as a separate subpackage
|
|
||||||
|
|
||||||
Local build output is written under:
|
Local build output is written under:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -209,28 +79,40 @@ Signing keys and distfiles are cached under:
|
|||||||
### Build Commands
|
### Build Commands
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mise run apk:lint
|
$ mise tasks
|
||||||
mise run apk:build
|
Name Description
|
||||||
mise run apk:build-all
|
apk:build Build the Alpine package in Docker for the default architecture
|
||||||
mise run apk:packages
|
apk:build-aarch64 Build the Alpine package in Docker for aarch64
|
||||||
mise run apk:smoke
|
apk:build-all Build the Alpine package in Docker for all configured architectures
|
||||||
mise run apk:test-install
|
apk:build-x86_64 Build the Alpine package in Docker for x86_64
|
||||||
mise run apk:test-shell
|
apk:checksum Refresh APKBUILD checksums in Docker
|
||||||
mise run apk:publish-check
|
apk:ci-build Build all configured Alpine packages directly in the current Alpine...
|
||||||
|
apk:ci-smoke Install-test built packages directly in the current Alpine environment
|
||||||
|
apk:clean Remove generated Alpine package build outputs
|
||||||
|
apk:lint Run Alpine APKBUILD lint in Docker
|
||||||
|
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: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
|
||||||
|
apk:test-shell Open an Alpine shell with the local APK repository configured
|
||||||
|
apk:update-generated Refresh packaged upstream examples and shell completions
|
||||||
|
apk:runtime-test Run package-local Docker runtime tests against the local...
|
||||||
|
gitea-workflow-build Run the Gitea build workflow locally through act as a pull_request event
|
||||||
```
|
```
|
||||||
|
|
||||||
`apk:build` targets `x86_64` by default. Multi-arch builds target `x86_64` and
|
`apk:build` targets `x86_64` by default. Multi-arch builds target `x86_64` and
|
||||||
`aarch64`; override with `ALPINE_ARCHES` when needed:
|
`aarch64`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_ARCHES="x86_64 aarch64" mise run apk:build-all
|
ALPINE_ARCHES="x86_64 aarch64" mise run apk:build-all
|
||||||
```
|
```
|
||||||
|
|
||||||
Unqualified build and install-test tasks discover all packages. GreptimeDB is a
|
Limit package selection with `ALPINE_PACKAGE` or `ALPINE_PACKAGES`:
|
||||||
source build and can take close to an hour; it is limited to `x86_64` during
|
|
||||||
production evaluation. Target fast package work explicitly:
|
|
||||||
|
|
||||||
Build or test a subset of packages with `ALPINE_PACKAGE` or `ALPINE_PACKAGES`:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_PACKAGE=seaweedfs mise run apk:build
|
ALPINE_PACKAGE=seaweedfs mise run apk:build
|
||||||
@@ -239,78 +121,99 @@ ALPINE_PACKAGE=seaweedfs mise run apk:test-install
|
|||||||
ALPINE_PACKAGE=greptimedb mise run apk:checksum
|
ALPINE_PACKAGE=greptimedb mise run apk:checksum
|
||||||
ALPINE_PACKAGE=greptimedb mise run apk:build
|
ALPINE_PACKAGE=greptimedb mise run apk:build
|
||||||
ALPINE_PACKAGE=greptimedb SKIP_BUILD=1 mise run apk:test-install
|
ALPINE_PACKAGE=greptimedb SKIP_BUILD=1 mise run apk:test-install
|
||||||
|
ALPINE_PACKAGE=lavinmq mise run apk:build
|
||||||
|
ALPINE_PACKAGE=lavinmq SKIP_BUILD=1 mise run apk:test-install
|
||||||
|
ALPINE_PACKAGE=gitea mise run apk:build
|
||||||
|
ALPINE_PACKAGE=gitea SKIP_BUILD=1 mise run apk:test-install
|
||||||
```
|
```
|
||||||
|
|
||||||
Docker-backed build tasks keep Cargo registry, Rustup, and Cargo target caches in named Docker volumes. The default volume scope is derived from the Git remote owner/repository and is split by package and architecture. Override it when needed:
|
Override Docker cache scope:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_APK_CACHE_SCOPE=public-alpine-packages ALPINE_PACKAGE=greptimedb mise run apk:build
|
ALPINE_APK_CACHE_SCOPE=public-alpine-packages ALPINE_PACKAGE=greptimedb mise run apk:build
|
||||||
ALPINE_APK_CACHE_PREFIX=alpine-apk-ci ALPINE_PACKAGE=greptimedb mise run apk:build
|
ALPINE_APK_CACHE_PREFIX=alpine-apk-ci ALPINE_PACKAGE=greptimedb mise run apk:build
|
||||||
```
|
```
|
||||||
|
|
||||||
Use the test shell to inspect the package in Alpine with the current build
|
Local packages use `local` as the default package metadata identity. Override it
|
||||||
installed:
|
when needed:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
PACKAGER="Example Builder <builder@example.com>" ALPINE_PACKAGE=seaweedfs mise run apk:build
|
||||||
|
```
|
||||||
|
|
||||||
|
Open an Alpine package build shell:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_PACKAGE=seaweedfs mise run apk:shell
|
ALPINE_PACKAGE=seaweedfs mise run apk:shell
|
||||||
mise run apk:test-shell
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Use the install test to validate the production instructions against the local
|
Run the install test:
|
||||||
package repository in a fresh Alpine container:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mise run apk:test-install
|
mise run apk:test-install
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `SKIP_BUILD=1` to reuse existing local packages:
|
Reuse existing local packages:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
SKIP_BUILD=1 mise run apk:test-install
|
SKIP_BUILD=1 mise run apk:test-install
|
||||||
SKIP_BUILD=1 mise run apk:test-shell
|
SKIP_BUILD=1 mise run apk:test-shell
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`apk:test-shell` opens an Alpine shell with the local APK repository configured.
|
||||||
|
Install whichever built packages you want inside the container:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add seaweedfs seaweedfs-master-openrc
|
||||||
|
weed version
|
||||||
|
|
||||||
|
apk add greptimedb greptimedb-docs greptimedb-standalone-openrc
|
||||||
|
greptime --version
|
||||||
|
|
||||||
|
apk add rclone-openrc
|
||||||
|
rclone version
|
||||||
|
```
|
||||||
|
|
||||||
|
Run package-local runtime tests:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mise run apk:runtime-test
|
||||||
|
ALPINE_PACKAGE=seaweedfs mise run apk:runtime-test
|
||||||
|
ALPINE_VERSION=3.24 mise run apk:runtime-test
|
||||||
|
```
|
||||||
|
|
||||||
### Adding Packages
|
### Adding Packages
|
||||||
|
|
||||||
Each package lives under:
|
Package path:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
packaging/alpine/local/<pkgname>/
|
packaging/alpine/local/<pkgname>/
|
||||||
```
|
```
|
||||||
|
|
||||||
The only required file is `APKBUILD`. Package-specific helpers can be added as
|
Optional package hooks:
|
||||||
hooks:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
packaging/alpine/local/<pkgname>/scripts/test-install.sh
|
packaging/alpine/local/<pkgname>/scripts/test-install.sh
|
||||||
packaging/alpine/local/<pkgname>/scripts/update-generated-sources.sh
|
packaging/alpine/local/<pkgname>/scripts/update-generated-sources.sh
|
||||||
|
packaging/alpine/local/<pkgname>/scripts/runtime-test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Repo-level tasks discover all `packaging/alpine/local/*/APKBUILD` files. Hook
|
Start from the blueprint:
|
||||||
tasks skip packages that do not provide the requested hook.
|
|
||||||
|
|
||||||
Start new packages from the blueprint:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
packaging/alpine/blueprint/
|
packaging/alpine/blueprint/
|
||||||
```
|
```
|
||||||
|
|
||||||
For compiled software, declare build tools in `makedepends` and use normal
|
|
||||||
Alpine `build()`, `check()`, and `package()` functions in the package's
|
|
||||||
`APKBUILD`.
|
|
||||||
|
|
||||||
### Generated Package Sources
|
### Generated Package Sources
|
||||||
|
|
||||||
Generated files should live next to the package's `APKBUILD` so
|
Generated package sources live next to the package `APKBUILD`:
|
||||||
`abuild checksum` can track them as ordinary package sources. For SeaweedFS,
|
|
||||||
that includes:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
packaging/alpine/local/seaweedfs/example-*.toml
|
packaging/alpine/local/seaweedfs/example-*.toml
|
||||||
packaging/alpine/local/seaweedfs/weed.bash-completion
|
packaging/alpine/local/seaweedfs/weed.bash-completion
|
||||||
```
|
```
|
||||||
|
|
||||||
Refresh generated sources through package-local hooks:
|
Refresh generated sources:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mise run apk:update-generated
|
mise run apk:update-generated
|
||||||
@@ -318,13 +221,43 @@ ALPINE_PACKAGE=seaweedfs mise run apk:update-generated
|
|||||||
mise run apk:checksum
|
mise run apk:checksum
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `apk:checksum` after changing any file listed in `source=`.
|
### Upstream Update Visibility
|
||||||
|
|
||||||
|
Check whether packaged upstream versions are current:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mise run apk:outdated
|
||||||
|
ALPINE_PACKAGE=seaweedfs mise run apk:outdated
|
||||||
|
```
|
||||||
|
|
||||||
|
By default this is a warning-only signal. To make outdated or unknown package
|
||||||
|
versions fail the command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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
|
### Gitea Workflow
|
||||||
|
|
||||||
The workflow at `.gitea/workflows/build.yml` builds in an `alpine:3.23`
|
The smoke test installs rebuilt artifacts from the local repository and uses
|
||||||
container and publishes on push or tag. It skips publishing for pull request
|
the published registry as a fallback for unchanged packages.
|
||||||
events.
|
|
||||||
|
|
||||||
Repository variables:
|
Repository variables:
|
||||||
|
|
||||||
@@ -341,13 +274,13 @@ PACKAGE_USER=<gitea package publisher>
|
|||||||
PACKAGE_TOKEN=<token with package write access>
|
PACKAGE_TOKEN=<token with package write access>
|
||||||
```
|
```
|
||||||
|
|
||||||
Pre-check the workflow locally with `act`:
|
Check the workflow locally:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mise run gitea-workflow-build
|
mise run gitea-workflow-build
|
||||||
```
|
```
|
||||||
|
|
||||||
Publish already-built local packages manually:
|
Publish local packages:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
INSTANCE_URL=https://code.factoring.digital \
|
INSTANCE_URL=https://code.factoring.digital \
|
||||||
@@ -358,25 +291,7 @@ PACKAGE_TOKEN=... \
|
|||||||
mise run apk:publish-gitea
|
mise run apk:publish-gitea
|
||||||
```
|
```
|
||||||
|
|
||||||
### Alpine Package Rules
|
### Checklist
|
||||||
|
|
||||||
Do:
|
|
||||||
|
|
||||||
- Keep local package sources next to the `APKBUILD`.
|
|
||||||
- Put full upstream scaffolds in `/usr/share/doc/seaweedfs/examples/`, not active `/etc`.
|
|
||||||
- Install only the OpenRC role packages needed on each node.
|
|
||||||
- Keep `/etc/conf.d` defaults short and production-neutral.
|
|
||||||
- Increment `pkgrel` for package-only changes; reset it when `pkgver` changes.
|
|
||||||
- Run `mise run apk:publish-check` before opening a PR.
|
|
||||||
|
|
||||||
Don't:
|
|
||||||
|
|
||||||
- Edit generated `src/`, `pkg/`, or `packages/` output.
|
|
||||||
- Hand-edit checksum lines when `abuild checksum` can update them.
|
|
||||||
- Install all OpenRC roles by default.
|
|
||||||
- Put long upstream examples into active `/etc` defaults.
|
|
||||||
|
|
||||||
### Practical PR Checklist
|
|
||||||
|
|
||||||
Before opening a PR, run:
|
Before opening a PR, run:
|
||||||
|
|
||||||
@@ -384,12 +299,14 @@ Before opening a PR, run:
|
|||||||
mise run apk:publish-check
|
mise run apk:publish-check
|
||||||
mise run gitea-workflow-build
|
mise run gitea-workflow-build
|
||||||
mise run apk:test-install
|
mise run apk:test-install
|
||||||
|
mise run apk:runtime-test
|
||||||
```
|
```
|
||||||
|
|
||||||
Then test at least one installed role in the package shell:
|
Then test at least one installed role in the package shell:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mise run apk:test-shell
|
mise run apk:test-shell
|
||||||
|
apk add seaweedfs seaweedfs-master-openrc
|
||||||
rc-service seaweedfs.master start
|
rc-service seaweedfs.master start
|
||||||
weed version
|
weed version
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env -S mise tool-stub
|
|
||||||
# GrepTimeDB 1.0.2 release binary.
|
|
||||||
|
|
||||||
version = "1.0.2"
|
|
||||||
bin = "greptime"
|
|
||||||
|
|
||||||
[platforms.linux-x64]
|
|
||||||
url = "https://github.com/GreptimeTeam/greptimedb/releases/download/v1.0.2/greptime-linux-amd64-v1.0.2.tar.gz"
|
|
||||||
checksum = "sha256:1ad1f9312ce18a49494434cf52cf9fa00093c4712728508bff4578d060fb2d89"
|
|
||||||
|
|
||||||
[platforms.linux-arm64]
|
|
||||||
url = "https://github.com/GreptimeTeam/greptimedb/releases/download/v1.0.2/greptime-linux-arm64-v1.0.2.tar.gz"
|
|
||||||
checksum = "sha256:e6567f5d97fd34b876b5653c22877c238a1633ecbe26b3b7c22b95892656c39c"
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env -S mise tool-stub
|
|
||||||
# SeaweedFS 4.31 release binary.
|
|
||||||
|
|
||||||
version = "4.31"
|
|
||||||
bin = "weed"
|
|
||||||
|
|
||||||
[platforms.linux-x64]
|
|
||||||
url = "https://github.com/seaweedfs/seaweedfs/releases/download/4.31/linux_amd64.tar.gz"
|
|
||||||
checksum = "sha256:81103c53453fddfa75d9d611cd3e61aa57e7a3099dc7a1de5977ab4b19211958"
|
|
||||||
size = 43223476
|
|
||||||
|
|
||||||
[platforms.linux-arm64]
|
|
||||||
url = "https://github.com/seaweedfs/seaweedfs/releases/download/4.31/linux_arm64.tar.gz"
|
|
||||||
checksum = "sha256:76ac1ffce87a2a710a3913282a19de6d9a3785f4a3586556858ec7b81a87d958"
|
|
||||||
size = 38036794
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# 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.
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
# @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"]
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
[tools]
|
[tools]
|
||||||
act = "latest"
|
act = "latest"
|
||||||
codex = "latest"
|
|
||||||
docker-cli = "latest"
|
docker-cli = "latest"
|
||||||
|
jq = "latest"
|
||||||
shellcheck = "latest"
|
shellcheck = "latest"
|
||||||
|
trivy = "latest"
|
||||||
|
|
||||||
[tasks."apk:build"]
|
[tasks."apk:build"]
|
||||||
description = "Build the Alpine package in Docker for the default architecture"
|
description = "Build the Alpine package in Docker for the default architecture"
|
||||||
@@ -36,6 +37,10 @@ run = "scripts/apk/update-generated-sources.sh"
|
|||||||
description = "Run Alpine APKBUILD lint in Docker"
|
description = "Run Alpine APKBUILD lint in Docker"
|
||||||
run = "scripts/apk/build.sh lint"
|
run = "scripts/apk/build.sh lint"
|
||||||
|
|
||||||
|
[tasks."apk:lint-shell"]
|
||||||
|
description = "Run ShellCheck for packaging automation"
|
||||||
|
run = "scripts/apk/lint-shell.sh"
|
||||||
|
|
||||||
[tasks."apk:smoke"]
|
[tasks."apk:smoke"]
|
||||||
description = "Install-test built packages from the local repository in Docker"
|
description = "Install-test built packages from the local repository in Docker"
|
||||||
run = "scripts/apk/smoke.sh"
|
run = "scripts/apk/smoke.sh"
|
||||||
@@ -45,17 +50,30 @@ description = "Install-test built packages directly in the current Alpine enviro
|
|||||||
run = "scripts/apk/ci-smoke.sh"
|
run = "scripts/apk/ci-smoke.sh"
|
||||||
|
|
||||||
[tasks."apk:test-shell"]
|
[tasks."apk:test-shell"]
|
||||||
description = "Open an Alpine shell with the current local package build installed"
|
description = "Open an Alpine shell with the local APK repository configured"
|
||||||
run = "scripts/apk/test-shell.sh"
|
run = "scripts/apk/test-shell.sh"
|
||||||
|
|
||||||
[tasks."apk:test-install"]
|
[tasks."apk:test-install"]
|
||||||
description = "Test README installation instructions in a fresh Alpine container"
|
description = "Test README installation instructions in a fresh Alpine container"
|
||||||
run = "scripts/apk/test-install.sh"
|
run = "scripts/apk/test-install.sh"
|
||||||
|
|
||||||
|
[tasks."apk:runtime-test"]
|
||||||
|
description = "Run package-local Docker runtime tests against the local Alpine repository"
|
||||||
|
run = "scripts/apk/runtime-test.sh"
|
||||||
|
env = { ALPINE_ARCH = "x86_64", ALPINE_REPO_NAME = "local", ALPINE_VERSION = "3.24" }
|
||||||
|
|
||||||
[tasks."apk:packages"]
|
[tasks."apk:packages"]
|
||||||
description = "List built Alpine packages and dependencies"
|
description = "List built Alpine packages and dependencies"
|
||||||
run = "scripts/apk/list-packages.sh"
|
run = "scripts/apk/list-packages.sh"
|
||||||
|
|
||||||
|
[tasks."apk:outdated"]
|
||||||
|
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"]
|
[tasks."apk:publish-check"]
|
||||||
description = "Run lint, multi-arch build, package listing, and smoke test"
|
description = "Run lint, multi-arch build, package listing, and smoke test"
|
||||||
run = "scripts/apk/publish-check.sh"
|
run = "scripts/apk/publish-check.sh"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ Optional package-local hooks:
|
|||||||
- `scripts/test-install.sh` validates README-style installation instructions.
|
- `scripts/test-install.sh` validates README-style installation instructions.
|
||||||
- `scripts/update-generated-sources.sh` refreshes generated files that are
|
- `scripts/update-generated-sources.sh` refreshes generated files that are
|
||||||
listed in `source=`.
|
listed in `source=`.
|
||||||
|
- `scripts/runtime-test.sh` validates an installed package in the shared Docker
|
||||||
|
runtime test.
|
||||||
|
|
||||||
Repo-level tasks discover packages from `packaging/alpine/local/*/APKBUILD`.
|
Repo-level tasks discover packages from `packaging/alpine/local/*/APKBUILD`.
|
||||||
Limit a task to one or more packages with:
|
Limit a task to one or more packages with:
|
||||||
@@ -20,6 +22,7 @@ Limit a task to one or more packages with:
|
|||||||
ALPINE_PACKAGE=<pkgname> mise run apk:build
|
ALPINE_PACKAGE=<pkgname> mise run apk:build
|
||||||
ALPINE_PACKAGES="<pkg-a> <pkg-b>" mise run apk:build-all
|
ALPINE_PACKAGES="<pkg-a> <pkg-b>" mise run apk:build-all
|
||||||
ALPINE_PACKAGE=<pkgname> mise run apk:test-install
|
ALPINE_PACKAGE=<pkgname> mise run apk:test-install
|
||||||
|
ALPINE_PACKAGE=<pkgname> mise run apk:runtime-test
|
||||||
```
|
```
|
||||||
|
|
||||||
For compiled software, put normal Alpine build logic in `build()`, `check()`,
|
For compiled software, put normal Alpine build logic in `build()`, `check()`,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
|
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
|
||||||
package_name="${PACKAGE_NAME:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)")}"
|
package_name="${PACKAGE_NAME:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)")}"
|
||||||
alpine_version="${ALPINE_VERSION:-3.23}"
|
alpine_version="${ALPINE_VERSION:-3.24}"
|
||||||
arch="${ALPINE_ARCH:-x86_64}"
|
arch="${ALPINE_ARCH:-x86_64}"
|
||||||
|
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
|
||||||
|
pkgname=gitea
|
||||||
|
pkgver=28.2.0
|
||||||
|
pkgrel=0
|
||||||
|
pkgdesc="Self-hosted Git service written in Go"
|
||||||
|
url="https://about.gitea.com/"
|
||||||
|
arch="x86_64 aarch64"
|
||||||
|
license="MIT"
|
||||||
|
depends="git git-lfs gnupg"
|
||||||
|
makedepends="tar xz"
|
||||||
|
provides="cmd:gitea=$pkgver-r$pkgrel"
|
||||||
|
install="$pkgname.pre-install"
|
||||||
|
pkgusers="gitea"
|
||||||
|
pkggroups="www-data"
|
||||||
|
subpackages="
|
||||||
|
$pkgname-doc
|
||||||
|
$pkgname-logrotate:_logrotate:noarch
|
||||||
|
$pkgname-openrc:_openrc:noarch
|
||||||
|
"
|
||||||
|
options="!check !strip !tracedeps"
|
||||||
|
|
||||||
|
case "$CARCH" in
|
||||||
|
x86_64)
|
||||||
|
_archive="$pkgname-$pkgver-linux-amd64.xz"
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
_archive="$pkgname-$pkgver-linux-arm64.xz"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
source="
|
||||||
|
$pkgname-$pkgver-linux-amd64.xz::https://github.com/go-gitea/gitea/releases/download/v$pkgver/gitea-$pkgver-linux-amd64.xz
|
||||||
|
$pkgname-$pkgver-linux-arm64.xz::https://github.com/go-gitea/gitea/releases/download/v$pkgver/gitea-$pkgver-linux-arm64.xz
|
||||||
|
$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"
|
||||||
|
|
||||||
|
prepare() {
|
||||||
|
default_prepare
|
||||||
|
xz -dc "$srcdir/$_archive" > "$srcdir"/gitea
|
||||||
|
chmod 0755 "$srcdir"/gitea
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
local _dir
|
||||||
|
for _dir in gitea gitea/git gitea/data gitea/db gitea/custom; do
|
||||||
|
install -d -m 0750 -o gitea -g www-data \
|
||||||
|
"$pkgdir"/var/lib/$_dir
|
||||||
|
done
|
||||||
|
|
||||||
|
install -d -m 0755 -o gitea -g www-data "$pkgdir"/var/log/gitea
|
||||||
|
install -Dm755 "$srcdir"/gitea "$pkgdir"/usr/bin/gitea
|
||||||
|
install -Dm644 -o gitea -g www-data "$srcdir"/gitea.ini \
|
||||||
|
"$pkgdir"/etc/gitea/app.ini
|
||||||
|
chown gitea:www-data "$pkgdir"/etc/gitea
|
||||||
|
|
||||||
|
install -d -m 0755 "$pkgdir"/usr/share/webapps/gitea
|
||||||
|
cp -r "$builddir"/options "$builddir"/public "$builddir"/templates \
|
||||||
|
"$pkgdir"/usr/share/webapps/gitea/
|
||||||
|
install -Dm644 "$builddir"/LICENSE -t "$pkgdir"/usr/share/licenses/gitea/
|
||||||
|
}
|
||||||
|
|
||||||
|
_openrc() {
|
||||||
|
pkgdesc="$pkgdesc (OpenRC service)"
|
||||||
|
depends="$pkgname=$pkgver-r$pkgrel 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
|
||||||
|
9474d707df8b049c93ec4642f71195adff699e1e812f315cac4295b3ab29eeb9ba8b83bf3307c50b04e072a4a9dc4c4f84ac490ee22291bd50015009795c1598 gitea.initd
|
||||||
|
456a565123b46c0c3a36adbde4c881ee04557a2f1ba492a76205c28f72598bf3b7b96192ddeae4f9ab197fdc75bb5e10a3421574e1bf831192220b4540bb39fc gitea.logrotate
|
||||||
|
"
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Gitea Alpine Package
|
||||||
|
|
||||||
|
Repackages upstream Gitea 1.27.0 Linux release binaries for `x86_64` and
|
||||||
|
`aarch64`.
|
||||||
|
|
||||||
|
The package follows Alpine's Gitea runtime layout:
|
||||||
|
|
||||||
|
- `/usr/bin/gitea`
|
||||||
|
- `/etc/gitea/app.ini`
|
||||||
|
- `/var/lib/gitea`
|
||||||
|
- `/var/log/gitea`
|
||||||
|
- `/usr/share/webapps/gitea`
|
||||||
|
|
||||||
|
Install the OpenRC service with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add gitea gitea-openrc
|
||||||
|
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
|
||||||
|
ALPINE_PACKAGE=gitea mise run apk:checksum
|
||||||
|
```
|
||||||
|
|
||||||
|
Build:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ALPINE_PACKAGE=gitea mise run apk:build
|
||||||
|
```
|
||||||
|
|
||||||
|
Install-test local build:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ALPINE_PACKAGE=gitea SKIP_BUILD=1 mise run apk:test-install
|
||||||
|
```
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
RUN_USER = gitea
|
||||||
|
RUN_MODE = prod
|
||||||
|
|
||||||
|
[repository]
|
||||||
|
ROOT = /var/lib/gitea/git
|
||||||
|
SCRIPT_TYPE = sh
|
||||||
|
|
||||||
|
[server]
|
||||||
|
STATIC_ROOT_PATH = /usr/share/webapps/gitea
|
||||||
|
APP_DATA_PATH = /var/lib/gitea/data
|
||||||
|
LFS_START_SERVER = true
|
||||||
|
|
||||||
|
[database]
|
||||||
|
DB_TYPE = sqlite3
|
||||||
|
PATH = /var/lib/gitea/db/gitea.db
|
||||||
|
SSL_MODE = disable
|
||||||
|
|
||||||
|
[session]
|
||||||
|
PROVIDER = file
|
||||||
|
|
||||||
|
[log]
|
||||||
|
ROOT_PATH = /var/log/gitea
|
||||||
|
MODE = file
|
||||||
|
LEVEL = Info
|
||||||
Executable
+30
@@ -0,0 +1,30 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
supervisor=supervise-daemon
|
||||||
|
name=gitea
|
||||||
|
command="/usr/bin/gitea"
|
||||||
|
command_user="${GITEA_USER:-gitea}"
|
||||||
|
command_args="web --config '${GITEA_CONF:-/etc/gitea/app.ini}'"
|
||||||
|
supervise_daemon_args="--env GITEA_WORK_DIR='${GITEA_WORK_DIR:-/var/lib/gitea}' --chdir '${GITEA_WORK_DIR:-/var/lib/gitea}' --stdout '${GITEA_LOG_FILE:-/var/log/gitea/http.log}' --stderr '${GITEA_LOG_FILE:-/var/log/gitea/http.log}'"
|
||||||
|
pidfile="/run/gitea.pid"
|
||||||
|
extra_started_commands="reopen_log"
|
||||||
|
capabilities="^cap_net_bind_service"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
use logger dns
|
||||||
|
need net
|
||||||
|
after firewall mysql postgresql
|
||||||
|
}
|
||||||
|
|
||||||
|
# https://github.com/go-gitea/gitea/issues/17976
|
||||||
|
# reload() {
|
||||||
|
# ebegin "Reloading ${RC_SVCNAME}"
|
||||||
|
# ${supervisor} ${RC_SVCNAME} --signal HUP --pidfile "${pidfile}"
|
||||||
|
# eend $?
|
||||||
|
# }
|
||||||
|
|
||||||
|
reopen_log() {
|
||||||
|
ebegin "Reopening logfile for ${RC_SVCNAME}"
|
||||||
|
${supervisor} ${RC_SVCNAME} --signal USR1 --pidfile "${pidfile}"
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/var/log/gitea/http.log {
|
||||||
|
daily
|
||||||
|
rotate 14
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
copytruncate
|
||||||
|
su gitea www-data
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
addgroup -S www-data 2>/dev/null
|
||||||
|
adduser -S -D -H -h /var/lib/gitea -s /sbin/nologin \
|
||||||
|
-G www-data -g gitea gitea 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
apk add gitea gitea-doc gitea-openrc
|
||||||
|
|
||||||
|
test -x /usr/bin/gitea
|
||||||
|
test -f /etc/gitea/app.ini
|
||||||
|
test -d /var/lib/gitea
|
||||||
|
test -d /var/lib/gitea/git
|
||||||
|
test -d /var/lib/gitea/data
|
||||||
|
test -d /var/lib/gitea/db
|
||||||
|
test -d /var/log/gitea
|
||||||
|
test -d /usr/share/webapps/gitea/options
|
||||||
|
test -d /usr/share/webapps/gitea/public
|
||||||
|
test -d /usr/share/webapps/gitea/templates
|
||||||
|
test -f /etc/init.d/gitea
|
||||||
|
|
||||||
|
gitea --version
|
||||||
|
|
||||||
|
rc-update add gitea default || true
|
||||||
|
test -L /etc/runlevels/default/gitea
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
#!/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:-gitea}" "${PACKAGE_VERSION:-28.0.0-r1}" <<'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
|
||||||
|
apk update
|
||||||
|
apk add "${PACKAGE_NAME}"
|
||||||
|
installed_before="$(apk list -I "${PACKAGE_NAME}" | awk "{print \$1}")"
|
||||||
|
printf "Installed repository package before local upgrade: %s\n" "${installed_before}"
|
||||||
|
if [ "${installed_before}" = "${PACKAGE_NAME}-${PACKAGE_VERSION}" ]; then
|
||||||
|
printf "default repository already has %s; upgrade path was not exercised\n" "${PACKAGE_VERSION}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp "/repo/${ALPINE_ARCH}"/*.rsa.pub /etc/apk/keys/
|
||||||
|
printf "%s\n" /repo >> /etc/apk/repositories
|
||||||
|
fi
|
||||||
|
apk update
|
||||||
|
apk add --upgrade "${PACKAGE_NAME}" "${PACKAGE_NAME}-doc" "${PACKAGE_NAME}-logrotate" "${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}"
|
||||||
|
|
||||||
|
test -x /usr/bin/gitea
|
||||||
|
test -f /etc/gitea/app.ini
|
||||||
|
test -d /var/lib/gitea
|
||||||
|
test -d /var/lib/gitea/git
|
||||||
|
test -d /var/lib/gitea/data
|
||||||
|
test -d /var/lib/gitea/db
|
||||||
|
test -d /var/log/gitea
|
||||||
|
test -d /usr/share/webapps/gitea/options
|
||||||
|
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
|
||||||
|
|
||||||
|
rc-update add gitea default
|
||||||
|
test -L /etc/runlevels/default/gitea
|
||||||
|
SCRIPT
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
provider=github
|
||||||
|
repo=go-gitea/gitea
|
||||||
|
version_prefix=v
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# Maintainer: Joachim Schlöffel <me@joachim-schloeffel.com>
|
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
|
||||||
pkgname=greptimedb
|
pkgname=greptimedb
|
||||||
pkgver=1.0.2
|
pkgver=1.2.1
|
||||||
pkgrel=1
|
pkgrel=5
|
||||||
pkgdesc="Cloud-native observability database for metrics, logs, and traces"
|
pkgdesc="Cloud-native observability database for metrics, logs, and traces"
|
||||||
url="https://github.com/GreptimeTeam/greptimedb"
|
url="https://github.com/GreptimeTeam/greptimedb"
|
||||||
arch="x86_64"
|
arch="x86_64"
|
||||||
@@ -12,14 +12,17 @@ makedepends="
|
|||||||
clang
|
clang
|
||||||
cmake
|
cmake
|
||||||
coreutils
|
coreutils
|
||||||
curl
|
cargo-auditable
|
||||||
|
git
|
||||||
lld
|
lld
|
||||||
linux-headers
|
linux-headers
|
||||||
make
|
make
|
||||||
mold
|
mold
|
||||||
|
nodejs
|
||||||
openssl-dev
|
openssl-dev
|
||||||
openssl-libs-static
|
openssl-libs-static
|
||||||
perl
|
perl
|
||||||
|
pnpm
|
||||||
protobuf
|
protobuf
|
||||||
protobuf-dev
|
protobuf-dev
|
||||||
rustup
|
rustup
|
||||||
@@ -28,17 +31,22 @@ makedepends="
|
|||||||
zstd-dev
|
zstd-dev
|
||||||
zstd-static
|
zstd-static
|
||||||
"
|
"
|
||||||
|
checkdepends="cargo-nextest"
|
||||||
install="$pkgname.pre-install"
|
install="$pkgname.pre-install"
|
||||||
subpackages="
|
subpackages="
|
||||||
$pkgname-datanode-openrc:_openrc_datanode:noarch
|
$pkgname-datanode-openrc:_openrc_datanode:noarch
|
||||||
|
$pkgname-docs:_docs:noarch
|
||||||
$pkgname-flownode-openrc:_openrc_flownode:noarch
|
$pkgname-flownode-openrc:_openrc_flownode:noarch
|
||||||
$pkgname-frontend-openrc:_openrc_frontend:noarch
|
$pkgname-frontend-openrc:_openrc_frontend:noarch
|
||||||
|
$pkgname-logrotate:_logrotate:noarch
|
||||||
$pkgname-metasrv-openrc:_openrc_metasrv:noarch
|
$pkgname-metasrv-openrc:_openrc_metasrv:noarch
|
||||||
$pkgname-standalone-openrc:_openrc_standalone:noarch
|
$pkgname-standalone-openrc:_openrc_standalone:noarch
|
||||||
"
|
"
|
||||||
options="net"
|
options="net"
|
||||||
|
_dashboard_version="v0.12.0"
|
||||||
source="
|
source="
|
||||||
$pkgname-$pkgver.tar.gz::https://github.com/GreptimeTeam/greptimedb/archive/refs/tags/v$pkgver.tar.gz
|
$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
|
||||||
datanode.toml
|
datanode.toml
|
||||||
flownode.toml
|
flownode.toml
|
||||||
frontend.toml
|
frontend.toml
|
||||||
@@ -46,6 +54,7 @@ source="
|
|||||||
greptimedb.flownode.confd
|
greptimedb.flownode.confd
|
||||||
greptimedb.frontend.confd
|
greptimedb.frontend.confd
|
||||||
greptimedb.initd
|
greptimedb.initd
|
||||||
|
greptimedb.logrotate
|
||||||
greptimedb.metasrv.confd
|
greptimedb.metasrv.confd
|
||||||
greptimedb.standalone.confd
|
greptimedb.standalone.confd
|
||||||
metasrv.toml
|
metasrv.toml
|
||||||
@@ -61,27 +70,45 @@ export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-2}"
|
|||||||
export CARGO_PROFILE_NIGHTLY_CODEGEN_UNITS="${CARGO_PROFILE_NIGHTLY_CODEGEN_UNITS:-16}"
|
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_DEBUG="${CARGO_PROFILE_NIGHTLY_DEBUG:-false}"
|
||||||
export CARGO_PROFILE_NIGHTLY_LTO="${CARGO_PROFILE_NIGHTLY_LTO:-thin}"
|
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 LIBRARY_PATH="/usr/lib"
|
||||||
|
export RUSTFLAGS="${RUSTFLAGS:-} -C link-arg=-fuse-ld=mold"
|
||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
default_prepare
|
default_prepare
|
||||||
|
|
||||||
rustup-init \
|
rustup-init \
|
||||||
-y \
|
-y \
|
||||||
--no-modify-path \
|
--no-modify-path \
|
||||||
--profile minimal \
|
--profile minimal \
|
||||||
--default-toolchain "$_rust_toolchain"
|
--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() {
|
build() {
|
||||||
"$CARGO_HOME"/bin/rustup run "$_rust_toolchain" cargo build \
|
"$CARGO_HOME"/bin/rustup run "$_rust_toolchain" cargo auditable build \
|
||||||
--profile "$_cargo_profile" \
|
--profile "$_cargo_profile" \
|
||||||
|
--frozen \
|
||||||
--locked \
|
--locked \
|
||||||
--bin greptime \
|
--bin greptime \
|
||||||
--features servers/dashboard
|
--features servers/dashboard
|
||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
"$CARGO_TARGET_DIR"/"$_cargo_profile"/greptime --version
|
"$CARGO_HOME"/bin/rustup run "$_rust_toolchain" cargo nextest run \
|
||||||
|
-p cmd \
|
||||||
|
--lib \
|
||||||
|
--frozen
|
||||||
}
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
@@ -111,15 +138,33 @@ _openrc_frontend() { _openrc_service frontend; }
|
|||||||
_openrc_metasrv() { _openrc_service metasrv; }
|
_openrc_metasrv() { _openrc_service metasrv; }
|
||||||
_openrc_standalone() { _openrc_service standalone; }
|
_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=""
|
||||||
|
|
||||||
|
mkdir -p "$subpkgdir"/usr/share/doc/$pkgname
|
||||||
|
cp -a "$builddir"/config "$subpkgdir"/usr/share/doc/$pkgname/
|
||||||
|
}
|
||||||
|
|
||||||
sha512sums="
|
sha512sums="
|
||||||
7f4ac722b84a26816030e65d504b37a53edfca15de669a4f6ee7a903f1a29c8358dcc2376a0a6cfd9ded13b0c5d7550a6856b9b10dc8cd080c6b12970553a0ea greptimedb-1.0.2.tar.gz
|
fc580f6e34df84b4f37219047d751968324c356f3cad352d1515abb4b441515a1ad98f0d01e2de33aac5129a2d7a5335edc4d8888923da7683a084a484769bea greptimedb-1.2.1.tar.gz
|
||||||
|
3f853b6767a86cfa97ec640a17de59b2e798561c9402026e9b3a749907780b9b686149dba8a932b5d61ae538c430deab2410248e5c9e6e1961909000445ee2ee dashboard-v0.12.0.tar.gz
|
||||||
29cc3376753487b216748e3f85e12639830e1ac4a763e94f330f87c3651a8ef9de35732958311c0049e1b7cbb4e90a9e602b3aff43297fe088c5ce795a110a79 datanode.toml
|
29cc3376753487b216748e3f85e12639830e1ac4a763e94f330f87c3651a8ef9de35732958311c0049e1b7cbb4e90a9e602b3aff43297fe088c5ce795a110a79 datanode.toml
|
||||||
52790808cb4f5cf0220ac2ab169b623fe76b6318d27d7f003e1197e850373cb915bfd40556098bcb7650f293d751039cb3bccbf9107bb160b8284887794ba975 flownode.toml
|
52790808cb4f5cf0220ac2ab169b623fe76b6318d27d7f003e1197e850373cb915bfd40556098bcb7650f293d751039cb3bccbf9107bb160b8284887794ba975 flownode.toml
|
||||||
e3e19ab3c7a345ecf8cf0a507f7fc95dd3b036a4a797385cf77fcf1999f2e4f053042c7bbda8de73ed43ff72e87aad81e4ac6d4a34d01773bbc1f6d0d967d9f7 frontend.toml
|
e3e19ab3c7a345ecf8cf0a507f7fc95dd3b036a4a797385cf77fcf1999f2e4f053042c7bbda8de73ed43ff72e87aad81e4ac6d4a34d01773bbc1f6d0d967d9f7 frontend.toml
|
||||||
313ed7d9ccd174b1869f3009e174266cdc414599e0b0f8307c8aaf2b73841eb36ce4c1b2f6244a0358b5a587a4edaa621b781fbd767835088b3fa13623fcc0df greptimedb.datanode.confd
|
313ed7d9ccd174b1869f3009e174266cdc414599e0b0f8307c8aaf2b73841eb36ce4c1b2f6244a0358b5a587a4edaa621b781fbd767835088b3fa13623fcc0df greptimedb.datanode.confd
|
||||||
daf8efacc8bf2b74abd9f4900f889585295b57333a8a562a722de0596d35f25d5f9149e0879f4140bfdf727caa59c3f55b1380212722df92c588d912275530b8 greptimedb.flownode.confd
|
daf8efacc8bf2b74abd9f4900f889585295b57333a8a562a722de0596d35f25d5f9149e0879f4140bfdf727caa59c3f55b1380212722df92c588d912275530b8 greptimedb.flownode.confd
|
||||||
e3e61b1df00f8172a3b1d4a0d37ed2574a8c5cd27676b4e2ce14d15ad8933d233baabe8da374f715d00cfaee26f665244c1ba00f70197fcc713c4e9af9c3229e greptimedb.frontend.confd
|
e3e61b1df00f8172a3b1d4a0d37ed2574a8c5cd27676b4e2ce14d15ad8933d233baabe8da374f715d00cfaee26f665244c1ba00f70197fcc713c4e9af9c3229e greptimedb.frontend.confd
|
||||||
c00740aee566b161bbe3610e0e0d6e8340022055750e6778772262474ffd6484d9f58be2fd498beafe28d0943e259e2277930af691bedea7650726e6c8998881 greptimedb.initd
|
f72f52aa8277fc56eb071b5118990b8f4e09d143634c2f7fc54ed1f5ff065631c8630c45fe90d3db1f3ea0540c1ab3154a383d2000b4c5978e889ca02a1b6564 greptimedb.initd
|
||||||
|
775b4db7e7bc6127376b22fed8330b952c5027e3bfbfa29bb6ae034e6c75e7fed8ddfc0ad9761f369acd37398dfbd145cfea210828f2fc0bec9be92b051e6a75 greptimedb.logrotate
|
||||||
df495367d85844dcba99e5aa01e5a23fd14799b7521a72d9ea00d29fc0e5fbc5c5d06ee88e88d9637e260f8337249a39d2b0115de58da4899824d20bd844254a greptimedb.metasrv.confd
|
df495367d85844dcba99e5aa01e5a23fd14799b7521a72d9ea00d29fc0e5fbc5c5d06ee88e88d9637e260f8337249a39d2b0115de58da4899824d20bd844254a greptimedb.metasrv.confd
|
||||||
882a79e969cac42adfada22060e6507fb687755a6d266d6728154b3e4da5777d2eaf5ad9bc331ed050448249ca609e6a61977b624d9faf25d83ed975345452cf greptimedb.standalone.confd
|
882a79e969cac42adfada22060e6507fb687755a6d266d6728154b3e4da5777d2eaf5ad9bc331ed050448249ca609e6a61977b624d9faf25d83ed975345452cf greptimedb.standalone.confd
|
||||||
8120ec338ebe1330d43b20d9b34a8f5f778ea13cb056febd3c8e9dc189d0de2380b90e5474a0990294d7004827c6133d44d2dd3e32d463b9259c47c82592d257 metasrv.toml
|
8120ec338ebe1330d43b20d9b34a8f5f778ea13cb056febd3c8e9dc189d0de2380b90e5474a0990294d7004827c6133d44d2dd3e32d463b9259c47c82592d257 metasrv.toml
|
||||||
|
|||||||
@@ -1,42 +1,105 @@
|
|||||||
# GreptimeDB Alpine Package
|
# GreptimeDB Alpine Package
|
||||||
|
|
||||||
This package builds `greptime` from the upstream GreptimeDB source release and packages OpenRC service subpackages plus default `/etc/greptimedb` configuration.
|
Builds `greptime` and its embedded dashboard from their upstream source
|
||||||
|
releases, and packages OpenRC service subpackages plus `/etc/greptimedb`
|
||||||
|
defaults.
|
||||||
|
|
||||||
The APKBUILD builds the release directly:
|
Build command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo build --profile nightly --locked --bin greptime --features servers/dashboard
|
cargo auditable build --profile nightly --frozen --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:
|
||||||
|
|
||||||
|
- `greptimedb-docs`: upstream configuration examples and reference files from
|
||||||
|
`config/`
|
||||||
|
- `greptimedb-standalone-openrc`: `greptime standalone start`
|
||||||
|
- `greptimedb-metasrv-openrc`: `greptime metasrv start`
|
||||||
|
- `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:
|
||||||
|
|
||||||
|
- `127.0.0.1:4000`: HTTP API and dashboard
|
||||||
|
- `127.0.0.1:4001`: gRPC
|
||||||
|
- `127.0.0.1:4002`: MySQL
|
||||||
|
- `127.0.0.1:4003`: PostgreSQL
|
||||||
|
|
||||||
|
Configs bind to localhost by default. Upstream config examples are in
|
||||||
|
`/usr/share/doc/greptimedb/config`.
|
||||||
|
|
||||||
|
## OpenRC Usage
|
||||||
|
|
||||||
|
Standalone:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add greptimedb greptimedb-docs greptimedb-standalone-openrc
|
||||||
|
rc-update add greptimedb.standalone default
|
||||||
|
rc-service greptimedb.standalone start
|
||||||
|
```
|
||||||
|
|
||||||
|
Distributed components:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add \
|
||||||
|
greptimedb \
|
||||||
|
greptimedb-metasrv-openrc \
|
||||||
|
greptimedb-datanode-openrc \
|
||||||
|
greptimedb-flownode-openrc \
|
||||||
|
greptimedb-frontend-openrc
|
||||||
|
```
|
||||||
|
|
||||||
|
Wrapper settings in `/etc/conf.d/greptimedb.<component>`:
|
||||||
|
|
||||||
|
- `GREPTIMEDB_CONFIG`: config file path passed with `-c`
|
||||||
|
- `GREPTIMEDB_LOG_DIR`: component log directory passed with `--log-dir`
|
||||||
|
- `GREPTIMEDB_DATA_HOME`: data directory passed with `--data-home` where the
|
||||||
|
component supports it
|
||||||
|
- `GREPTIMEDB_WAL_DIR`: datanode WAL directory passed with `--wal-dir`
|
||||||
|
- `GREPTIMEDB_OPTS`: extra component arguments appended after package defaults
|
||||||
|
- `GREPTIMEDB_GLOBAL_OPTS`: arguments inserted before the component command
|
||||||
|
|
||||||
## Package Commands
|
## Package Commands
|
||||||
|
|
||||||
Refresh the source checksum after changing `pkgver`:
|
Refresh checksums:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_PACKAGE=greptimedb mise run apk:checksum
|
ALPINE_PACKAGE=greptimedb mise run apk:checksum
|
||||||
```
|
```
|
||||||
|
|
||||||
Build only this package:
|
Build:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_PACKAGE=greptimedb mise run apk:build
|
ALPINE_PACKAGE=greptimedb mise run apk:build
|
||||||
```
|
```
|
||||||
|
|
||||||
Install-test an existing local build without recompiling:
|
Install-test local build:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_PACKAGE=greptimedb SKIP_BUILD=1 mise run apk:test-install
|
ALPINE_PACKAGE=greptimedb SKIP_BUILD=1 mise run apk:test-install
|
||||||
```
|
```
|
||||||
|
|
||||||
Install-test from a published Gitea Alpine repository:
|
Install-test published repository:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ALPINE_PACKAGE=greptimedb \
|
ALPINE_PACKAGE=greptimedb \
|
||||||
SKIP_BUILD=1 \
|
SKIP_BUILD=1 \
|
||||||
ALPINE_REPOSITORY_URL=https://code.factoring.digital/api/packages/public/alpine/v3.23/alpine-packages \
|
ALPINE_REPOSITORY_URL=https://code.factoring.digital/api/packages/public/alpine/v3.24/alpine-packages \
|
||||||
ALPINE_REPOSITORY_KEY_URL=https://code.factoring.digital/api/packages/public/alpine/key \
|
ALPINE_REPOSITORY_KEY_URL=https://code.factoring.digital/api/packages/public/alpine/key \
|
||||||
mise run apk:test-install
|
mise run apk:test-install
|
||||||
```
|
```
|
||||||
|
|
||||||
The full build can take close to an hour. Do not run it as part of lightweight
|
Full builds and the targeted upstream Nextest check take close to an hour.
|
||||||
metadata or script checks.
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ description="GreptimeDB ${service_name} service"
|
|||||||
command="/usr/bin/greptime"
|
command="/usr/bin/greptime"
|
||||||
command_user="${GREPTIMEDB_USER:-greptimedb}:${GREPTIMEDB_GROUP:-greptimedb}"
|
command_user="${GREPTIMEDB_USER:-greptimedb}:${GREPTIMEDB_GROUP:-greptimedb}"
|
||||||
command_background="yes"
|
command_background="yes"
|
||||||
|
retry="TERM/30/KILL/5"
|
||||||
pidfile="/run/greptimedb/${RC_SVCNAME}.pid"
|
pidfile="/run/greptimedb/${RC_SVCNAME}.pid"
|
||||||
output_log="${GREPTIMEDB_LOG:-/var/log/greptimedb/${RC_SVCNAME}.log}"
|
output_log="${GREPTIMEDB_LOG:-/var/log/greptimedb/${RC_SVCNAME}.log}"
|
||||||
error_log="${GREPTIMEDB_ERRLOG:-/var/log/greptimedb/${RC_SVCNAME}.log}"
|
error_log="${GREPTIMEDB_ERRLOG:-/var/log/greptimedb/${RC_SVCNAME}.log}"
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/var/log/greptimedb/greptimedb.*.log {
|
||||||
|
daily
|
||||||
|
rotate 14
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
copytruncate
|
||||||
|
su greptimedb greptimedb
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
apk add greptimedb \
|
||||||
|
greptimedb-datanode-openrc \
|
||||||
|
greptimedb-docs \
|
||||||
|
greptimedb-flownode-openrc \
|
||||||
|
greptimedb-frontend-openrc \
|
||||||
|
greptimedb-metasrv-openrc \
|
||||||
|
greptimedb-standalone-openrc
|
||||||
|
|
||||||
|
test -x /usr/bin/greptime
|
||||||
|
test -d /etc/greptimedb
|
||||||
|
test -f /etc/greptimedb/standalone.toml
|
||||||
|
test -f /etc/conf.d/greptimedb.standalone
|
||||||
|
test -f /etc/init.d/greptimedb.standalone
|
||||||
|
test -f /usr/share/doc/greptimedb/config/config.md
|
||||||
|
test -f /usr/share/doc/greptimedb/config/standalone.example.toml
|
||||||
|
|
||||||
|
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
|
||||||
@@ -2,43 +2,10 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
|
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
|
||||||
package_name="${PACKAGE_NAME:-greptimedb}"
|
# shellcheck source=scripts/apk/test-install-lib.sh
|
||||||
alpine_version="${ALPINE_VERSION:-3.23}"
|
. "${repo_root}/scripts/apk/test-install-lib.sh"
|
||||||
arch="${ALPINE_ARCH:-x86_64}"
|
|
||||||
repository_url="${ALPINE_REPOSITORY_URL:-}"
|
|
||||||
repository_key_url="${ALPINE_REPOSITORY_KEY_URL:-}"
|
|
||||||
|
|
||||||
case "${arch}" in
|
apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-greptimedb}" "${PACKAGE_VERSION:-}" <<'SCRIPT'
|
||||||
x86_64)
|
|
||||||
platform="${ALPINE_TEST_PLATFORM:-linux/amd64}"
|
|
||||||
;;
|
|
||||||
aarch64)
|
|
||||||
platform="${ALPINE_TEST_PLATFORM:-linux/arm64}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2
|
|
||||||
exit 2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ -z "${repository_url}" && "${SKIP_BUILD:-0}" != "1" ]]; then
|
|
||||||
ALPINE_PACKAGE="${package_name}" "${repo_root}/scripts/apk/build.sh" build "${arch}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "${repository_url}" && ! -d "${repo_root}/packages/local/${arch}" ]]; then
|
|
||||||
printf 'missing local repository: packages/local/%s\n' "${arch}" >&2
|
|
||||||
printf 'run: ALPINE_PACKAGE=%s mise run apk:build\n' "${package_name}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker run --rm --platform "${platform}" \
|
|
||||||
-e "ALPINE_ARCH=${arch}" \
|
|
||||||
-e "PACKAGE_NAME=${package_name}" \
|
|
||||||
-e "ALPINE_REPOSITORY_URL=${repository_url}" \
|
|
||||||
-e "ALPINE_REPOSITORY_KEY_URL=${repository_key_url}" \
|
|
||||||
-v "${repo_root}/packages/local:/repo:ro" \
|
|
||||||
"alpine:${alpine_version}" \
|
|
||||||
sh -lc '
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [ -n "${ALPINE_REPOSITORY_URL}" ]; then
|
if [ -n "${ALPINE_REPOSITORY_URL}" ]; then
|
||||||
@@ -56,13 +23,20 @@ docker run --rm --platform "${platform}" \
|
|||||||
apk add \
|
apk add \
|
||||||
"${PACKAGE_NAME}" \
|
"${PACKAGE_NAME}" \
|
||||||
"${PACKAGE_NAME}-datanode-openrc" \
|
"${PACKAGE_NAME}-datanode-openrc" \
|
||||||
|
"${PACKAGE_NAME}-docs" \
|
||||||
"${PACKAGE_NAME}-flownode-openrc" \
|
"${PACKAGE_NAME}-flownode-openrc" \
|
||||||
"${PACKAGE_NAME}-frontend-openrc" \
|
"${PACKAGE_NAME}-frontend-openrc" \
|
||||||
|
"${PACKAGE_NAME}-logrotate" \
|
||||||
"${PACKAGE_NAME}-metasrv-openrc" \
|
"${PACKAGE_NAME}-metasrv-openrc" \
|
||||||
"${PACKAGE_NAME}-standalone-openrc"
|
"${PACKAGE_NAME}-standalone-openrc"
|
||||||
|
|
||||||
test -x /usr/bin/greptime
|
test -x /usr/bin/greptime
|
||||||
greptime --version
|
greptime --version
|
||||||
ls -1 /etc/greptimedb
|
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
|
find /etc/init.d -maxdepth 1 -name "greptimedb.*" -print | sort
|
||||||
'
|
SCRIPT
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/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}"
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
provider=github
|
||||||
|
repo=GreptimeTeam/greptimedb
|
||||||
|
version_prefix=v
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
|
||||||
|
pkgname=lavinmq
|
||||||
|
pkgver=2.10.2
|
||||||
|
pkgrel=1
|
||||||
|
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
|
||||||
|
gc-dev
|
||||||
|
help2man
|
||||||
|
libevent-dev
|
||||||
|
lz4-dev
|
||||||
|
make
|
||||||
|
openssl
|
||||||
|
openssl-dev
|
||||||
|
pcre2-dev
|
||||||
|
shards
|
||||||
|
tar
|
||||||
|
yaml-dev
|
||||||
|
"
|
||||||
|
install="$pkgname.pre-install"
|
||||||
|
pkgusers="lavinmq"
|
||||||
|
pkggroups="lavinmq"
|
||||||
|
subpackages="
|
||||||
|
$pkgname-doc
|
||||||
|
$pkgname-logrotate:_logrotate:noarch
|
||||||
|
$pkgname-openrc:_openrc:noarch
|
||||||
|
"
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
crystal --version
|
||||||
|
make
|
||||||
|
make man
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
crystal spec spec/config_spec.cr
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
make DESTDIR="$pkgdir" install
|
||||||
|
rm -r "$pkgdir"/lib/systemd "$pkgdir"/usr/lib/sysusers.d
|
||||||
|
rmdir "$pkgdir"/lib "$pkgdir"/usr/lib
|
||||||
|
install -d -m 0750 -o lavinmq -g lavinmq "$pkgdir"/var/lib/lavinmq
|
||||||
|
}
|
||||||
|
|
||||||
|
_openrc() {
|
||||||
|
pkgdesc="$pkgdesc (OpenRC service)"
|
||||||
|
depends="$pkgname=$pkgver-r$pkgrel openrc"
|
||||||
|
|
||||||
|
install -Dm755 "$srcdir"/lavinmq.initd \
|
||||||
|
"$subpkgdir"/etc/init.d/lavinmq
|
||||||
|
install -Dm644 "$srcdir"/lavinmq.confd \
|
||||||
|
"$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
|
||||||
|
62a609d50f28db960098c4c84ce4f1dad78413366a9a9aca18fe321114d687be3bf7b71924d4ace69bd74383c5ac40d2ee09ae0eef9c1bfe653b97448e42e110 lavinmq.confd
|
||||||
|
1853196e70297b5c4a2207fde50df735620cf6d99c4994644fd676bffaf863d67300ad7ae771c4bbb86fce1a0485c2a7968cf912c5f5bb878e08b15e5a28ba1b lavinmq.initd
|
||||||
|
9999dd6a96bd29a3d0bda1b2110af940b15acf1250a0f3ba6c93d16bd62063ab1c1dfa4c237da99bbb401150517abde59e2c7275f4b72c3eb7c90e1ce61d43b9 lavinmq.logrotate
|
||||||
|
e7617099f745ecbf2f0686830d0a1b28044741ebd543798505b5b3c08f1be96b6cc478eb18f6785af49b100c2f49d837775f0721ac27519ddf3f081e681c581c use-vendored-build-inputs.patch
|
||||||
|
"
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
Build command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Runtime Layout
|
||||||
|
|
||||||
|
Installs:
|
||||||
|
|
||||||
|
- `lavinmq`
|
||||||
|
- `lavinmqctl`
|
||||||
|
- `lavinmqperf`
|
||||||
|
- `/etc/lavinmq/lavinmq.ini`
|
||||||
|
- `/var/lib/lavinmq`
|
||||||
|
|
||||||
|
Default ports:
|
||||||
|
|
||||||
|
- `5672`: AMQP
|
||||||
|
- `15672`: management UI
|
||||||
|
|
||||||
|
## OpenRC Usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add lavinmq lavinmq-doc lavinmq-openrc
|
||||||
|
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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ALPINE_PACKAGE=lavinmq mise run apk:checksum
|
||||||
|
```
|
||||||
|
|
||||||
|
Build:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ALPINE_PACKAGE=lavinmq mise run apk:build
|
||||||
|
```
|
||||||
|
|
||||||
|
Install-test local build:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ALPINE_PACKAGE=lavinmq SKIP_BUILD=1 mise run apk:test-install
|
||||||
|
```
|
||||||
|
|
||||||
|
Install-test published repository:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ALPINE_PACKAGE=lavinmq \
|
||||||
|
SKIP_BUILD=1 \
|
||||||
|
ALPINE_REPOSITORY_URL=https://code.factoring.digital/api/packages/public/alpine/v3.24/alpine-packages \
|
||||||
|
ALPINE_REPOSITORY_KEY_URL=https://code.factoring.digital/api/packages/public/alpine/key \
|
||||||
|
mise run apk:test-install
|
||||||
|
```
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,4 @@
|
|||||||
|
# Defaults for LavinMQ.
|
||||||
|
LAVINMQ_CONFIG="/etc/lavinmq/lavinmq.ini"
|
||||||
|
LAVINMQ_DATA_DIR="/var/lib/lavinmq"
|
||||||
|
LAVINMQ_OPTS=""
|
||||||
Executable
+28
@@ -0,0 +1,28 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
description="LavinMQ message queue service"
|
||||||
|
|
||||||
|
command="/usr/bin/lavinmq"
|
||||||
|
command_user="${LAVINMQ_USER:-lavinmq}:${LAVINMQ_GROUP:-lavinmq}"
|
||||||
|
command_background="yes"
|
||||||
|
pidfile="/run/lavinmq/lavinmq.pid"
|
||||||
|
output_log="${LAVINMQ_LOG:-/var/log/lavinmq/lavinmq.log}"
|
||||||
|
error_log="${LAVINMQ_ERRLOG:-/var/log/lavinmq/lavinmq.log}"
|
||||||
|
|
||||||
|
config_file="${LAVINMQ_CONFIG:-/etc/lavinmq/lavinmq.ini}"
|
||||||
|
data_dir="${LAVINMQ_DATA_DIR:-/var/lib/lavinmq}"
|
||||||
|
command_args="-D ${data_dir} --config ${config_file} ${LAVINMQ_OPTS:-}"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need net
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
local service_owner="${LAVINMQ_USER:-lavinmq}:${LAVINMQ_GROUP:-lavinmq}"
|
||||||
|
|
||||||
|
checkpath -d -m 0755 -o "$service_owner" \
|
||||||
|
/run/lavinmq \
|
||||||
|
/var/log/lavinmq
|
||||||
|
checkpath -d -m 0750 -o "$service_owner" "$data_dir"
|
||||||
|
checkpath -f -m 0640 -o "$service_owner" "$data_dir"/.lock
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/var/log/lavinmq/lavinmq.log {
|
||||||
|
daily
|
||||||
|
rotate 14
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
copytruncate
|
||||||
|
su lavinmq lavinmq
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
addgroup -S lavinmq 2>/dev/null
|
||||||
|
adduser -S -D -H -h /var/lib/lavinmq -s /sbin/nologin \
|
||||||
|
-G lavinmq -g lavinmq lavinmq 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
apk add lavinmq lavinmq-doc lavinmq-openrc
|
||||||
|
|
||||||
|
test -x /usr/bin/lavinmq
|
||||||
|
test -x /usr/bin/lavinmqctl
|
||||||
|
test -x /usr/bin/lavinmqperf
|
||||||
|
test -f /etc/lavinmq/lavinmq.ini
|
||||||
|
test -d /var/lib/lavinmq
|
||||||
|
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 /usr/share/doc/lavinmq/README.md
|
||||||
|
|
||||||
|
lavinmq -v
|
||||||
|
lavinmqctl --version
|
||||||
|
lavinmqperf --version
|
||||||
|
|
||||||
|
rc-update add lavinmq default || true
|
||||||
|
test -L /etc/runlevels/default/lavinmq
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
#!/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:-lavinmq}" "${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}" "${PACKAGE_NAME}-doc" "${PACKAGE_NAME}-logrotate" "${PACKAGE_NAME}-openrc"
|
||||||
|
|
||||||
|
test -x /usr/bin/lavinmq
|
||||||
|
test -x /usr/bin/lavinmqctl
|
||||||
|
test -x /usr/bin/lavinmqperf
|
||||||
|
test -f /etc/lavinmq/lavinmq.ini
|
||||||
|
test -d /var/lib/lavinmq
|
||||||
|
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
|
||||||
|
|
||||||
|
lavinmq -v
|
||||||
|
lavinmqctl --version
|
||||||
|
lavinmqperf --version
|
||||||
|
|
||||||
|
rc-update add lavinmq default
|
||||||
|
test -L /etc/runlevels/default/lavinmq
|
||||||
|
SCRIPT
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#!/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##*/}"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
provider=github
|
||||||
|
repo=cloudamqp/lavinmq
|
||||||
|
version_prefix=v
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
--- 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" "$@"
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# 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
|
||||||
|
"
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# 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
|
||||||
|
```
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Defaults for Apache NiFi.
|
||||||
|
NIFI_USER="nifi"
|
||||||
|
NIFI_GROUP="nifi"
|
||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
#!/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
|
||||||
|
}
|
||||||
Executable
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/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
|
||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec /usr/lib/nifi/bin/nifi.sh "$@"
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
#!/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
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
#!/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
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
provider="github"
|
||||||
|
repo="apache/nifi"
|
||||||
|
version_prefix="rel/nifi-"
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# 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
|
||||||
|
"
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# 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
|
||||||
|
```
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/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
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# 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"
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#!/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}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#!/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
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#!/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
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
# Maintainer: Joachim Schlöffel <me@joachim-schloeffel.com>
|
# Maintainer: Joachim Schlöffel <joachim.schloeffel@financial-service-plus.de>
|
||||||
pkgname=seaweedfs
|
pkgname=seaweedfs
|
||||||
pkgver=4.31
|
pkgver=4.48
|
||||||
pkgrel=3
|
pkgrel=4
|
||||||
pkgdesc="Distributed storage system for object storage, file systems, and Iceberg tables"
|
pkgdesc="Distributed storage system for object storage, file systems, and Iceberg tables"
|
||||||
url="https://github.com/seaweedfs/seaweedfs"
|
url="https://github.com/seaweedfs/seaweedfs"
|
||||||
arch="x86_64 aarch64"
|
arch="x86_64 aarch64"
|
||||||
license="Apache-2.0"
|
license="Apache-2.0"
|
||||||
depends="ca-certificates /bin/sh"
|
depends="ca-certificates /bin/sh"
|
||||||
|
makedepends="build-base cargo go protobuf-dev rust"
|
||||||
provides="!$pkgname-openrc cmd:weed=$pkgver-r$pkgrel"
|
provides="!$pkgname-openrc cmd:weed=$pkgver-r$pkgrel"
|
||||||
install="$pkgname.pre-install"
|
install="$pkgname.pre-install"
|
||||||
subpackages="
|
subpackages="
|
||||||
@@ -14,66 +15,78 @@ subpackages="
|
|||||||
$pkgname-bash-completion:_bashcomp:noarch
|
$pkgname-bash-completion:_bashcomp:noarch
|
||||||
$pkgname-doc
|
$pkgname-doc
|
||||||
$pkgname-filer-openrc:_openrc_filer:noarch
|
$pkgname-filer-openrc:_openrc_filer:noarch
|
||||||
|
$pkgname-logrotate:_logrotate:noarch
|
||||||
$pkgname-master-openrc:_openrc_master:noarch
|
$pkgname-master-openrc:_openrc_master:noarch
|
||||||
$pkgname-s3-openrc:_openrc_s3:noarch
|
$pkgname-s3-openrc:_openrc_s3:noarch
|
||||||
$pkgname-sftp-openrc:_openrc_sftp:noarch
|
$pkgname-sftp-openrc:_openrc_sftp:noarch
|
||||||
$pkgname-volume-openrc:_openrc_volume:noarch
|
$pkgname-volume-openrc:_openrc_volume:noarch
|
||||||
$pkgname-webdav-openrc:_openrc_webdav:noarch
|
$pkgname-webdav-openrc:_openrc_webdav:noarch
|
||||||
$pkgname-worker-openrc:_openrc_worker:noarch
|
$pkgname-worker-openrc:_openrc_worker:noarch
|
||||||
|
$pkgname-worker-lance:_worker_lance
|
||||||
|
$pkgname-worker-lance-openrc:_openrc_worker_lance:noarch
|
||||||
"
|
"
|
||||||
options="!check !strip !tracedeps"
|
options="!strip !tracedeps net"
|
||||||
|
|
||||||
case "$CARCH" in
|
|
||||||
x86_64)
|
|
||||||
_archive="$pkgname-$pkgver-linux-amd64.tar.gz"
|
|
||||||
;;
|
|
||||||
aarch64)
|
|
||||||
_archive="$pkgname-$pkgver-linux-arm64.tar.gz"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
source="
|
source="
|
||||||
$pkgname-$pkgver-linux-amd64.tar.gz::https://github.com/seaweedfs/seaweedfs/releases/download/$pkgver/linux_amd64.tar.gz
|
$pkgname-$pkgver-src.tar.gz::https://github.com/seaweedfs/seaweedfs/archive/refs/tags/$pkgver.tar.gz
|
||||||
$pkgname-$pkgver-linux-arm64.tar.gz::https://github.com/seaweedfs/seaweedfs/releases/download/$pkgver/linux_arm64.tar.gz
|
admin.toml
|
||||||
credential.toml
|
credential.toml
|
||||||
|
example-admin.toml
|
||||||
example-credential.toml
|
example-credential.toml
|
||||||
example-filer.toml
|
example-filer.toml
|
||||||
example-master.toml
|
example-master.toml
|
||||||
|
example-volume.toml
|
||||||
example-notification.toml
|
example-notification.toml
|
||||||
example-replication.toml
|
example-replication.toml
|
||||||
example-security.toml
|
example-security.toml
|
||||||
example-shell.toml
|
example-shell.toml
|
||||||
filer.toml
|
filer.toml
|
||||||
master.toml
|
master.toml
|
||||||
notification.toml
|
|
||||||
replication.toml
|
|
||||||
security.toml
|
security.toml
|
||||||
shell.toml
|
|
||||||
seaweedfs.admin.confd
|
seaweedfs.admin.confd
|
||||||
seaweedfs.filer.confd
|
seaweedfs.filer.confd
|
||||||
seaweedfs.initd
|
seaweedfs.initd
|
||||||
|
seaweedfs.logrotate
|
||||||
seaweedfs.master.confd
|
seaweedfs.master.confd
|
||||||
seaweedfs.s3.confd
|
seaweedfs.s3.confd
|
||||||
seaweedfs.sftp.confd
|
seaweedfs.sftp.confd
|
||||||
seaweedfs.volume.confd
|
seaweedfs.volume.confd
|
||||||
seaweedfs.webdav.confd
|
seaweedfs.webdav.confd
|
||||||
seaweedfs.worker.confd
|
seaweedfs.worker.confd
|
||||||
|
seaweedfs.worker-lance.confd
|
||||||
weed.bash-completion
|
weed.bash-completion
|
||||||
"
|
"
|
||||||
|
|
||||||
builddir="$srcdir"
|
_worker_builddir="$srcdir/$pkgname-$pkgver/seaweed-worker"
|
||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
default_prepare
|
default_prepare
|
||||||
tar -xzf "$srcdir/$_archive" -C "$builddir"
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
install -Dm755 "$srcdir"/weed "$pkgdir"/usr/bin/weed
|
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
|
||||||
local _config
|
local _config
|
||||||
for _config in credential filer master notification replication security shell; do
|
for _config in admin credential filer master security; do
|
||||||
install -Dm644 "$srcdir"/$_config.toml \
|
install -Dm644 "$srcdir"/$_config.toml \
|
||||||
"$pkgdir"/etc/seaweedfs/$_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 \
|
install -Dm644 "$srcdir"/example-$_config.toml \
|
||||||
"$pkgdir"/usr/share/doc/$pkgname/examples/$_config.toml
|
"$pkgdir"/usr/share/doc/$pkgname/examples/$_config.toml
|
||||||
done
|
done
|
||||||
@@ -99,6 +112,26 @@ _openrc_volume() { _openrc_service volume; }
|
|||||||
_openrc_webdav() { _openrc_service webdav; }
|
_openrc_webdav() { _openrc_service webdav; }
|
||||||
_openrc_worker() { _openrc_service worker; }
|
_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() {
|
_bashcomp() {
|
||||||
pkgdesc="Bash completions for $pkgname"
|
pkgdesc="Bash completions for $pkgname"
|
||||||
depends=""
|
depends=""
|
||||||
@@ -109,30 +142,31 @@ _bashcomp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sha512sums="
|
sha512sums="
|
||||||
60c758d6d565d0cbc533e4e5677186a4700d48be12ebbd2bd1c6b4bcf38f687d0ab1f66e0953c8a27c663549cdbae73e5fd7eda74bb422c20e10e0d0850b5ead seaweedfs-4.31-linux-amd64.tar.gz
|
91a34fec9bb78832f421b54dd823adb1c1690b746083d947c5f72e4ad7670362512bbb920432f42342482774fd8be2b396645ff3bc764b10f328432601733fe3 seaweedfs-4.48-src.tar.gz
|
||||||
93c7539fe15a0aa6192d26ac2360003961f0643e302d910179d02341b10a7243df776294fb1b0134ec2a2a9596b1abc3ce9ab701f9bc3d78f2b965ea464a4b18 seaweedfs-4.31-linux-arm64.tar.gz
|
58be6587b082f45b4dd22ad8ebb1b8bf84cea2a7c0cb6b4ad4a749ac0bfdf92d10d22281a432f9e5a87afa0b940cd0172671a292fbe17803e56425cd940d47f9 admin.toml
|
||||||
b6ce09d6d83dd70e2797a185171eea3587436fb024a99b4998f714b713244d6f768ef59f67c9b7251650d4f19d414eea231eab92099763d85cd92e41cb2bdc3f credential.toml
|
7f77ad8787629e3defbc89e39e5432482aa50d87ddd723de927a9c6c77b14b1673cbf5b3fc3c18dd7d0eba26fbcd4220d2da6939ed097d0294b24ccd5c002635 credential.toml
|
||||||
|
507b389f6373b5f4d8ca69f27bc806b39bda8edf7f58e4f32720958e7782ee171dd0461bdecb285e5a8bf2cf4ea3d6cbe8b62ae6ac43c2a40d0eb053d50a22f8 example-admin.toml
|
||||||
7105de7053654b8c0502521ce58585915fc831c3152801e1db02b1c5214dc3c3ed31f4fc18000665d8338c7a10ffbf0d248368bef2ef3a6d37d46cd856398366 example-credential.toml
|
7105de7053654b8c0502521ce58585915fc831c3152801e1db02b1c5214dc3c3ed31f4fc18000665d8338c7a10ffbf0d248368bef2ef3a6d37d46cd856398366 example-credential.toml
|
||||||
6213e9cff227d66a7a04237d15e2f77904f1bcdf5709fd985c1e12fe4aca0d0327db6997d567303eff47dabec3650db2a6d874b03adda41b239e04ee0c3557ee example-filer.toml
|
c6ec4fc7709c42dc6771b5039203c44cbd693742abcd7720936c00b1bd5f99bb2999bb1545680ae4418efedd65d71c234f4602f52ce9d58b1ff7ec53eafb1a1a example-filer.toml
|
||||||
e5753bd0bcc60dc84428c40ba556c08acae61dec083a5b76640125f637532e7c5759a72cdfd95114222a7a0901a916ec3c4d12f306853cfca0fe9a0b1857893e example-master.toml
|
59965fd2649a956677c6d4104ff07ff010d6edd1d3733eaa5c5bc01eabe54429c413e35d52ed4a4c0129bfa798e434828b32a5f0ef19dbbe4eab0199faa2738c example-master.toml
|
||||||
|
aea1b3114311304230cb30143825329ef7353a302d094c131ca4e049b847305e2143b76078e6574c6d7d4039c03a2e2d5a4925de80cd7cb2be75b2b522ce47f7 example-volume.toml
|
||||||
2c200c28172a5d0b1c80ab28e849287e7af8d103355638fd3183b8614d3e2b1b3482132522663f7c6d844e10e13b8c6e23fb5fba0dec2cc83de45c2f17b33477 example-notification.toml
|
2c200c28172a5d0b1c80ab28e849287e7af8d103355638fd3183b8614d3e2b1b3482132522663f7c6d844e10e13b8c6e23fb5fba0dec2cc83de45c2f17b33477 example-notification.toml
|
||||||
4b507540d57799e42ec0ee84073c6fa32c577a2f4a98bf66ee7302355080c63c65d70709115185debdee3c957e9294e79a8e461347d7148af7fdd368dc548af6 example-replication.toml
|
328cfe43d0c2ebf5092a1178af45c37b07593085135c31649754f0df9fd4c043847c13b56c3c7c45194541db8082309c4845c825d7011e4c3e503b1e6576528d example-replication.toml
|
||||||
a0f307bc73b1aa03653c42c22a1fc704640cbd86957a417f947fe33356e03734c33782777cb1d6cb17360fc6b3930ffbe1386f89123e9dc3c21468210418aae2 example-security.toml
|
b7caad9dff0bb812d4046b8e0285ac4e88a7af3a742a168579df08762da735a025725f78286e17bdd4b19a966a3d7ab88e0e52efbb5cf1c69d7a4ff071390e0f example-security.toml
|
||||||
70069f97edf261a2cd0669dd60adad80533609a25d7429254e0c3322d7e80337f5ff69a5581bc39e6a15442098d14d610ce5f0cb14f02c461c8d3dd440b22c56 example-shell.toml
|
70069f97edf261a2cd0669dd60adad80533609a25d7429254e0c3322d7e80337f5ff69a5581bc39e6a15442098d14d610ce5f0cb14f02c461c8d3dd440b22c56 example-shell.toml
|
||||||
be5771a5e1bf626c53f9dffbfa2a400d9b8f9626d55a7b61dcd853753561989427ba872a2638a5e6343f44dea6790678483bd29101d6495dbbfcd3029947b9a7 filer.toml
|
130b9932f99d0a3ec3c30c74eaf1dc441c1a9252da30e2c5365084f2a0679f58531e6180689c24b71f92cf9a7966b02ea25ee31d356e7118cbb82743d0bfcbd9 filer.toml
|
||||||
2cd6c73a5e23e0395b6f099dcc3acf9280cbb3e13f54408571e91741c4e6b0dad85f6d4e5a92f23ad541bad57ce295c28bb8450fe11da35acbd4da25848f61e5 master.toml
|
088c3aebc142054af1b54a92a2c5bd30d53be61bdf382f7cae2efef2d917d7b57022d9b494a60f32c7bf56689d4ce2f971e19c98da1d87e27021a3e948035605 master.toml
|
||||||
0a1b3d0fd1671744f96e7642fb9aee9b80debd0d9a82f586beb36fe32f9ad440332acd2a8b0ee0b210b912cb281d88ca56fd15e3a2ece61be9dcf96afc00a6f8 notification.toml
|
79a078133c259473e601488cd1d8032b74c5fa32da6f34a4ed46efa9736bf5369365a77d775e3d78512b1060cd87012eb40226829eecb30544e1542d165af7d6 security.toml
|
||||||
5a607ce6cdd11ffbe528b9a85e0012b48accefa6ccfeda9d6aa70d92ccf7f219e75c93cd2f1c36f3eb16204b3652a45dcd52ffcb64bceef91d081702b19cef3c replication.toml
|
|
||||||
d21981923b5964cf8365185a4f7c28a14e33ba6f60ad63e797e315544a6c22efdaa72814292824c07ef14554738769e0fd4c670fe797cf77b0226b2595a8b43b security.toml
|
|
||||||
7a91ce9da79b92e5ef42d4915f56a010bceaaa6c96dcef1f7b1821ee208d381aaa88b9cf495248276132e66d3215927f589b7fabc4eae2c2cb195645f904fac7 shell.toml
|
|
||||||
82e2793bf483ffb5b0c8fbe38e6c9df75afe01f824f8414cafd91e4bed5c79c13dae1ca659070401d4968d16ed4b26455b0c6208f777705527bceb2e5f286988 seaweedfs.admin.confd
|
82e2793bf483ffb5b0c8fbe38e6c9df75afe01f824f8414cafd91e4bed5c79c13dae1ca659070401d4968d16ed4b26455b0c6208f777705527bceb2e5f286988 seaweedfs.admin.confd
|
||||||
5ad952c37c62a770327bd70f7349fa677406606f0b9bf03fdc8f6c6804701f1e77710ab20d6153f9e0cfb549ec161d68a3316abab9c59837bbe3f91ee99e5ce0 seaweedfs.filer.confd
|
5ad952c37c62a770327bd70f7349fa677406606f0b9bf03fdc8f6c6804701f1e77710ab20d6153f9e0cfb549ec161d68a3316abab9c59837bbe3f91ee99e5ce0 seaweedfs.filer.confd
|
||||||
6c7ebdaf8f941868051a025fda36278bdf5e5438a2d478ca1cbe35064f933e7b07bf6d56bdd2268894f01c4e232e48f69099f793baeb2d6011063ac56a132fe4 seaweedfs.initd
|
19cbd65d701b0995e088f265d88f481f14e214ecbd8a783f7e7b17e811e421a28425f96d073757cc07fbb17e8eb084d14d41f46baee82ee13e043ce0c0c5bde9 seaweedfs.initd
|
||||||
|
816e763164c2cec66509c213ed56cb633f13d1daf48a511d1a9cfdf692a6ad945cf599cb0e706202b8fd522022ce512eae6170422e478abdf95334b0088ac4cc seaweedfs.logrotate
|
||||||
57ba77519bb266f0117eaadae3af5ae6bc99bb653668ff526202f327df1c8d93973c0e19dae0c53a19e06389868043c04e53f16f01c851b77fe1387e92cc993b seaweedfs.master.confd
|
57ba77519bb266f0117eaadae3af5ae6bc99bb653668ff526202f327df1c8d93973c0e19dae0c53a19e06389868043c04e53f16f01c851b77fe1387e92cc993b seaweedfs.master.confd
|
||||||
22a3ea6c83266a979ea7c848fc74b40fc0f2ade960b273fa11e63d4a72a1328bd688c9918be3e9234cfb19f889fd9c931388bb5c2863cea3500e534b8bd90282 seaweedfs.s3.confd
|
22a3ea6c83266a979ea7c848fc74b40fc0f2ade960b273fa11e63d4a72a1328bd688c9918be3e9234cfb19f889fd9c931388bb5c2863cea3500e534b8bd90282 seaweedfs.s3.confd
|
||||||
3e9c41bc61cdd9a4c53ece64d847eca26ab7d0ce0cc98e72462c3dbb225a40de10a02201362801015a9c629d77d5c0d54c7228e9d20111fb6f478b2267d2db98 seaweedfs.sftp.confd
|
3e9c41bc61cdd9a4c53ece64d847eca26ab7d0ce0cc98e72462c3dbb225a40de10a02201362801015a9c629d77d5c0d54c7228e9d20111fb6f478b2267d2db98 seaweedfs.sftp.confd
|
||||||
262cc5132a70a43f9f154d24da16fe2f34f736c0bfdafd56cd341b7f34b48b82aa3a38a93d64206360c391e1167e2b665a3ade5c7eddfe4b322253521629f4e0 seaweedfs.volume.confd
|
262cc5132a70a43f9f154d24da16fe2f34f736c0bfdafd56cd341b7f34b48b82aa3a38a93d64206360c391e1167e2b665a3ade5c7eddfe4b322253521629f4e0 seaweedfs.volume.confd
|
||||||
84a9caa8f5203a31f2f96ef812dca8e4f7597f8f06ed3f55db38daff167448b0332564a421dcb356405d761c7a9e815656208d431e84b8106951554ab7ef2142 seaweedfs.webdav.confd
|
84a9caa8f5203a31f2f96ef812dca8e4f7597f8f06ed3f55db38daff167448b0332564a421dcb356405d761c7a9e815656208d431e84b8106951554ab7ef2142 seaweedfs.webdav.confd
|
||||||
b586dfbdbcf17591366a7a62c4da6f2b13e1bd5dfb5b066beea114d01057eeb3d81172814655d812c48e02336277b3d70fa9f9550923cfe616e9dd8162661f51 seaweedfs.worker.confd
|
b586dfbdbcf17591366a7a62c4da6f2b13e1bd5dfb5b066beea114d01057eeb3d81172814655d812c48e02336277b3d70fa9f9550923cfe616e9dd8162661f51 seaweedfs.worker.confd
|
||||||
|
0a06a1ea007a6e4e0110a6208830f080685b81f6e1aae8453a75941ef54e4506155e4c7be125b2eed0b971050d0743118cf1454b6e9d01cf8eec02005125b6b2 seaweedfs.worker-lance.confd
|
||||||
2815330810545d17cffd993d93502c934c24af5aeff8f7096bcf0f020f895f1da50b74c356c028b67de552cbd8e4ccfa176636da2642feae99542035e4272171 weed.bash-completion
|
2815330810545d17cffd993d93502c934c24af5aeff8f7096bcf0f020f895f1da50b74c356c028b67de552cbd8e4ccfa176636da2642feae99542035e4272171 weed.bash-completion
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
## Package Commands
|
||||||
|
|
||||||
|
When updating SeaweedFS, generate the config scaffolds and refresh checksums:
|
||||||
|
|
||||||
|
```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
|
||||||
|
ALPINE_PACKAGE=seaweedfs mise run apk:build
|
||||||
|
```
|
||||||
|
|
||||||
|
Install-test local build:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ALPINE_PACKAGE=seaweedfs SKIP_BUILD=1 mise run apk:test-install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Install Node Roles
|
||||||
|
|
||||||
|
Single-node install:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add seaweedfs \
|
||||||
|
seaweedfs-master-openrc \
|
||||||
|
seaweedfs-volume-openrc \
|
||||||
|
seaweedfs-filer-openrc
|
||||||
|
```
|
||||||
|
|
||||||
|
Role-specific installs:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add seaweedfs seaweedfs-master-openrc
|
||||||
|
apk add seaweedfs seaweedfs-volume-openrc
|
||||||
|
apk add seaweedfs seaweedfs-filer-openrc
|
||||||
|
```
|
||||||
|
|
||||||
|
Available OpenRC role packages:
|
||||||
|
|
||||||
|
```text
|
||||||
|
seaweedfs-master-openrc -> /etc/init.d/seaweedfs.master
|
||||||
|
seaweedfs-volume-openrc -> /etc/init.d/seaweedfs.volume
|
||||||
|
seaweedfs-filer-openrc -> /etc/init.d/seaweedfs.filer
|
||||||
|
seaweedfs-s3-openrc -> /etc/init.d/seaweedfs.s3
|
||||||
|
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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk del seaweedfs-openrc
|
||||||
|
apk add seaweedfs seaweedfs-master-openrc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configure Services
|
||||||
|
|
||||||
|
Runtime paths:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/bin/weed
|
||||||
|
/etc/seaweedfs/*.toml
|
||||||
|
/etc/conf.d/seaweedfs.*
|
||||||
|
/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:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/share/doc/seaweedfs/examples/
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy and customize a scaffold file only when enabling its related feature.
|
||||||
|
|
||||||
|
Enable services:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rc-update add seaweedfs.master default
|
||||||
|
rc-service seaweedfs.master start
|
||||||
|
|
||||||
|
rc-update add seaweedfs.volume default
|
||||||
|
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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
weed version
|
||||||
|
rc-service seaweedfs.master status
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optional Packages
|
||||||
|
|
||||||
|
Docs and examples:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add seaweedfs-doc
|
||||||
|
```
|
||||||
|
|
||||||
|
Bash completion:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk upgrade seaweedfs
|
||||||
|
rc-service seaweedfs.master restart
|
||||||
|
```
|
||||||
|
|
||||||
|
Pin:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
apk add seaweedfs=4.47-r3
|
||||||
|
```
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# 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,19 +1,3 @@
|
|||||||
|
# Use the existing filer store for credentials by default.
|
||||||
[credential.filer_etc]
|
[credential.filer_etc]
|
||||||
enabled = true
|
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
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# 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"
|
username = "root"
|
||||||
password = ""
|
password = ""
|
||||||
database = "" # create or use an existing database
|
database = "" # create or use an existing database
|
||||||
connection_max_idle = 10
|
connection_max_idle = 50
|
||||||
connection_max_open = 50
|
connection_max_open = 50
|
||||||
connection_max_lifetime_seconds = 300
|
connection_max_lifetime_seconds = 300
|
||||||
interpolateParams = false
|
interpolateParams = false
|
||||||
@@ -97,7 +97,7 @@ port = 3306
|
|||||||
username = "root"
|
username = "root"
|
||||||
password = ""
|
password = ""
|
||||||
database = "" # create or use an existing database
|
database = "" # create or use an existing database
|
||||||
connection_max_idle = 10
|
connection_max_idle = 50
|
||||||
connection_max_open = 50
|
connection_max_open = 50
|
||||||
connection_max_lifetime_seconds = 300
|
connection_max_lifetime_seconds = 300
|
||||||
interpolateParams = false
|
interpolateParams = false
|
||||||
@@ -106,13 +106,9 @@ enableUpsert = true
|
|||||||
upsertQuery = """INSERT INTO `%s` (`dirhash`,`name`,`directory`,`meta`) VALUES (?,?,?,?) AS `new` ON DUPLICATE KEY UPDATE `meta` = `new`.`meta`"""
|
upsertQuery = """INSERT INTO `%s` (`dirhash`,`name`,`directory`,`meta`) VALUES (?,?,?,?) AS `new` ON DUPLICATE KEY UPDATE `meta` = `new`.`meta`"""
|
||||||
|
|
||||||
[postgres] # or cockroachdb, YugabyteDB
|
[postgres] # or cockroachdb, YugabyteDB
|
||||||
# CREATE TABLE IF NOT EXISTS filemeta (
|
# createTable = true # auto-create filemeta with the default schema
|
||||||
# dirhash BIGINT,
|
# createTable = false # skip table creation (default; for restricted DB roles)
|
||||||
# name VARCHAR(65535),
|
# createTable = """CREATE TABLE IF NOT EXISTS "%s" (...)""" # custom template
|
||||||
# directory VARCHAR(65535),
|
|
||||||
# meta bytea,
|
|
||||||
# PRIMARY KEY (dirhash, name)
|
|
||||||
# );
|
|
||||||
enabled = false
|
enabled = false
|
||||||
hostname = "localhost"
|
hostname = "localhost"
|
||||||
port = 5432
|
port = 5432
|
||||||
@@ -127,7 +123,7 @@ sslmode = "disable"
|
|||||||
# sslkey = "/path/to/client.key" # client private key file
|
# sslkey = "/path/to/client.key" # client private key file
|
||||||
# sslrootcert = "/path/to/ca.crt" # CA certificate file
|
# sslrootcert = "/path/to/ca.crt" # CA certificate file
|
||||||
# sslcrl = "/path/to/client.crl" # Certificate Revocation List (CRL) (optional)
|
# sslcrl = "/path/to/client.crl" # Certificate Revocation List (CRL) (optional)
|
||||||
connection_max_idle = 10
|
connection_max_idle = 50
|
||||||
connection_max_open = 50
|
connection_max_open = 50
|
||||||
connection_max_lifetime_seconds = 300
|
connection_max_lifetime_seconds = 300
|
||||||
# Set to true when using PgBouncer connection pooler
|
# Set to true when using PgBouncer connection pooler
|
||||||
@@ -166,7 +162,7 @@ sslmode = "disable"
|
|||||||
# sslkey = "/path/to/client.key" # client private key file
|
# sslkey = "/path/to/client.key" # client private key file
|
||||||
# sslrootcert = "/path/to/ca.crt" # CA certificate file
|
# sslrootcert = "/path/to/ca.crt" # CA certificate file
|
||||||
# sslcrl = "/path/to/client.crl" # Certificate Revocation List (CRL) (optional)
|
# sslcrl = "/path/to/client.crl" # Certificate Revocation List (CRL) (optional)
|
||||||
connection_max_idle = 10
|
connection_max_idle = 50
|
||||||
connection_max_open = 50
|
connection_max_open = 50
|
||||||
connection_max_lifetime_seconds = 300
|
connection_max_lifetime_seconds = 300
|
||||||
# Set to true when using PgBouncer connection pooler
|
# Set to true when using PgBouncer connection pooler
|
||||||
@@ -230,6 +226,23 @@ client_cert_path = ""
|
|||||||
client_key_path = ""
|
client_key_path = ""
|
||||||
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
||||||
superLargeDirectories = []
|
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]
|
[redis2_sentinel]
|
||||||
enabled = false
|
enabled = false
|
||||||
@@ -237,6 +250,9 @@ addresses = ["172.22.12.7:26379","172.22.12.8:26379","172.22.12.9:26379"]
|
|||||||
masterName = "master"
|
masterName = "master"
|
||||||
username = ""
|
username = ""
|
||||||
password = ""
|
password = ""
|
||||||
|
# credentials used to authenticate against the sentinel nodes themselves (if they require auth)
|
||||||
|
sentinel_username = ""
|
||||||
|
sentinel_password = ""
|
||||||
database = 0
|
database = 0
|
||||||
# prefix for filer redis keys
|
# prefix for filer redis keys
|
||||||
keyPrefix = ""
|
keyPrefix = ""
|
||||||
@@ -244,6 +260,7 @@ enable_tls = false
|
|||||||
ca_cert_path = ""
|
ca_cert_path = ""
|
||||||
client_cert_path = ""
|
client_cert_path = ""
|
||||||
client_key_path = ""
|
client_key_path = ""
|
||||||
|
# see [redis2] for the connection tuning keys
|
||||||
|
|
||||||
[redis_cluster2]
|
[redis_cluster2]
|
||||||
enabled = false
|
enabled = false
|
||||||
@@ -264,7 +281,7 @@ ca_cert_path = ""
|
|||||||
client_cert_path = ""
|
client_cert_path = ""
|
||||||
client_key_path = ""
|
client_key_path = ""
|
||||||
# allows reads from slave servers or the master, but all writes still go to the master
|
# allows reads from slave servers or the master, but all writes still go to the master
|
||||||
readOnly = false
|
useReadOnly = false
|
||||||
# automatically use the closest Redis server for reads
|
# automatically use the closest Redis server for reads
|
||||||
routeByLatency = false
|
routeByLatency = false
|
||||||
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
# This changes the data layout. Only add new directories. Removing/Updating will cause data loss.
|
||||||
@@ -366,6 +383,21 @@ healthcheck_enabled = false
|
|||||||
# increase the value is recommend, be sure the value in Elastic is greater or equal here
|
# increase the value is recommend, be sure the value in Elastic is greater or equal here
|
||||||
index.max_result_window = 10000
|
index.max_result_window = 10000
|
||||||
|
|
||||||
|
# for Elasticsearch 8.x clusters
|
||||||
|
[elastic8]
|
||||||
|
enabled = false
|
||||||
|
servers = [
|
||||||
|
"http://localhost1:9200",
|
||||||
|
"http://localhost2:9200",
|
||||||
|
"http://localhost3:9200",
|
||||||
|
]
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
sniff_enabled = false
|
||||||
|
healthcheck_enabled = false
|
||||||
|
# increase the value is recommend, be sure the value in Elastic is greater or equal here
|
||||||
|
index.max_result_window = 10000
|
||||||
|
|
||||||
|
|
||||||
[arangodb] # in development dont use it
|
[arangodb] # in development dont use it
|
||||||
enabled = false
|
enabled = false
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ copy_2 = 6 # create 2 x 6 = 12 actual volumes
|
|||||||
copy_3 = 3 # create 3 x 3 = 9 actual volumes
|
copy_3 = 3 # create 3 x 3 = 9 actual volumes
|
||||||
copy_other = 1 # create n x 1 = n actual volumes
|
copy_other = 1 # create n x 1 = n actual volumes
|
||||||
threshold = 0.9 # create threshold
|
threshold = 0.9 # create threshold
|
||||||
|
reservation_timeout = "5m"# capacity reservation timeout before unreleased reservations expire
|
||||||
disable = false # disables volume growth if true
|
disable = false # disables volume growth if true
|
||||||
|
|
||||||
# configuration flags for replication
|
# configuration flags for replication
|
||||||
|
|||||||
@@ -59,7 +59,17 @@ is_incremental = false
|
|||||||
# experimental, let me know if it works
|
# experimental, let me know if it works
|
||||||
enabled = false
|
enabled = false
|
||||||
account_name = ""
|
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 = ""
|
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
|
container = "mycontainer" # an existing container
|
||||||
directory = "/" # destination directory
|
directory = "/" # destination directory
|
||||||
is_incremental = false
|
is_incremental = false
|
||||||
|
|||||||
@@ -4,7 +4,16 @@
|
|||||||
# /etc/seaweedfs/security.toml
|
# /etc/seaweedfs/security.toml
|
||||||
# this file is read by master, volume server, filer, and worker
|
# this file is read by master, volume server, filer, and worker
|
||||||
|
|
||||||
# comma separated origins allowed to make requests to the filer and s3 gateway.
|
# Any value below can also be supplied as an environment variable instead of
|
||||||
|
# living in this file: prefix the key with WEED_, upper-case it, and replace
|
||||||
|
# "." with "_". This is the recommended way to inject the secrets in here from
|
||||||
|
# a Kubernetes Secret (env valueFrom.secretKeyRef) rather than a ConfigMap.
|
||||||
|
# The JWT signing keys map to:
|
||||||
|
# WEED_JWT_SIGNING_KEY, WEED_JWT_SIGNING_READ_KEY (master <-> volume)
|
||||||
|
# WEED_JWT_FILER_SIGNING_KEY, WEED_JWT_FILER_SIGNING_READ_KEY (s3/clients <-> filer)
|
||||||
|
# A set env var wins over the file, so the file can stay empty (or absent).
|
||||||
|
|
||||||
|
# comma separated origins allowed to make requests to the filer and s3 gateway.
|
||||||
# enter in this format: https://domain.com, or http://localhost:port
|
# enter in this format: https://domain.com, or http://localhost:port
|
||||||
[cors.allowed_origins]
|
[cors.allowed_origins]
|
||||||
values = "*"
|
values = "*"
|
||||||
@@ -68,6 +77,12 @@ expires_after_seconds = 10 # seconds
|
|||||||
# All gRPC TLS authentications are mutual (mTLS)
|
# All gRPC TLS authentications are mutual (mTLS)
|
||||||
# The values for ca, cert, and key are paths to the certificate/key files
|
# 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
|
# 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]
|
[grpc]
|
||||||
ca = ""
|
ca = ""
|
||||||
# Set wildcard domain for enable TLS authentication by common names
|
# Set wildcard domain for enable TLS authentication by common names
|
||||||
@@ -78,6 +93,8 @@ allowed_wildcard_domain = "" # .mycompany.com
|
|||||||
[grpc.volume]
|
[grpc.volume]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
# Master server gRPC options (server-side)
|
# Master server gRPC options (server-side)
|
||||||
@@ -85,6 +102,8 @@ allowed_commonNames = "" # comma-separated SSL certificate common names
|
|||||||
[grpc.master]
|
[grpc.master]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
# Filer server gRPC options (server-side)
|
# Filer server gRPC options (server-side)
|
||||||
@@ -92,6 +111,8 @@ allowed_commonNames = "" # comma-separated SSL certificate common names
|
|||||||
[grpc.filer]
|
[grpc.filer]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
# S3 server gRPC options (server-side)
|
# S3 server gRPC options (server-side)
|
||||||
@@ -99,31 +120,43 @@ allowed_commonNames = "" # comma-separated SSL certificate common names
|
|||||||
[grpc.s3]
|
[grpc.s3]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
[grpc.msg_broker]
|
[grpc.msg_broker]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
[grpc.msg_agent]
|
[grpc.msg_agent]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
[grpc.admin]
|
[grpc.admin]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
[grpc.worker]
|
[grpc.worker]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
[grpc.mq]
|
[grpc.mq]
|
||||||
cert = ""
|
cert = ""
|
||||||
key = ""
|
key = ""
|
||||||
|
client_cert = ""
|
||||||
|
client_key = ""
|
||||||
allowed_commonNames = "" # comma-separated SSL certificate common names
|
allowed_commonNames = "" # comma-separated SSL certificate common names
|
||||||
|
|
||||||
# gRPC client configuration for outgoing gRPC connections
|
# gRPC client configuration for outgoing gRPC connections
|
||||||
@@ -199,6 +232,15 @@ kek = ""
|
|||||||
# Cannot be used while /etc/s3/sse_kek exists on the filer — delete it first.
|
# Cannot be used while /etc/s3/sse_kek exists on the filer — delete it first.
|
||||||
key = ""
|
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.
|
# white list. It's checking request ip address.
|
||||||
[guard]
|
[guard]
|
||||||
white_list = ""
|
white_list = ""
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# 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"
|
||||||
|
|
||||||
@@ -1,46 +1,4 @@
|
|||||||
[filer.options]
|
# Store standalone filer metadata in the package-managed data directory.
|
||||||
recursive_delete = false
|
|
||||||
|
|
||||||
[leveldb2]
|
[leveldb2]
|
||||||
enabled = true
|
enabled = true
|
||||||
dir = "/var/lib/seaweedfs/filer/meta"
|
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
|
|
||||||
|
|||||||
@@ -1,27 +1,3 @@
|
|||||||
|
# Disable scheduled maintenance until it is explicitly configured.
|
||||||
[master.maintenance]
|
[master.maintenance]
|
||||||
scripts = ""
|
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
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
[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
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
[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
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
apk add seaweedfs \
|
||||||
|
seaweedfs-doc \
|
||||||
|
bash-completion \
|
||||||
|
seaweedfs-master-openrc \
|
||||||
|
seaweedfs-volume-openrc \
|
||||||
|
seaweedfs-filer-openrc \
|
||||||
|
seaweedfs-worker-lance-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
|
||||||
|
|
||||||
|
rc-update add seaweedfs.master default || true
|
||||||
|
rc-update add seaweedfs.volume default || true
|
||||||
|
rc-update add seaweedfs.filer default || true
|
||||||
|
|
||||||
|
rc-service seaweedfs.master start
|
||||||
|
rc-service seaweedfs.volume start
|
||||||
|
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
|
||||||
@@ -2,38 +2,10 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
|
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
|
||||||
package_name="${PACKAGE_NAME:-seaweedfs}"
|
# shellcheck source=scripts/apk/test-install-lib.sh
|
||||||
alpine_version="${ALPINE_VERSION:-3.23}"
|
. "${repo_root}/scripts/apk/test-install-lib.sh"
|
||||||
arch="${ALPINE_ARCH:-x86_64}"
|
|
||||||
|
|
||||||
case "${arch}" in
|
apk_test_install_run "${repo_root}" "${PACKAGE_NAME:-seaweedfs}" "${PACKAGE_VERSION:-}" <<'SCRIPT'
|
||||||
x86_64)
|
|
||||||
platform="${ALPINE_TEST_PLATFORM:-linux/amd64}"
|
|
||||||
;;
|
|
||||||
aarch64)
|
|
||||||
platform="${ALPINE_TEST_PLATFORM:-linux/arm64}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2
|
|
||||||
exit 2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ "${SKIP_BUILD:-0}" != "1" ]]; then
|
|
||||||
ALPINE_PACKAGE="${package_name}" "${repo_root}/scripts/apk/build.sh" build "${arch}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d "${repo_root}/packages/local/${arch}" ]]; then
|
|
||||||
printf 'missing local repository: packages/local/%s\n' "${arch}" >&2
|
|
||||||
printf 'run: ALPINE_PACKAGE=%s mise run apk:build\n' "${package_name}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker run --rm --platform "${platform}" \
|
|
||||||
-e "ALPINE_ARCH=${arch}" \
|
|
||||||
-v "${repo_root}/packages/local:/repo:ro" \
|
|
||||||
"alpine:${alpine_version}" \
|
|
||||||
sh -lc '
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
cp "/repo/${ALPINE_ARCH}"/*.rsa.pub /etc/apk/keys/
|
cp "/repo/${ALPINE_ARCH}"/*.rsa.pub /etc/apk/keys/
|
||||||
@@ -43,18 +15,27 @@ docker run --rm --platform "${platform}" \
|
|||||||
apk add seaweedfs \
|
apk add seaweedfs \
|
||||||
seaweedfs-master-openrc \
|
seaweedfs-master-openrc \
|
||||||
seaweedfs-volume-openrc \
|
seaweedfs-volume-openrc \
|
||||||
seaweedfs-filer-openrc
|
seaweedfs-filer-openrc \
|
||||||
|
seaweedfs-logrotate \
|
||||||
|
seaweedfs-worker-lance-openrc
|
||||||
|
|
||||||
test -x /usr/bin/weed
|
test -x /usr/bin/weed
|
||||||
test -d /etc/seaweedfs
|
test -d /etc/seaweedfs
|
||||||
test -f /etc/seaweedfs/master.toml
|
test -f /etc/seaweedfs/master.toml
|
||||||
test -f /etc/seaweedfs/filer.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.master
|
||||||
test -f /etc/conf.d/seaweedfs.volume
|
test -f /etc/conf.d/seaweedfs.volume
|
||||||
test -f /etc/conf.d/seaweedfs.filer
|
test -f /etc/conf.d/seaweedfs.filer
|
||||||
test -f /etc/init.d/seaweedfs.master
|
test -f /etc/init.d/seaweedfs.master
|
||||||
test -f /etc/init.d/seaweedfs.volume
|
test -f /etc/init.d/seaweedfs.volume
|
||||||
test -f /etc/init.d/seaweedfs.filer
|
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
|
weed version
|
||||||
|
|
||||||
@@ -69,5 +50,6 @@ docker run --rm --platform "${platform}" \
|
|||||||
apk info -e seaweedfs-bash-completion
|
apk info -e seaweedfs-bash-completion
|
||||||
test -d /usr/share/doc/seaweedfs/examples
|
test -d /usr/share/doc/seaweedfs/examples
|
||||||
test -f /usr/share/doc/seaweedfs/examples/master.toml
|
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
|
test -f /usr/share/bash-completion/completions/weed
|
||||||
'
|
SCRIPT
|
||||||
|
|||||||
@@ -1,15 +1,38 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../.." && pwd)}"
|
|
||||||
package_dir="${PACKAGE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
package_dir="${PACKAGE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
||||||
configs=(credential filer master notification replication security shell)
|
configs=(admin credential filer master volume 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
|
||||||
|
)
|
||||||
|
|
||||||
for config in "${configs[@]}"; do
|
for config in "${configs[@]}"; do
|
||||||
"${repo_root}/bin/weed" scaffold -config "${config}" 2>/dev/null \
|
"${tmpdir}/weed" scaffold -config "${config}" 2>/dev/null \
|
||||||
> "${package_dir}/example-${config}.toml"
|
> "${package_dir}/example-${config}.toml"
|
||||||
done
|
done
|
||||||
|
|
||||||
"${repo_root}/bin/weed" autocomplete bash 2>/dev/null \
|
"${tmpdir}/weed" autocomplete bash 2>/dev/null \
|
||||||
| sed -E 's#complete -C "?[^"]*/weed"? weed#complete -C /usr/bin/weed weed#' \
|
| sed -E 's#complete -C "?[^"]*/weed"? weed#complete -C /usr/bin/weed weed#' \
|
||||||
> "${package_dir}/weed.bash-completion"
|
> "${package_dir}/weed.bash-completion"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -6,6 +6,9 @@ description="SeaweedFS ${service_name} service"
|
|||||||
command="/usr/bin/weed"
|
command="/usr/bin/weed"
|
||||||
command_user="${SEAWEEDFS_USER:-seaweedfs}:${SEAWEEDFS_GROUP:-seaweedfs}"
|
command_user="${SEAWEEDFS_USER:-seaweedfs}:${SEAWEEDFS_GROUP:-seaweedfs}"
|
||||||
command_background="yes"
|
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"
|
pidfile="/run/seaweedfs/${RC_SVCNAME}.pid"
|
||||||
output_log="${SEAWEEDFS_LOG:-/var/log/seaweedfs/${RC_SVCNAME}.log}"
|
output_log="${SEAWEEDFS_LOG:-/var/log/seaweedfs/${RC_SVCNAME}.log}"
|
||||||
error_log="${SEAWEEDFS_ERRLOG:-/var/log/seaweedfs/${RC_SVCNAME}.log}"
|
error_log="${SEAWEEDFS_ERRLOG:-/var/log/seaweedfs/${RC_SVCNAME}.log}"
|
||||||
@@ -46,6 +49,10 @@ build_command_args() {
|
|||||||
data_dir="${SEAWEEDFS_DATA_DIR:-/var/lib/seaweedfs/worker}"
|
data_dir="${SEAWEEDFS_DATA_DIR:-/var/lib/seaweedfs/worker}"
|
||||||
command_args="$command_args -admin=${SEAWEEDFS_ADMIN:-localhost:23646} -workingDir=${data_dir}"
|
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
|
esac
|
||||||
|
|
||||||
command_args="$command_args ${SEAWEEDFS_OPTS:-}"
|
command_args="$command_args ${SEAWEEDFS_OPTS:-}"
|
||||||
@@ -62,7 +69,7 @@ depend() {
|
|||||||
s3|webdav|sftp)
|
s3|webdav|sftp)
|
||||||
after seaweedfs.filer
|
after seaweedfs.filer
|
||||||
;;
|
;;
|
||||||
worker)
|
worker|worker-lance)
|
||||||
after seaweedfs.admin
|
after seaweedfs.admin
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/var/log/seaweedfs/seaweedfs.*.log {
|
||||||
|
daily
|
||||||
|
rotate 14
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
copytruncate
|
||||||
|
su seaweedfs seaweedfs
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Lance maintenance worker. It is optional and requires a Lance namespace.
|
||||||
|
SEAWEEDFS_ADMIN="localhost:23646"
|
||||||
|
SEAWEEDFS_LANCE_NAMESPACE="http://localhost:9101"
|
||||||
|
SEAWEEDFS_OPTS=""
|
||||||
@@ -1,104 +1,3 @@
|
|||||||
[cors.allowed_origins]
|
# Do not expose the administrative UI by default.
|
||||||
values = "*"
|
|
||||||
|
|
||||||
[jwt.signing]
|
|
||||||
key = ""
|
|
||||||
expires_after_seconds = 10
|
|
||||||
|
|
||||||
[access]
|
[access]
|
||||||
ui = false
|
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 = ""
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
[cluster]
|
|
||||||
default = "c1"
|
|
||||||
|
|
||||||
[cluster.c1]
|
|
||||||
master = "localhost:9333" # comma-separated master servers
|
|
||||||
|
|
||||||
[cluster.c2]
|
|
||||||
master = ""
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
provider=github
|
||||||
|
repo=seaweedfs/seaweedfs
|
||||||
|
version_prefix=none
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
ARG ALPINE_VERSION=3.23
|
ARG ALPINE_VERSION=3.24
|
||||||
FROM alpine:${ALPINE_VERSION}
|
FROM alpine:${ALPINE_VERSION}
|
||||||
|
|
||||||
ARG BUILDER_UID=1000
|
ARG BUILDER_UID=1000
|
||||||
ARG BUILDER_GID=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 \
|
RUN apk add --no-cache \
|
||||||
abuild-rootbld \
|
abuild-rootbld \
|
||||||
alpine-sdk \
|
alpine-sdk \
|
||||||
|
|||||||
+26
-13
@@ -6,7 +6,7 @@ requested_arch="${2:-${ALPINE_ARCH:-x86_64}}"
|
|||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
. "${repo_root}/scripts/apk/package-lib.sh"
|
. "${repo_root}/scripts/apk/package-lib.sh"
|
||||||
|
|
||||||
alpine_version="${ALPINE_VERSION:-3.23}"
|
alpine_version="${ALPINE_VERSION:-3.24}"
|
||||||
repo_name="${ALPINE_REPO_NAME:-local}"
|
repo_name="${ALPINE_REPO_NAME:-local}"
|
||||||
build_platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
|
build_platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
|
||||||
builder_uid="$(id -u)"
|
builder_uid="$(id -u)"
|
||||||
@@ -19,6 +19,8 @@ if [[ "${builder_gid}" == "0" ]]; then
|
|||||||
builder_gid=1000
|
builder_gid=1000
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
image_name="${ALPINE_APK_BUILDER_IMAGE:-alpine-apk-builder:${alpine_version}-${builder_uid}-${builder_gid}}"
|
||||||
|
|
||||||
cache_scope_from_remote() {
|
cache_scope_from_remote() {
|
||||||
local remote
|
local remote
|
||||||
local path
|
local path
|
||||||
@@ -63,7 +65,6 @@ run_for_arch() {
|
|||||||
local arch="$1"
|
local arch="$1"
|
||||||
local subcommand="$2"
|
local subcommand="$2"
|
||||||
local package_dir="$3"
|
local package_dir="$3"
|
||||||
local image_name
|
|
||||||
local container_package_dir
|
local container_package_dir
|
||||||
local package_name
|
local package_name
|
||||||
local cache_scope
|
local cache_scope
|
||||||
@@ -73,19 +74,9 @@ run_for_arch() {
|
|||||||
apk_validate_package_dir "${package_dir}"
|
apk_validate_package_dir "${package_dir}"
|
||||||
package_name="$(apk_package_name "${package_dir}")"
|
package_name="$(apk_package_name "${package_dir}")"
|
||||||
container_package_dir="$(apk_container_package_dir "${repo_root}" "${package_dir}")"
|
container_package_dir="$(apk_container_package_dir "${repo_root}" "${package_dir}")"
|
||||||
image_name="${ALPINE_APK_BUILDER_IMAGE:-alpine-apk-builder:${arch}}"
|
|
||||||
cache_scope="${ALPINE_APK_CACHE_SCOPE:-$(cache_scope_from_remote)}"
|
cache_scope="${ALPINE_APK_CACHE_SCOPE:-$(cache_scope_from_remote)}"
|
||||||
cache_prefix="${ALPINE_APK_CACHE_PREFIX:-alpine-apk}-${cache_scope}-${package_name}-${arch}"
|
cache_prefix="${ALPINE_APK_CACHE_PREFIX:-alpine-apk}-${cache_scope}-${package_name}-${arch}"
|
||||||
|
|
||||||
docker build \
|
|
||||||
--platform "${build_platform}" \
|
|
||||||
--build-arg "ALPINE_VERSION=${alpine_version}" \
|
|
||||||
--build-arg "BUILDER_UID=${builder_uid}" \
|
|
||||||
--build-arg "BUILDER_GID=${builder_gid}" \
|
|
||||||
-f "${repo_root}/scripts/apk/Dockerfile" \
|
|
||||||
-t "${image_name}" \
|
|
||||||
"${repo_root}"
|
|
||||||
|
|
||||||
docker_args=(--rm --platform "${build_platform}")
|
docker_args=(--rm --platform "${build_platform}")
|
||||||
if [[ -t 0 && -t 1 ]]; then
|
if [[ -t 0 && -t 1 ]]; then
|
||||||
docker_args+=(-it)
|
docker_args+=(-it)
|
||||||
@@ -98,7 +89,7 @@ run_for_arch() {
|
|||||||
-e "APKBUILD_DIR=${container_package_dir}" \
|
-e "APKBUILD_DIR=${container_package_dir}" \
|
||||||
-e "CARGO_HOME=/home/builder/.cache/cargo" \
|
-e "CARGO_HOME=/home/builder/.cache/cargo" \
|
||||||
-e "CARGO_TARGET_DIR=/home/builder/.cache/cargo-target" \
|
-e "CARGO_TARGET_DIR=/home/builder/.cache/cargo-target" \
|
||||||
-e "PACKAGER=${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}" \
|
-e "PACKAGER=${PACKAGER:-local}" \
|
||||||
-e "RUSTUP_HOME=/home/builder/.cache/rustup" \
|
-e "RUSTUP_HOME=/home/builder/.cache/rustup" \
|
||||||
-v "${cache_prefix}-cargo:/home/builder/.cache/cargo" \
|
-v "${cache_prefix}-cargo:/home/builder/.cache/cargo" \
|
||||||
-v "${cache_prefix}-cargo-target:/home/builder/.cache/cargo-target" \
|
-v "${cache_prefix}-cargo-target:/home/builder/.cache/cargo-target" \
|
||||||
@@ -111,11 +102,33 @@ run_for_arch() {
|
|||||||
"${subcommand}"
|
"${subcommand}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_builder_image() {
|
||||||
|
docker build \
|
||||||
|
--platform "${build_platform}" \
|
||||||
|
--build-arg "ALPINE_VERSION=${alpine_version}" \
|
||||||
|
--build-arg "BUILDER_UID=${builder_uid}" \
|
||||||
|
--build-arg "BUILDER_GID=${builder_gid}" \
|
||||||
|
-f "${repo_root}/scripts/apk/Dockerfile" \
|
||||||
|
-t "${image_name}" \
|
||||||
|
"${repo_root}"
|
||||||
|
}
|
||||||
|
|
||||||
mkdir -p \
|
mkdir -p \
|
||||||
"${repo_root}/.cache/abuild" \
|
"${repo_root}/.cache/abuild" \
|
||||||
"${repo_root}/.cache/apk-distfiles" \
|
"${repo_root}/.cache/apk-distfiles" \
|
||||||
"${repo_root}/packages"
|
"${repo_root}/packages"
|
||||||
|
|
||||||
|
case "${command_name}" in
|
||||||
|
build-all|build|checksum|lint|shell) ;;
|
||||||
|
*)
|
||||||
|
printf 'unknown command: %s\n' "${command_name}" >&2
|
||||||
|
printf 'usage: %s [build|build-all|checksum|lint|shell] [x86_64|aarch64]\n' "$0" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
build_builder_image
|
||||||
|
|
||||||
case "${command_name}" in
|
case "${command_name}" in
|
||||||
build-all)
|
build-all)
|
||||||
while IFS= read -r package_dir; do
|
while IFS= read -r package_dir; do
|
||||||
|
|||||||
+43
-6
@@ -2,12 +2,20 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
# shellcheck source=scripts/apk/package-lib.sh
|
||||||
. "${repo_root}/scripts/apk/package-lib.sh"
|
. "${repo_root}/scripts/apk/package-lib.sh"
|
||||||
|
|
||||||
repo_name="${ALPINE_REPO_NAME:-local}"
|
repo_name="${ALPINE_REPO_NAME:-local}"
|
||||||
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
|
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
|
||||||
packager="${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}"
|
packager="${PACKAGER:-local}"
|
||||||
selected_packages="${ALPINE_PACKAGE:-${ALPINE_PACKAGES:-}}"
|
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'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "${1:-}" != "--as-builder" && "$(id -u)" == "0" ]]; then
|
if [[ "${1:-}" != "--as-builder" && "$(id -u)" == "0" ]]; then
|
||||||
addgroup -g 1000 builder 2>/dev/null || addgroup builder
|
addgroup -g 1000 builder 2>/dev/null || addgroup builder
|
||||||
@@ -17,13 +25,22 @@ if [[ "${1:-}" != "--as-builder" && "$(id -u)" == "0" ]]; then
|
|||||||
printf 'permit nopass :wheel\n' > /etc/doas.d/wheel.conf
|
printf 'permit nopass :wheel\n' > /etc/doas.d/wheel.conf
|
||||||
printf '%%wheel ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/wheel
|
printf '%%wheel ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/wheel
|
||||||
chown -R builder:builder "${repo_root}"
|
chown -R builder:builder "${repo_root}"
|
||||||
exec su builder -c "ALPINE_ARCHES='${arches}' ALPINE_REPO_NAME='${repo_name}' ALPINE_PACKAGES='${selected_packages}' PACKAGER='${packager}' '${BASH_SOURCE[0]}' --as-builder"
|
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"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export PACKAGER="${packager}"
|
export PACKAGER="${packager}"
|
||||||
export REPODEST="${repo_root}/packages"
|
export REPODEST="${repo_root}/packages"
|
||||||
export SRCDEST="${repo_root}/.cache/apk-distfiles"
|
export SRCDEST="${repo_root}/.cache/apk-distfiles"
|
||||||
|
|
||||||
|
install_repo_keys() {
|
||||||
|
local key
|
||||||
|
shopt -s nullglob
|
||||||
|
for key in "${REPODEST}/${repo_name}"/*/*.rsa.pub; do
|
||||||
|
doas cp "${key}" /etc/apk/keys/
|
||||||
|
done
|
||||||
|
shopt -u nullglob
|
||||||
|
}
|
||||||
|
|
||||||
git config --global --add safe.directory "${repo_root}"
|
git config --global --add safe.directory "${repo_root}"
|
||||||
mkdir -p "${repo_root}/.cache/abuild" "${SRCDEST}" "${REPODEST}" "${HOME}/.abuild"
|
mkdir -p "${repo_root}/.cache/abuild" "${SRCDEST}" "${REPODEST}" "${HOME}/.abuild"
|
||||||
|
|
||||||
@@ -33,10 +50,17 @@ if [[ ! -e "${HOME}/.abuild/abuild.conf" && -d "${repo_root}/.cache/abuild" ]];
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if ! compgen -G "${HOME}/.abuild/*.rsa" > /dev/null; then
|
if ! compgen -G "${HOME}/.abuild/*.rsa" > /dev/null; then
|
||||||
abuild-keygen -a -n
|
# 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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
doas cp "${HOME}"/.abuild/*.rsa.pub /etc/apk/keys/
|
doas cp "${HOME}"/.abuild/*.rsa.pub /etc/apk/keys/
|
||||||
|
install_repo_keys
|
||||||
doas apk update
|
doas apk update
|
||||||
|
|
||||||
while IFS= read -r package_dir; do
|
while IFS= read -r package_dir; do
|
||||||
@@ -55,10 +79,23 @@ while IFS= read -r package_dir; do
|
|||||||
|
|
||||||
printf 'Building %s for %s\n' "$(basename "${package_dir}")" "${arch}"
|
printf 'Building %s for %s\n' "$(basename "${package_dir}")" "${arch}"
|
||||||
(
|
(
|
||||||
export ALPINE_ARCH="${arch}"
|
package_name="$(apk_package_name "${package_dir}")"
|
||||||
export CARCH="${arch}"
|
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}"
|
cd "${package_dir}"
|
||||||
abuild -r
|
ALPINE_ARCH="${arch}" CARCH="${arch}" abuild -r
|
||||||
)
|
)
|
||||||
|
|
||||||
mkdir -p "${REPODEST}/${repo_name}/${arch}"
|
mkdir -p "${REPODEST}/${repo_name}/${arch}"
|
||||||
|
|||||||
Executable
+173
@@ -0,0 +1,173 @@
|
|||||||
|
#!/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"
|
||||||
|
|
||||||
|
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:-}"
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
registry_url() {
|
||||||
|
printf '%s/api/packages/%s/alpine/%s/%s\n' \
|
||||||
|
"${instance_url%/}" "${owner}" "${branch}" "${repository}"
|
||||||
|
}
|
||||||
|
|
||||||
|
registry_key_url() {
|
||||||
|
printf '%s/api/packages/%s/alpine/key\n' "${instance_url%/}" "${owner}"
|
||||||
|
}
|
||||||
|
|
||||||
|
download_registry_metadata() {
|
||||||
|
local arch url key_dir http_status
|
||||||
|
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
load_registry_index() {
|
||||||
|
local arch package_name package_version registry_key comparison
|
||||||
|
declare -gA registry_latest_versions=()
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
registry_upgrade_packages() {
|
||||||
|
local package_dir package_name arch candidate_spec candidate_version published_version comparison selected
|
||||||
|
|
||||||
|
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}"
|
||||||
|
done < <(apk_all_package_dirs "${repo_root}")
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare() {
|
||||||
|
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)
|
||||||
|
|
||||||
|
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}"
|
||||||
|
else
|
||||||
|
ALPINE_SKIP_BUILD=1
|
||||||
|
printf 'No packages selected for rebuild: registry has equal or newer package versions\n'
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${command_name}" in
|
||||||
|
prepare) prepare ;;
|
||||||
|
*) printf 'usage: %s prepare\n' "$0" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
+73
-7
@@ -2,26 +2,92 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
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}"
|
repo_name="${ALPINE_REPO_NAME:-local}"
|
||||||
arch="${ALPINE_ARCH:-$(apk --print-arch)}"
|
arch="${ALPINE_ARCH:-$(apk --print-arch)}"
|
||||||
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb}"
|
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb lavinmq lavinmq-openrc gitea gitea-openrc rclone-openrc}"
|
||||||
repo_dir="${repo_root}/packages/${repo_name}/${arch}"
|
repo_dir="${repo_root}/packages/${repo_name}/${arch}"
|
||||||
|
registry_url="${ALPINE_REGISTRY_URL:-}"
|
||||||
|
registry_key="${ALPINE_REGISTRY_KEY:-}"
|
||||||
read -r -a package_list <<< "${packages}"
|
read -r -a package_list <<< "${packages}"
|
||||||
|
declare -A source_packages=()
|
||||||
|
local_repo_complete=0
|
||||||
|
|
||||||
if [[ ! -d "${repo_dir}" ]]; then
|
while IFS= read -r package_dir; do
|
||||||
printf 'missing local repository: packages/%s/%s\n' "${repo_name}" "${arch}" >&2
|
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
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp "${repo_dir}"/*.rsa.pub /etc/apk/keys/
|
|
||||||
echo "${repo_root}/packages/${repo_name}" >> /etc/apk/repositories
|
|
||||||
apk update
|
apk update
|
||||||
apk add "${package_list[@]}"
|
apk add "${package_list[@]}"
|
||||||
weed version
|
if command -v weed >/dev/null 2>&1; then
|
||||||
|
weed version
|
||||||
|
ls -1 /etc/seaweedfs
|
||||||
|
fi
|
||||||
if command -v greptime >/dev/null 2>&1; then
|
if command -v greptime >/dev/null 2>&1; then
|
||||||
greptime --version
|
greptime --version
|
||||||
fi
|
fi
|
||||||
ls -1 /etc/seaweedfs
|
if command -v lavinmq >/dev/null 2>&1; then
|
||||||
|
lavinmq -v
|
||||||
|
lavinmqctl --version
|
||||||
|
lavinmqperf --version
|
||||||
|
fi
|
||||||
|
if command -v gitea >/dev/null 2>&1; then
|
||||||
|
gitea --version
|
||||||
|
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
|
if ls /etc/init.d/seaweedfs.* >/dev/null 2>&1; then
|
||||||
find /etc/init.d -maxdepth 1 -name 'seaweedfs.*' -print | sort
|
find /etc/init.d -maxdepth 1 -name 'seaweedfs.*' -print | sort
|
||||||
fi
|
fi
|
||||||
|
if [[ -f /etc/init.d/lavinmq ]]; then
|
||||||
|
printf '%s\n' /etc/init.d/lavinmq
|
||||||
|
fi
|
||||||
|
if [[ -f /etc/init.d/gitea ]]; then
|
||||||
|
printf '%s\n' /etc/init.d/gitea
|
||||||
|
fi
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ repo_name="${ALPINE_REPO_NAME:-local}"
|
|||||||
arch="${ALPINE_ARCH:-x86_64}"
|
arch="${ALPINE_ARCH:-x86_64}"
|
||||||
|
|
||||||
export CARCH="${CARCH:-$arch}"
|
export CARCH="${CARCH:-$arch}"
|
||||||
export PACKAGER="${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}"
|
export PACKAGER="${PACKAGER:-local}"
|
||||||
if [[ -n "${PACKAGER_PRIVKEY:-}" ]]; then
|
if [[ -n "${PACKAGER_PRIVKEY:-}" ]]; then
|
||||||
export PACKAGER_PRIVKEY
|
export PACKAGER_PRIVKEY
|
||||||
fi
|
fi
|
||||||
@@ -15,6 +15,15 @@ fi
|
|||||||
git config --global --add safe.directory /work
|
git config --global --add safe.directory /work
|
||||||
mkdir -p /home/builder/.abuild /home/builder/packages "${package_dir}"
|
mkdir -p /home/builder/.abuild /home/builder/packages "${package_dir}"
|
||||||
|
|
||||||
|
install_repo_keys() {
|
||||||
|
local key
|
||||||
|
shopt -s nullglob
|
||||||
|
for key in "/home/builder/packages/${repo_name}"/*/*.rsa.pub; do
|
||||||
|
doas cp "${key}" /etc/apk/keys/
|
||||||
|
done
|
||||||
|
shopt -u nullglob
|
||||||
|
}
|
||||||
|
|
||||||
if [[ -n "${PACKAGER_PRIVKEY:-}" && ! -f "${PACKAGER_PRIVKEY}" ]]; then
|
if [[ -n "${PACKAGER_PRIVKEY:-}" && ! -f "${PACKAGER_PRIVKEY}" ]]; then
|
||||||
abuild-keygen -a -n
|
abuild-keygen -a -n
|
||||||
elif ! compgen -G "/home/builder/.abuild/*.rsa" > /dev/null; then
|
elif ! compgen -G "/home/builder/.abuild/*.rsa" > /dev/null; then
|
||||||
@@ -34,6 +43,7 @@ if [[ -n "${PACKAGER_PRIVKEY:-}" && -f "${PACKAGER_PRIVKEY}.pub" ]]; then
|
|||||||
elif compgen -G "/home/builder/.abuild/*.rsa.pub" > /dev/null; then
|
elif compgen -G "/home/builder/.abuild/*.rsa.pub" > /dev/null; then
|
||||||
doas cp /home/builder/.abuild/*.rsa.pub /etc/apk/keys/
|
doas cp /home/builder/.abuild/*.rsa.pub /etc/apk/keys/
|
||||||
fi
|
fi
|
||||||
|
install_repo_keys
|
||||||
|
|
||||||
case "${command_name}" in
|
case "${command_name}" in
|
||||||
build)
|
build)
|
||||||
|
|||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
|
||||||
|
shellcheck \
|
||||||
|
"${repo_root}"/scripts/apk/*.sh \
|
||||||
|
"${repo_root}"/packaging/alpine/local/*/scripts/*.sh
|
||||||
@@ -2,7 +2,25 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
# shellcheck source=scripts/apk/package-lib.sh
|
||||||
|
. "${repo_root}/scripts/apk/package-lib.sh"
|
||||||
|
|
||||||
repo_dir="${repo_root}/packages/local"
|
repo_dir="${repo_root}/packages/local"
|
||||||
|
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
|
||||||
|
declare -A expected_apks=()
|
||||||
|
|
||||||
|
while IFS= read -r package_source_dir; do
|
||||||
|
apk_validate_package_dir "${package_source_dir}"
|
||||||
|
for arch in ${arches}; do
|
||||||
|
if ! apk_package_supports_arch "${package_source_dir}" "${arch}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r apk_name; do
|
||||||
|
expected_apks["${repo_dir}/${arch}/${apk_name}"]=1
|
||||||
|
done < <(apk_package_apk_names "${package_source_dir}" "${arch}")
|
||||||
|
done
|
||||||
|
done < <(apk_all_package_dirs "${repo_root}")
|
||||||
|
|
||||||
if [[ -n "${ALPINE_ARCH:-}" ]]; then
|
if [[ -n "${ALPINE_ARCH:-}" ]]; then
|
||||||
package_dirs=("${repo_dir}/${ALPINE_ARCH}")
|
package_dirs=("${repo_dir}/${ALPINE_ARCH}")
|
||||||
@@ -29,6 +47,10 @@ for package_dir in "${package_dirs[@]}"; do
|
|||||||
|
|
||||||
printf '## %s\n' "$(basename "${package_dir}")"
|
printf '## %s\n' "$(basename "${package_dir}")"
|
||||||
for apk in "${apks[@]}"; do
|
for apk in "${apks[@]}"; do
|
||||||
|
if [[ -z "${expected_apks[${apk}]:-}" ]]; then
|
||||||
|
printf 'Skipping stale local APK: %s\n' "${apk#"${repo_root}/"}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
printf '### %s\n' "$(basename "${apk}")"
|
printf '### %s\n' "$(basename "${apk}")"
|
||||||
tar -xOf "${apk}" .PKGINFO 2>/dev/null \
|
tar -xOf "${apk}" .PKGINFO 2>/dev/null \
|
||||||
| sed -n '/^pkgname =/p;/^pkgver =/p;/^arch =/p;/^depend =/p;/^provides =/p;/^install_if =/p'
|
| sed -n '/^pkgname =/p;/^pkgver =/p;/^arch =/p;/^depend =/p;/^provides =/p;/^install_if =/p'
|
||||||
|
|||||||
Executable
+103
@@ -0,0 +1,103 @@
|
|||||||
|
#!/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
|
||||||
Executable
+225
@@ -0,0 +1,225 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
# shellcheck source=scripts/apk/package-lib.sh
|
||||||
|
source "${repo_root}/scripts/apk/package-lib.sh"
|
||||||
|
|
||||||
|
mode="${APK_UPDATE_CHECK_MODE:-warn}"
|
||||||
|
if [[ "${mode}" != "warn" && "${mode}" != "fail" ]]; then
|
||||||
|
printf 'APK_UPDATE_CHECK_MODE must be warn or fail\n' >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
github_latest_release() {
|
||||||
|
local repo="$1"
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
apkbuild_value() {
|
||||||
|
local package_dir="$1"
|
||||||
|
local key="$2"
|
||||||
|
|
||||||
|
awk -F= -v key="${key}" '
|
||||||
|
$1 == key {
|
||||||
|
value = $2
|
||||||
|
gsub(/["'\'']/, "", value)
|
||||||
|
gsub(/^[ \t]+|[ \t]+$/, "", value)
|
||||||
|
print value
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
' "${package_dir}/APKBUILD"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_update_metadata() {
|
||||||
|
local package_dir="$1"
|
||||||
|
local metadata="${package_dir}/update-check.conf"
|
||||||
|
|
||||||
|
provider=""
|
||||||
|
repo=""
|
||||||
|
version_prefix="v"
|
||||||
|
|
||||||
|
if [[ ! -f "${metadata}" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "${metadata}"
|
||||||
|
|
||||||
|
if [[ "${provider}" != "github" || -z "${repo}" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_version() {
|
||||||
|
local version="$1"
|
||||||
|
local prefix="$2"
|
||||||
|
|
||||||
|
case "${prefix}" in
|
||||||
|
none|"")
|
||||||
|
printf '%s\n' "${version}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf '%s\n' "${version#"${prefix}"}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
version_is_newer() {
|
||||||
|
local latest="$1"
|
||||||
|
local current="$2"
|
||||||
|
local apk_result
|
||||||
|
local sorted
|
||||||
|
|
||||||
|
if [[ "${latest}" == "${current}" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v apk >/dev/null 2>&1; then
|
||||||
|
apk_result="$(apk version -t "${latest}-r0" "${current}-r0" 2>/dev/null || true)"
|
||||||
|
[[ "${apk_result}" == ">" ]]
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if sort -V </dev/null >/dev/null 2>&1; then
|
||||||
|
sorted="$(printf '%s\n%s\n' "${current}" "${latest}" | sort -V | tail -n 1)"
|
||||||
|
[[ "${sorted}" == "${latest}" && "${latest}" != "${current}" ]]
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
printf '%-14s %-14s %-14s %-18s %s\n' "PACKAGE" "CURRENT" "LATEST" "STATUS" "UPSTREAM"
|
||||||
|
|
||||||
|
has_update=0
|
||||||
|
has_unknown=0
|
||||||
|
release_details=""
|
||||||
|
|
||||||
|
while IFS= read -r package_dir; do
|
||||||
|
apk_validate_package_dir "${package_dir}"
|
||||||
|
|
||||||
|
package_name="$(apk_package_name "${package_dir}")"
|
||||||
|
current_version="$(apkbuild_value "${package_dir}" "pkgver")"
|
||||||
|
status="unknown"
|
||||||
|
latest_version="-"
|
||||||
|
upstream_url="-"
|
||||||
|
|
||||||
|
if load_update_metadata "${package_dir}"; then
|
||||||
|
upstream_url="https://github.com/${repo}/releases"
|
||||||
|
if latest_tag="$(github_latest_release "${repo}")" && [[ -n "${latest_tag}" ]]; then
|
||||||
|
latest_version="$(normalize_version "${latest_tag}" "${version_prefix}")"
|
||||||
|
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
|
||||||
|
else
|
||||||
|
has_unknown=1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
has_unknown=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%-14s %-14s %-14s %-18s %s\n' \
|
||||||
|
"${package_name}" \
|
||||||
|
"${current_version:-"-"}" \
|
||||||
|
"${latest_version}" \
|
||||||
|
"${status}" \
|
||||||
|
"${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
|
||||||
@@ -37,6 +37,14 @@ apk_package_dirs() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
apk_all_package_dirs "${repo_root}"
|
||||||
|
}
|
||||||
|
|
||||||
|
apk_all_package_dirs() {
|
||||||
|
local repo_root="$1"
|
||||||
|
local package_root
|
||||||
|
|
||||||
|
package_root="$(apk_package_root "${repo_root}")"
|
||||||
find "${package_root}" -mindepth 2 -maxdepth 2 -name APKBUILD -print \
|
find "${package_root}" -mindepth 2 -maxdepth 2 -name APKBUILD -print \
|
||||||
| sed 's#/APKBUILD$##' \
|
| sed 's#/APKBUILD$##' \
|
||||||
| sort
|
| sort
|
||||||
@@ -87,6 +95,56 @@ apk_package_supports_arch() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apk_package_apk_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.apk\n' "${pkgname}" "${pkgver}" "${pkgrel}"
|
||||||
|
for subpackage in ${subpackages:-}; do
|
||||||
|
subpackage="${subpackage%%:*}"
|
||||||
|
printf '%s-%s-r%s.apk\n' "${subpackage}" "${pkgver}" "${pkgrel}"
|
||||||
|
done
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
apk_container_package_dir() {
|
||||||
local repo_root="$1"
|
local repo_root="$1"
|
||||||
local package_dir="$2"
|
local package_dir="$2"
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ set -euo pipefail
|
|||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
|
||||||
cd "${repo_root}"
|
cd "${repo_root}"
|
||||||
|
mise run apk:outdated
|
||||||
mise run apk:lint
|
mise run apk:lint
|
||||||
|
mise run apk:lint-shell
|
||||||
mise run apk:build-all
|
mise run apk:build-all
|
||||||
mise run apk:packages
|
mise run apk:packages
|
||||||
mise run apk:smoke
|
mise run apk:smoke
|
||||||
|
mise run apk:security-report
|
||||||
|
|||||||
@@ -2,8 +2,12 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
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}"
|
repo_name="${ALPINE_REPO_NAME:-local}"
|
||||||
alpine_version="${ALPINE_VERSION:-3.23}"
|
alpine_version="${ALPINE_VERSION:-3.24}"
|
||||||
|
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
|
||||||
branch="${ALPINE_REGISTRY_BRANCH:-v${alpine_version}}"
|
branch="${ALPINE_REGISTRY_BRANCH:-v${alpine_version}}"
|
||||||
repository="${ALPINE_REGISTRY_REPOSITORY:-${PACKAGE_NAME:-main}}"
|
repository="${ALPINE_REGISTRY_REPOSITORY:-${PACKAGE_NAME:-main}}"
|
||||||
instance_url="${INSTANCE_URL:-}"
|
instance_url="${INSTANCE_URL:-}"
|
||||||
@@ -46,9 +50,42 @@ if [[ "${#apks[@]}" -eq 0 ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf 'Publishing %d APK files to %s\n' "${#apks[@]}" "${upload_url}"
|
declare -A expected_apks=()
|
||||||
|
while IFS= read -r package_dir; do
|
||||||
|
apk_validate_package_dir "${package_dir}"
|
||||||
|
for arch in ${arches}; do
|
||||||
|
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r apk_name; do
|
||||||
|
expected_apks["${package_root}/${arch}/${apk_name}"]=1
|
||||||
|
done < <(apk_package_apk_names "${package_dir}" "${arch}")
|
||||||
|
done
|
||||||
|
done < <(apk_all_package_dirs "${repo_root}")
|
||||||
|
|
||||||
|
current_apks=()
|
||||||
|
stale_count=0
|
||||||
for apk in "${apks[@]}"; do
|
for apk in "${apks[@]}"; do
|
||||||
|
if [[ -z "${expected_apks[${apk}]:-}" ]]; then
|
||||||
|
printf 'Skipping stale local APK: %s\n' "${apk#"${repo_root}/"}"
|
||||||
|
stale_count=$((stale_count + 1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
current_apks+=("${apk}")
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "${#current_apks[@]}" -eq 0 ]]; then
|
||||||
|
printf 'no current APK files found under %s\n' "${package_root}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'Publishing %d APK files to %s\n' "${#current_apks[@]}" "${upload_url}"
|
||||||
|
if [[ "${stale_count}" -ne 0 ]]; then
|
||||||
|
printf 'Skipping %d stale local APK file(s)\n' "${stale_count}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for apk in "${current_apks[@]}"; do
|
||||||
filename="$(basename "${apk}")"
|
filename="$(basename "${apk}")"
|
||||||
status="$(
|
status="$(
|
||||||
curl --silent --show-error --location \
|
curl --silent --show-error --location \
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
ARG ALPINE_VERSION=3.24
|
||||||
|
FROM alpine:${ALPINE_VERSION}
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash openrc
|
||||||
Executable
+149
@@ -0,0 +1,149 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
. "${repo_root}/scripts/apk/package-lib.sh"
|
||||||
|
|
||||||
|
alpine_version="${ALPINE_VERSION:-3.24}"
|
||||||
|
repo_name="${ALPINE_REPO_NAME:-local}"
|
||||||
|
arch="${ALPINE_ARCH:-x86_64}"
|
||||||
|
platform="${ALPINE_TEST_PLATFORM:-linux/amd64}"
|
||||||
|
repo_dir="${repo_root}/packages/${repo_name}/${arch}"
|
||||||
|
runtime_mode="${ALPINE_RUNTIME_TEST_MODE:-auto}"
|
||||||
|
runtime_image="${ALPINE_RUNTIME_TEST_IMAGE:-alpine-apk-runtime-test:${alpine_version}}"
|
||||||
|
|
||||||
|
validate_repo() {
|
||||||
|
if [[ ! -d "${repo_dir}" ]]; then
|
||||||
|
printf 'missing local repository: packages/%s/%s\n' "${repo_name}" "${arch}" >&2
|
||||||
|
printf 'run: ALPINE_ARCH=%s mise run apk:build\n' "${arch}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
repo_keys=("${repo_dir}"/*.rsa.pub)
|
||||||
|
repo_indexes=("${repo_dir}"/APKINDEX.tar.gz)
|
||||||
|
shopt -u nullglob
|
||||||
|
|
||||||
|
if [[ "${#repo_keys[@]}" -eq 0 ]]; then
|
||||||
|
printf 'missing repository key: packages/%s/%s/*.rsa.pub\n' "${repo_name}" "${arch}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "${#repo_indexes[@]}" -eq 0 ]]; then
|
||||||
|
printf 'missing repository index: packages/%s/%s/APKINDEX.tar.gz\n' "${repo_name}" "${arch}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
in_alpine() {
|
||||||
|
[[ -f /etc/alpine-release ]] && command -v apk >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_direct_runtime() {
|
||||||
|
apk add --no-cache bash openrc >/dev/null
|
||||||
|
cp "${repo_dir}"/*.rsa.pub /etc/apk/keys/
|
||||||
|
printf '%s\n' "${repo_root}/packages/${repo_name}" >> /etc/apk/repositories
|
||||||
|
apk update
|
||||||
|
mkdir -p /run/openrc
|
||||||
|
touch /run/openrc/softlevel
|
||||||
|
}
|
||||||
|
|
||||||
|
run_hook_direct() {
|
||||||
|
local hook_path="$1"
|
||||||
|
local package_dir="$2"
|
||||||
|
local package_name="$3"
|
||||||
|
|
||||||
|
PACKAGE_DIR="${package_dir}" \
|
||||||
|
PACKAGE_NAME="${package_name}" \
|
||||||
|
"${hook_path}"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_hook_docker() {
|
||||||
|
local package_dir_rel="$1"
|
||||||
|
|
||||||
|
docker run --rm --privileged --platform "${platform}" \
|
||||||
|
-e "ALPINE_ARCH=${arch}" \
|
||||||
|
-e "ALPINE_REPO_NAME=${repo_name}" \
|
||||||
|
-e "PACKAGE_DIR=/work/${package_dir_rel}" \
|
||||||
|
-e "PACKAGE_NAME=${package_name}" \
|
||||||
|
-v "${repo_root}:/work:ro" \
|
||||||
|
-v "${repo_root}/packages/${repo_name}:/repo:ro" \
|
||||||
|
"${runtime_image}" \
|
||||||
|
sh -lc '
|
||||||
|
set -e
|
||||||
|
cp "/repo/${ALPINE_ARCH}"/*.rsa.pub /etc/apk/keys/
|
||||||
|
printf "%s\n" /repo >> /etc/apk/repositories
|
||||||
|
apk update
|
||||||
|
mkdir -p /run/openrc
|
||||||
|
touch /run/openrc/softlevel
|
||||||
|
exec /bin/bash "${PACKAGE_DIR}/scripts/runtime-test.sh"
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
build_runtime_image() {
|
||||||
|
docker build \
|
||||||
|
--platform "${platform}" \
|
||||||
|
--build-arg "ALPINE_VERSION=${alpine_version}" \
|
||||||
|
-f "${repo_root}/scripts/apk/runtime-test.Dockerfile" \
|
||||||
|
-t "${runtime_image}" \
|
||||||
|
"${repo_root}"
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_repo
|
||||||
|
|
||||||
|
case "${runtime_mode}" in
|
||||||
|
auto)
|
||||||
|
if in_alpine; then
|
||||||
|
runtime_mode="direct"
|
||||||
|
else
|
||||||
|
runtime_mode="docker"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
direct|docker) ;;
|
||||||
|
*)
|
||||||
|
printf 'unsupported ALPINE_RUNTIME_TEST_MODE: %s\n' "${runtime_mode}" >&2
|
||||||
|
printf 'expected: auto, direct, or docker\n' >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "${runtime_mode}" == "direct" ]]; then
|
||||||
|
prepare_direct_runtime
|
||||||
|
else
|
||||||
|
build_runtime_image
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r package_dir; do
|
||||||
|
apk_validate_package_dir "${package_dir}"
|
||||||
|
package_name="$(apk_package_name "${package_dir}")"
|
||||||
|
hook_path="${package_dir}/scripts/runtime-test.sh"
|
||||||
|
|
||||||
|
if [[ ! -e "${hook_path}" ]]; then
|
||||||
|
printf 'Skipping %s: no runtime-test hook\n' "${package_name}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ ! -x "${hook_path}" ]]; then
|
||||||
|
printf 'package hook is not executable: %s\n' "${hook_path}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
|
||||||
|
printf 'Skipping %s: unsupported arch %s\n' "${package_name}" "${arch}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${package_dir}" in
|
||||||
|
"${repo_root}"/*)
|
||||||
|
package_dir_rel="${package_dir#"${repo_root}/"}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf 'package directory must be inside repository: %s\n' "${package_dir}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf 'Running runtime-test hook for %s\n' "${package_name}"
|
||||||
|
if [[ "${runtime_mode}" == "direct" ]]; then
|
||||||
|
run_hook_direct "${hook_path}" "${package_dir}" "${package_name}"
|
||||||
|
else
|
||||||
|
run_hook_docker "${package_dir_rel}"
|
||||||
|
fi
|
||||||
|
done < <(apk_package_dirs "${repo_root}")
|
||||||
Executable
+183
@@ -0,0 +1,183 @@
|
|||||||
|
#!/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}")
|
||||||
+30
-4
@@ -2,10 +2,10 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
alpine_version="${ALPINE_VERSION:-3.23}"
|
alpine_version="${ALPINE_VERSION:-3.24}"
|
||||||
platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
|
platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
|
||||||
arch="${ALPINE_ARCH:-x86_64}"
|
arch="${ALPINE_ARCH:-x86_64}"
|
||||||
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc}"
|
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb lavinmq lavinmq-openrc gitea gitea-openrc rclone-openrc}"
|
||||||
|
|
||||||
if [[ ! -d "${repo_root}/packages/local/${arch}" ]]; then
|
if [[ ! -d "${repo_root}/packages/local/${arch}" ]]; then
|
||||||
printf 'missing local repository: packages/local/%s\n' "${arch}" >&2
|
printf 'missing local repository: packages/local/%s\n' "${arch}" >&2
|
||||||
@@ -22,9 +22,35 @@ docker run --rm --platform "${platform}" \
|
|||||||
echo /repo >> /etc/apk/repositories
|
echo /repo >> /etc/apk/repositories
|
||||||
apk update >/dev/null
|
apk update >/dev/null
|
||||||
apk add ${packages} >/dev/null
|
apk add ${packages} >/dev/null
|
||||||
weed version
|
if command -v weed >/dev/null 2>&1; then
|
||||||
ls -1 /etc/seaweedfs
|
weed version
|
||||||
|
ls -1 /etc/seaweedfs
|
||||||
|
fi
|
||||||
|
if command -v greptime >/dev/null 2>&1; then
|
||||||
|
greptime --version
|
||||||
|
fi
|
||||||
|
if command -v lavinmq >/dev/null 2>&1; then
|
||||||
|
lavinmq -v
|
||||||
|
lavinmqctl --version
|
||||||
|
lavinmqperf --version
|
||||||
|
fi
|
||||||
|
if command -v gitea >/dev/null 2>&1; then
|
||||||
|
gitea --version
|
||||||
|
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
|
if ls /etc/init.d/seaweedfs.* >/dev/null 2>&1; then
|
||||||
ls -1 /etc/init.d/seaweedfs.* | sort
|
ls -1 /etc/init.d/seaweedfs.* | sort
|
||||||
fi
|
fi
|
||||||
|
if [ -f /etc/init.d/lavinmq ]; then
|
||||||
|
ls -1 /etc/init.d/lavinmq
|
||||||
|
fi
|
||||||
|
if [ -f /etc/init.d/gitea ]; then
|
||||||
|
ls -1 /etc/init.d/gitea
|
||||||
|
fi
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
apk_test_install_run() {
|
||||||
|
local repo_root="$1"
|
||||||
|
local package_name="$2"
|
||||||
|
local package_version="$3"
|
||||||
|
local alpine_version="${ALPINE_VERSION:-3.24}"
|
||||||
|
local arch="${ALPINE_ARCH:-x86_64}"
|
||||||
|
local repository_url="${ALPINE_REPOSITORY_URL:-}"
|
||||||
|
local repository_key_url="${ALPINE_REPOSITORY_KEY_URL:-}"
|
||||||
|
local platform
|
||||||
|
local test_command
|
||||||
|
|
||||||
|
case "${arch}" in
|
||||||
|
x86_64) platform="${ALPINE_TEST_PLATFORM:-linux/amd64}" ;;
|
||||||
|
aarch64) platform="${ALPINE_TEST_PLATFORM:-linux/arm64}" ;;
|
||||||
|
*)
|
||||||
|
printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2
|
||||||
|
return 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ -z "${repository_url}" && "${SKIP_BUILD:-0}" != "1" ]]; then
|
||||||
|
ALPINE_PACKAGE="${package_name}" "${repo_root}/scripts/apk/build.sh" build "${arch}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${repository_url}" && ! -d "${repo_root}/packages/local/${arch}" ]]; then
|
||||||
|
printf 'missing local repository: packages/local/%s\n' "${arch}" >&2
|
||||||
|
printf 'run: ALPINE_PACKAGE=%s mise run apk:build\n' "${package_name}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_command="$(cat)"
|
||||||
|
docker run --rm --platform "${platform}" \
|
||||||
|
-e "ALPINE_ARCH=${arch}" \
|
||||||
|
-e "PACKAGE_NAME=${package_name}" \
|
||||||
|
-e "PACKAGE_VERSION=${package_version}" \
|
||||||
|
-e "ALPINE_REPOSITORY_URL=${repository_url}" \
|
||||||
|
-e "ALPINE_REPOSITORY_KEY_URL=${repository_key_url}" \
|
||||||
|
-v "${repo_root}/packages/local:/repo:ro" \
|
||||||
|
"alpine:${alpine_version}" \
|
||||||
|
sh -lc "${test_command}"
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user