mirror of
https://github.com/rsyslog/rsyslog.git
synced 2026-08-24 19:24:14 +02:00
Why: Ensure published package verification detects unexpected as well as missing profile dependencies. Impact: The full profile must now match its exact version-locked rsyslog closure. Before/After: Before: checks confirmed required dependencies by membership. After: checks compare the complete normalized rsyslog dependency set. Technical Overview: Debian and Ubuntu normalize the full package Depends field. RPM targets normalize direct rsyslog requirements. Alpine normalizes the direct dependency atoms after its package header. All comparisons retain exact package version requirements. With the help of AI-Agents: Codex
809 lines
29 KiB
YAML
809 lines
29 KiB
YAML
# Copyright 2026 Rainer Gerhards and Others
|
|
#
|
|
# https://github.com/rsyslog/rsyslog
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# https://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
---
|
|
name: ubuntu daily stable
|
|
|
|
'on':
|
|
workflow_dispatch:
|
|
inputs:
|
|
source_ref:
|
|
description: rsyslog source branch, tag, or commit to package
|
|
required: true
|
|
default: main
|
|
type: string
|
|
publish_to_archive:
|
|
description: Publish to the configured DigitalOcean Spaces archive
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
schedule:
|
|
- cron: '23 4 * * *'
|
|
|
|
concurrency:
|
|
group: ubuntu-daily-stable
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
DEBIAN_CI_POLICY_FILE: .github/ubuntu-daily-stable-26.04-policy.yml
|
|
PACKAGE_FEATURE_CONTRACT: .github/daily-stable-package-features.yml
|
|
DEBIAN_CI_HELPER: .github/scripts/debian_package_build.sh
|
|
DEBIAN_DAILY_STABLE_HELPER: devtools/release/debian-daily-stable.sh
|
|
DEBIAN_BUILD_ROOT: /tmp/rsyslog-ubuntu-daily-stable-build
|
|
DEBIAN_SUITE: resolute
|
|
DEBIAN_COMPONENT: main
|
|
PACKAGE_REPOSITORY_ARCHITECTURES: amd64 arm64
|
|
PACKAGE_CHANNEL: daily-stable
|
|
PACKAGE_DISTRO: ubuntu
|
|
PACKAGE_DISTRO_LABEL: Ubuntu
|
|
PACKAGE_DISTRO_VERSION: '26.04'
|
|
SPACE_PREFIX: apt/daily-stable/ubuntu/26.04
|
|
|
|
jobs:
|
|
preflight:
|
|
name: preflight
|
|
runs-on: ubuntu-24.04
|
|
if: github.repository == 'rsyslog/rsyslog'
|
|
permissions:
|
|
contents: read
|
|
outputs:
|
|
should_run: ${{ steps.decision.outputs.should_run }}
|
|
should_publish: ${{ steps.decision.outputs.should_publish }}
|
|
source_ref: ${{ steps.decision.outputs.source_ref }}
|
|
steps:
|
|
- name: Decide whether this run is active
|
|
id: decision
|
|
env:
|
|
EVENT_NAME: ${{ github.event_name }}
|
|
MANUAL_PUBLISH: ${{ inputs.publish_to_archive }}
|
|
MANUAL_SOURCE_REF: ${{ inputs.source_ref }}
|
|
SCHEDULE_ENABLED: ${{ vars.UBUNTU_DAILY_STABLE_ENABLED }}
|
|
run: |
|
|
set -euo pipefail
|
|
should_run=false
|
|
should_publish=false
|
|
source_ref=main
|
|
|
|
case "$EVENT_NAME" in
|
|
workflow_dispatch)
|
|
should_run=true
|
|
source_ref="${MANUAL_SOURCE_REF:-main}"
|
|
if [ "${MANUAL_PUBLISH:-false}" = "true" ]; then
|
|
should_publish=true
|
|
fi
|
|
;;
|
|
schedule)
|
|
case "${SCHEDULE_ENABLED:-}" in
|
|
true)
|
|
should_run=true
|
|
should_publish=true
|
|
;;
|
|
false)
|
|
;;
|
|
*)
|
|
echo "::error::UBUNTU_DAILY_STABLE_ENABLED must be a repository variable set to true or false"
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
{
|
|
echo "should_run=$should_run"
|
|
echo "should_publish=$should_publish"
|
|
echo "source_ref=$source_ref"
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
build:
|
|
name: build Ubuntu 26.04 ${{ matrix.arch }} packages
|
|
needs: preflight
|
|
if: needs.preflight.outputs.should_run == 'true'
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- arch: amd64
|
|
runner: ubuntu-24.04
|
|
- arch: arm64
|
|
runner: ubuntu-24.04-arm
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 120
|
|
container:
|
|
image: ubuntu:26.04
|
|
options: --user root
|
|
permissions:
|
|
contents: read
|
|
env:
|
|
DEBIAN_ARCH: ${{ matrix.arch }}
|
|
outputs:
|
|
archive_date: ${{ steps.version.outputs.archive_date }}
|
|
version: ${{ steps.version.outputs.version }}
|
|
source_sha: ${{ steps.source.outputs.source_sha }}
|
|
steps:
|
|
- name: Bootstrap container tools
|
|
run: |
|
|
apt-get update
|
|
apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
git \
|
|
python3
|
|
|
|
- name: Checkout archive automation
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Checkout source to package
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
path: rsyslog-source
|
|
persist-credentials: false
|
|
ref: ${{ needs.preflight.outputs.source_ref }}
|
|
|
|
- name: Record packaged source revision
|
|
id: source
|
|
run: |
|
|
set -euo pipefail
|
|
source_sha="$(git -C rsyslog-source rev-parse HEAD)"
|
|
{
|
|
echo "source_sha=$source_sha"
|
|
echo "SOURCE_GIT_SHA=$source_sha"
|
|
echo "RSYSLOG_SOURCE_DIR=$GITHUB_WORKSPACE/rsyslog-source"
|
|
} | tee -a "$GITHUB_ENV" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Install prerequisites
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" install_prereqs
|
|
apt-get install -y --no-install-recommends \
|
|
apt-utils \
|
|
curl \
|
|
gnupg \
|
|
xz-utils
|
|
|
|
- name: Test incremental archive generation
|
|
id: archive_self_test
|
|
run: |
|
|
devtools/ci-flake-phase.sh run ubuntu-archive-self-test custom -- \
|
|
"$GITHUB_WORKSPACE/$DEBIAN_DAILY_STABLE_HELPER" self-test
|
|
|
|
- name: Generate daily package version
|
|
id: version
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_DAILY_STABLE_HELPER" version
|
|
|
|
- name: Load Ubuntu CI policy
|
|
run: |
|
|
mkdir -p "$DEBIAN_BUILD_ROOT"
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" load_policy \
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_POLICY_FILE" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy"
|
|
|
|
- name: Fetch Ubuntu packaging baseline
|
|
id: packaging
|
|
run: |
|
|
baseline_version_file="$DEBIAN_BUILD_ROOT/debian-packaging-version"
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" \
|
|
fetch_debian_release_packaging \
|
|
"$DEBIAN_BUILD_ROOT/debian-packaging" \
|
|
"$baseline_version_file"
|
|
baseline_version="$(cat "$baseline_version_file")"
|
|
echo "baseline_version=$baseline_version" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Apply packaging baseline policy
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" apply_control_replacements \
|
|
"$DEBIAN_BUILD_ROOT/debian-packaging/control" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/control_replacements.tsv" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/control_replacements.reasons.txt"
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" \
|
|
apply_install_manifest_additions \
|
|
"$DEBIAN_BUILD_ROOT/debian-packaging" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/install_manifest_additions.tsv"
|
|
python3 devtools/release/package-feature-overlay.py debian \
|
|
"$DEBIAN_BUILD_ROOT/debian-packaging" \
|
|
"$PACKAGE_FEATURE_CONTRACT"
|
|
|
|
- name: Install Ubuntu build dependencies
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" install_build_deps \
|
|
"$DEBIAN_BUILD_ROOT/debian-packaging/control" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/supplemental_build_deps.txt"
|
|
|
|
- name: Generate rsyslog dist tarball
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" run_dist_build \
|
|
"$GITHUB_WORKSPACE/rsyslog-source"
|
|
|
|
- name: Locate rsyslog dist tarball
|
|
run: |
|
|
dist_tarball="$(
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" find_dist_tarball \
|
|
"$GITHUB_WORKSPACE/rsyslog-source"
|
|
)"
|
|
echo "DIST_TARBALL=$dist_tarball" >> "$GITHUB_ENV"
|
|
|
|
- name: Unpack tarball and inject Ubuntu packaging
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" unpack_source_tree \
|
|
"$GITHUB_WORKSPACE/rsyslog-source" \
|
|
"$DIST_TARBALL" \
|
|
"$DEBIAN_BUILD_ROOT/debian-packaging" \
|
|
"$DEBIAN_BUILD_ROOT/debian-src"
|
|
|
|
- name: Stamp daily stable changelog
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_DAILY_STABLE_HELPER" stamp-changelog \
|
|
"$DEBIAN_BUILD_ROOT/debian-src" \
|
|
"$VERSION"
|
|
|
|
- name: Apply Ubuntu CI policy
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" apply_not_installed_policy \
|
|
"$DEBIAN_BUILD_ROOT/debian-src" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/not_installed_paths.txt" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/not_installed_paths.reasons.txt"
|
|
"$GITHUB_WORKSPACE/$DEBIAN_CI_HELPER" resolve_patch_policy \
|
|
"$DEBIAN_BUILD_ROOT/debian-src" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/allowed_patch_skips.txt" \
|
|
"$DEBIAN_BUILD_ROOT/debian-ci-policy/allowed_patch_skips.reasons.txt" \
|
|
strict
|
|
|
|
- name: Build source and binary packages
|
|
id: package_build
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
devtools/ci-flake-phase.sh run ubuntu-package-build custom -- \
|
|
"$GITHUB_WORKSPACE/$DEBIAN_DAILY_STABLE_HELPER" build-package \
|
|
"$GITHUB_WORKSPACE/rsyslog-source" \
|
|
"$DEBIAN_BUILD_ROOT/debian-src" \
|
|
"$DIST_TARBALL" \
|
|
"$GITHUB_WORKSPACE/ubuntu-daily-stable-artifacts" \
|
|
"$VERSION" \
|
|
"$DEBIAN_BUILD_ROOT/ubuntu-daily-stable-build.log"
|
|
|
|
- name: Upload failure evidence
|
|
if: >-
|
|
${{
|
|
failure() &&
|
|
(steps.archive_self_test.outcome == 'failure' ||
|
|
steps.package_build.outcome == 'failure')
|
|
}}
|
|
uses: ./.github/actions/upload-flake-evidence
|
|
with:
|
|
job-name: Ubuntu 26.04 daily stable package build
|
|
|
|
- name: Generate artifact manifest
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
"$GITHUB_WORKSPACE/$DEBIAN_DAILY_STABLE_HELPER" manifest \
|
|
"$GITHUB_WORKSPACE/ubuntu-daily-stable-artifacts" \
|
|
"$VERSION" \
|
|
"$DEBIAN_SUITE" \
|
|
"$DEBIAN_ARCH" \
|
|
"$PACKAGE_CHANNEL" \
|
|
"$PACKAGE_DISTRO" \
|
|
"$PACKAGE_DISTRO_VERSION"
|
|
|
|
- name: Upload Ubuntu package artifacts
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: ubuntu-daily-stable-${{ steps.version.outputs.version }}-${{ matrix.arch }}
|
|
path: ubuntu-daily-stable-artifacts/
|
|
retention-days: 14
|
|
if-no-files-found: error
|
|
|
|
- name: Summarize build
|
|
env:
|
|
BASELINE_VERSION: ${{ steps.packaging.outputs.baseline_version }}
|
|
SOURCE_REF: ${{ needs.preflight.outputs.source_ref }}
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
{
|
|
echo "### Ubuntu daily stable build"
|
|
echo
|
|
echo "- Version: \`$VERSION\`"
|
|
echo "- Source ref: \`$SOURCE_REF\`"
|
|
echo "- Source commit: \`$SOURCE_GIT_SHA\`"
|
|
echo "- Ubuntu packaging baseline: \`rsyslog $BASELINE_VERSION\`"
|
|
echo "- Target: Ubuntu 26.04 (\`$DEBIAN_SUITE\`), \`$DEBIAN_ARCH\`"
|
|
echo "- Archive prefix: \`$SPACE_PREFIX\`"
|
|
echo
|
|
echo "Artifacts:"
|
|
find ubuntu-daily-stable-artifacts -maxdepth 1 -type f \
|
|
-printf '%f\n' | sort |
|
|
while IFS= read -r artifact; do
|
|
printf -- "- \`%s\`\n" "$artifact"
|
|
done
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
publish:
|
|
name: publish DigitalOcean Spaces APT archive
|
|
needs:
|
|
- preflight
|
|
- build
|
|
if: needs.preflight.outputs.should_publish == 'true'
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 30
|
|
environment: debian-daily-stable
|
|
permissions:
|
|
contents: read
|
|
env:
|
|
AWS_ACCESS_KEY_ID: ${{ secrets.DEBIAN_DAILY_STABLE_SPACE_ACCESS_KEY }}
|
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.DEBIAN_DAILY_STABLE_SPACE_SECRET_KEY }}
|
|
AWS_DEFAULT_REGION: ${{ vars.DEBIAN_DAILY_STABLE_SPACE_REGION }}
|
|
SPACE_BUCKET: ${{ vars.DEBIAN_DAILY_STABLE_SPACE_BUCKET }}
|
|
SPACE_ENDPOINT: ${{ vars.DEBIAN_DAILY_STABLE_SPACE_ENDPOINT }}
|
|
DEBIAN_DAILY_STABLE_GPG_PRIVATE_KEY: ${{ secrets.DEBIAN_DAILY_STABLE_GPG_PRIVATE_KEY }}
|
|
DEBIAN_DAILY_STABLE_GPG_PASSPHRASE: ${{ secrets.DEBIAN_DAILY_STABLE_GPG_PASSPHRASE }}
|
|
steps:
|
|
- name: Checkout archive automation
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Prepare repository and Spaces tools
|
|
run: |
|
|
command -v aws
|
|
aws --version
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends \
|
|
apt-utils \
|
|
gnupg \
|
|
xz-utils
|
|
|
|
- name: Validate archive configuration
|
|
run: |
|
|
set -euo pipefail
|
|
for variable in \
|
|
AWS_ACCESS_KEY_ID \
|
|
AWS_SECRET_ACCESS_KEY \
|
|
AWS_DEFAULT_REGION \
|
|
SPACE_BUCKET \
|
|
SPACE_ENDPOINT \
|
|
DEBIAN_DAILY_STABLE_GPG_PRIVATE_KEY; do
|
|
[ -n "${!variable:-}" ] || {
|
|
echo "$variable is empty" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
|
|
- name: Download Ubuntu amd64 package artifacts
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: ubuntu-daily-stable-${{ needs.build.outputs.version }}-amd64
|
|
path: ubuntu-daily-stable-artifacts/amd64
|
|
|
|
- name: Download Ubuntu arm64 package artifacts
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: ubuntu-daily-stable-${{ needs.build.outputs.version }}-arm64
|
|
path: ubuntu-daily-stable-artifacts/arm64
|
|
|
|
- name: Verify artifact checksums
|
|
run: |
|
|
for arch in $PACKAGE_REPOSITORY_ARCHITECTURES; do
|
|
(cd "ubuntu-daily-stable-artifacts/$arch" && sha256sum -c SHA256SUMS)
|
|
done
|
|
|
|
- name: Import archive signing key
|
|
run: |
|
|
set -euo pipefail
|
|
install -m 700 -d "$HOME/.gnupg"
|
|
printf '%s\n' "$DEBIAN_DAILY_STABLE_GPG_PRIVATE_KEY" |
|
|
gpg --batch --import
|
|
gpg --batch --list-secret-keys
|
|
|
|
- name: Download current indexes
|
|
run: |
|
|
set -euo pipefail
|
|
for arch in $PACKAGE_REPOSITORY_ARCHITECTURES; do
|
|
mkdir -p "apt-repo/dists/$DEBIAN_SUITE/$DEBIAN_COMPONENT/binary-$arch"
|
|
done
|
|
mkdir -p "apt-repo/dists/$DEBIAN_SUITE/$DEBIAN_COMPONENT/source"
|
|
|
|
download_if_present() {
|
|
local relative_path="$1"
|
|
local key="$SPACE_PREFIX/$relative_path"
|
|
local remote_key
|
|
|
|
remote_key="$(
|
|
aws s3api list-objects-v2 \
|
|
--endpoint-url "$SPACE_ENDPOINT" \
|
|
--bucket "$SPACE_BUCKET" \
|
|
--prefix "$key" \
|
|
--max-keys 1 \
|
|
--query 'Contents[0].Key' \
|
|
--output text
|
|
)"
|
|
if [ "$remote_key" = "$key" ]; then
|
|
aws s3 cp \
|
|
--endpoint-url "$SPACE_ENDPOINT" \
|
|
"s3://$SPACE_BUCKET/$key" \
|
|
"apt-repo/$relative_path"
|
|
fi
|
|
}
|
|
|
|
for arch in $PACKAGE_REPOSITORY_ARCHITECTURES; do
|
|
download_if_present \
|
|
"dists/$DEBIAN_SUITE/$DEBIAN_COMPONENT/binary-$arch/Packages.xz"
|
|
done
|
|
download_if_present \
|
|
"dists/$DEBIAN_SUITE/$DEBIAN_COMPONENT/source/Sources.xz"
|
|
|
|
- name: Generate signed incremental APT repository
|
|
run: |
|
|
for arch in $PACKAGE_REPOSITORY_ARCHITECTURES; do
|
|
"$GITHUB_WORKSPACE/$DEBIAN_DAILY_STABLE_HELPER" generate-repo \
|
|
"$GITHUB_WORKSPACE/ubuntu-daily-stable-artifacts/$arch" \
|
|
"$GITHUB_WORKSPACE/apt-repo" \
|
|
"$DEBIAN_SUITE" \
|
|
"$DEBIAN_COMPONENT" \
|
|
"$arch"
|
|
done
|
|
|
|
- name: Prepare immutable build snapshot
|
|
env:
|
|
ARCHIVE_DATE: ${{ needs.build.outputs.archive_date }}
|
|
VERSION: ${{ needs.build.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
snapshot_dir="apt-repo/snapshots/$ARCHIVE_DATE/$VERSION"
|
|
for arch in $PACKAGE_REPOSITORY_ARCHITECTURES; do
|
|
mkdir -p "$snapshot_dir/$arch"
|
|
find "ubuntu-daily-stable-artifacts/$arch" -maxdepth 1 -type f \
|
|
\( -name 'manifest.json' -o -name 'SHA256SUMS' \
|
|
-o -name '*.changes' -o -name '*.buildinfo' \
|
|
-o -name 'build.log' \) \
|
|
-exec cp -a {} "$snapshot_dir/$arch/" \;
|
|
done
|
|
|
|
- name: Publish immutable packages and snapshots
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
upload_immutable() {
|
|
local path="$1"
|
|
local relative_path="${path#apt-repo/}"
|
|
local key="$SPACE_PREFIX/$relative_path"
|
|
local remote_key local_hash remote_hash
|
|
|
|
remote_key="$(
|
|
aws s3api list-objects-v2 \
|
|
--endpoint-url "$SPACE_ENDPOINT" \
|
|
--bucket "$SPACE_BUCKET" \
|
|
--prefix "$key" \
|
|
--max-keys 1 \
|
|
--query 'Contents[0].Key' \
|
|
--output text
|
|
)"
|
|
local_hash="$(sha256sum "$path" | awk '{print $1}')"
|
|
if [ "$remote_key" = "$key" ]; then
|
|
remote_hash="$(
|
|
aws s3 cp \
|
|
--quiet \
|
|
--endpoint-url "$SPACE_ENDPOINT" \
|
|
"s3://$SPACE_BUCKET/$key" - |
|
|
sha256sum | awk '{print $1}'
|
|
)"
|
|
[ "$remote_hash" = "$local_hash" ] || {
|
|
echo "immutable archive collision at $key" >&2
|
|
exit 1
|
|
}
|
|
return
|
|
fi
|
|
|
|
aws s3 cp \
|
|
--only-show-errors \
|
|
--endpoint-url "$SPACE_ENDPOINT" \
|
|
--acl public-read \
|
|
--cache-control 'public,max-age=31536000,immutable' \
|
|
--metadata "sha256=$local_hash,max-age=31536000" \
|
|
"$path" \
|
|
"s3://$SPACE_BUCKET/$key"
|
|
}
|
|
|
|
while IFS= read -r -d '' path; do
|
|
upload_immutable "$path"
|
|
done < <(
|
|
find apt-repo/pool apt-repo/snapshots \
|
|
"apt-repo/dists/$DEBIAN_SUITE" \
|
|
-type f \
|
|
\( -path '*/pool/*' -o -path '*/snapshots/*' \
|
|
-o -path '*/by-hash/*' \) \
|
|
-print0
|
|
)
|
|
|
|
- name: Publish archive key and mutable metadata
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
upload_metadata() {
|
|
local path="$1"
|
|
local relative_path="${path#apt-repo/}"
|
|
aws s3 cp \
|
|
--only-show-errors \
|
|
--endpoint-url "$SPACE_ENDPOINT" \
|
|
--acl public-read \
|
|
--cache-control 'public,max-age=60,must-revalidate' \
|
|
--metadata 'max-age=60' \
|
|
"$path" \
|
|
"s3://$SPACE_BUCKET/$SPACE_PREFIX/$relative_path"
|
|
}
|
|
|
|
upload_metadata apt-repo/rsyslog-archive-keyring.asc
|
|
while IFS= read -r -d '' path; do
|
|
upload_metadata "$path"
|
|
done < <(
|
|
find "apt-repo/dists/$DEBIAN_SUITE" -type f \
|
|
! -path '*/by-hash/*' \
|
|
! -name Release \
|
|
! -name Release.gpg \
|
|
! -name InRelease \
|
|
-print0
|
|
)
|
|
upload_metadata "apt-repo/dists/$DEBIAN_SUITE/Release"
|
|
upload_metadata "apt-repo/dists/$DEBIAN_SUITE/Release.gpg"
|
|
upload_metadata "apt-repo/dists/$DEBIAN_SUITE/InRelease"
|
|
|
|
verify:
|
|
name: verify published Ubuntu 26.04 ${{ matrix.arch }} repository
|
|
needs:
|
|
- preflight
|
|
- build
|
|
- publish
|
|
if: needs.preflight.outputs.should_publish == 'true'
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- arch: amd64
|
|
runner: ubuntu-24.04
|
|
- arch: arm64
|
|
runner: ubuntu-24.04-arm
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 20
|
|
container:
|
|
image: ubuntu:26.04
|
|
options: --user root
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
environment: debian-daily-stable
|
|
permissions:
|
|
contents: read
|
|
env:
|
|
DEBIAN_ARCH: ${{ matrix.arch }}
|
|
REPO_URL: ${{ vars.UBUNTU_DAILY_STABLE_REPO_URL }}
|
|
EXPECTED_GPG_FINGERPRINT: ${{ vars.DEBIAN_DAILY_STABLE_GPG_FINGERPRINT }}
|
|
steps:
|
|
- name: Checkout archive automation
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Install verification tools
|
|
run: |
|
|
apt-get update
|
|
apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
curl \
|
|
gnupg \
|
|
gpgv \
|
|
python3 \
|
|
xz-utils
|
|
|
|
- name: Wait for CDN and verify signed metadata
|
|
id: published_metadata
|
|
env:
|
|
VERSION: ${{ needs.build.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
[ -n "$REPO_URL" ] || {
|
|
echo "UBUNTU_DAILY_STABLE_REPO_URL is empty" >&2
|
|
exit 1
|
|
}
|
|
[ -n "$EXPECTED_GPG_FINGERPRINT" ] || {
|
|
echo "DEBIAN_DAILY_STABLE_GPG_FINGERPRINT is empty" >&2
|
|
exit 1
|
|
}
|
|
devtools/ci-flake-phase.sh begin ubuntu-published-metadata custom
|
|
set +e
|
|
verification_rc=1
|
|
for attempt in $(seq 1 20); do
|
|
if "$GITHUB_WORKSPACE/$DEBIAN_DAILY_STABLE_HELPER" verify-repo \
|
|
"$REPO_URL" \
|
|
"$DEBIAN_SUITE" \
|
|
"$DEBIAN_COMPONENT" \
|
|
"$DEBIAN_ARCH" \
|
|
"$VERSION" \
|
|
"$EXPECTED_GPG_FINGERPRINT" \
|
|
true; then
|
|
verification_rc=0
|
|
break
|
|
fi
|
|
echo "Repository not ready yet, retrying ($attempt/20)..."
|
|
if [ "$attempt" -lt 20 ]; then
|
|
sleep 30
|
|
fi
|
|
done
|
|
set -e
|
|
devtools/ci-flake-phase.sh end \
|
|
ubuntu-published-metadata custom "$verification_rc"
|
|
if [ "$verification_rc" -ne 0 ]; then
|
|
echo "Repository verification did not succeed before timeout." >&2
|
|
exit "$verification_rc"
|
|
fi
|
|
|
|
- name: Install and smoke-test the published package
|
|
id: published_install
|
|
env:
|
|
VERSION: ${{ needs.build.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p .ci/flake-evidence/logs
|
|
devtools/ci-flake-phase.sh begin ubuntu-published-install custom
|
|
set +e
|
|
(
|
|
set -euo pipefail
|
|
curl -fsSL "$REPO_URL/rsyslog-archive-keyring.asc" |
|
|
gpg --dearmor -o /usr/share/keyrings/rsyslog-archive-keyring.gpg
|
|
echo "deb [signed-by=/usr/share/keyrings/rsyslog-archive-keyring.gpg] $REPO_URL $DEBIAN_SUITE $DEBIAN_COMPONENT" \
|
|
> /etc/apt/sources.list.d/rsyslog-daily-stable.list
|
|
apt-get update
|
|
apt-get install -y \
|
|
"rsyslog=$VERSION" \
|
|
"rsyslog-standard=$VERSION"
|
|
for package in rsyslog rsyslog-openssl rsyslog-gnutls rsyslog-omotel \
|
|
rsyslog-standard; do
|
|
[ "$(dpkg-query -W -f='${Version}\n' "$package")" = "$VERSION" ]
|
|
done
|
|
apt-get install -y "rsyslog-full=$VERSION"
|
|
full_dependencies="$(dpkg-query -W -f='${Depends}\n' rsyslog-full)"
|
|
expected_full_dependencies="$(
|
|
printf '%s\n' \
|
|
"rsyslog (= $VERSION)" \
|
|
"rsyslog-openssl (= $VERSION)" \
|
|
"rsyslog-gnutls (= $VERSION)" \
|
|
"rsyslog-omotel (= $VERSION)" \
|
|
"rsyslog-omazuredce (= $VERSION)" | sort
|
|
)"
|
|
actual_full_dependencies="$(
|
|
printf '%s\n' "$full_dependencies" | tr ',' '\n' |
|
|
sed 's/^ *//; s/ *$//' | grep '^rsyslog' | sort
|
|
)"
|
|
[ "$actual_full_dependencies" = "$expected_full_dependencies" ]
|
|
installed_version="$(dpkg-query -W -f='${Version}\n' rsyslog)"
|
|
[ "$installed_version" = "$VERSION" ] || {
|
|
echo "installed rsyslog version $installed_version does not match $VERSION" >&2
|
|
exit 1
|
|
}
|
|
for package in rsyslog-openssl rsyslog-gnutls rsyslog-omotel \
|
|
rsyslog-omazuredce rsyslog-standard rsyslog-full; do
|
|
[ "$(dpkg-query -W -f='${Version}\n' "$package")" = "$VERSION" ]
|
|
done
|
|
for package_file in \
|
|
rsyslog-openssl:lmnsd_ossl.so \
|
|
rsyslog-gnutls:lmnsd_gtls.so \
|
|
rsyslog-omotel:omotel.so \
|
|
rsyslog-omazuredce:omazuredce.so; do
|
|
package="${package_file%%:*}"
|
|
module_file="${package_file#*:}"
|
|
module_file="${module_file//./\\.}"
|
|
dpkg-query -L "$package" | grep -Eq "/rsyslog/$module_file$"
|
|
done
|
|
rsyslogd -v
|
|
devtools/release/package-feature-smoke.sh
|
|
) 2>&1 | tee .ci/flake-evidence/logs/ubuntu-published-install.log
|
|
install_status=$?
|
|
set -e
|
|
devtools/ci-flake-phase.sh end \
|
|
ubuntu-published-install custom "$install_status"
|
|
exit "$install_status"
|
|
|
|
- name: Upload publication failure evidence
|
|
if: >-
|
|
${{
|
|
failure() &&
|
|
(steps.published_metadata.outcome == 'failure' ||
|
|
steps.published_install.outcome == 'failure')
|
|
}}
|
|
uses: ./.github/actions/upload-flake-evidence
|
|
with:
|
|
job-name: Ubuntu 26.04 daily stable publication verification
|
|
|
|
report_failure:
|
|
name: report failure
|
|
needs:
|
|
- preflight
|
|
- build
|
|
- publish
|
|
- verify
|
|
if: >-
|
|
always() &&
|
|
github.event_name == 'schedule' &&
|
|
(contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled'))
|
|
runs-on: ubuntu-24.04
|
|
permissions:
|
|
issues: write
|
|
contents: read
|
|
steps:
|
|
- name: Create or update failure issue
|
|
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
env:
|
|
VERSION: ${{ needs.build.outputs.version }}
|
|
PREFLIGHT_RESULT: ${{ needs.preflight.result }}
|
|
BUILD_RESULT: ${{ needs.build.result }}
|
|
PUBLISH_RESULT: ${{ needs.publish.result }}
|
|
VERIFY_RESULT: ${{ needs.verify.result }}
|
|
with:
|
|
script: |
|
|
const version = process.env.VERSION || `run-${context.runId}`;
|
|
const title = '[ubuntu-daily-stable] package archive failure';
|
|
const body = [
|
|
`Automated Ubuntu daily stable failed for \`${version}\`.`,
|
|
'',
|
|
`Workflow run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
|
|
`Workflow commit: ${context.sha}`,
|
|
'',
|
|
'Job results:',
|
|
`- preflight: ${process.env.PREFLIGHT_RESULT}`,
|
|
`- build: ${process.env.BUILD_RESULT}`,
|
|
`- publish: ${process.env.PUBLISH_RESULT}`,
|
|
`- verify: ${process.env.VERIFY_RESULT}`,
|
|
'',
|
|
'Inspect the workflow artifacts and logs, then rerun the workflow manually after fixing the cause.'
|
|
].join('\n');
|
|
|
|
const {owner, repo} = context.repo;
|
|
const existing = await github.paginate(github.rest.issues.listForRepo, {
|
|
owner,
|
|
repo,
|
|
state: 'open',
|
|
per_page: 100
|
|
});
|
|
const issue = existing.find(item => item.title === title && !item.pull_request);
|
|
if (issue) {
|
|
await github.rest.issues.createComment({
|
|
owner,
|
|
repo,
|
|
issue_number: issue.number,
|
|
body
|
|
});
|
|
return;
|
|
}
|
|
|
|
const created = await github.rest.issues.create({
|
|
owner,
|
|
repo,
|
|
title,
|
|
body
|
|
});
|
|
try {
|
|
await github.rest.issues.addLabels({
|
|
owner,
|
|
repo,
|
|
issue_number: created.data.number,
|
|
labels: ['release', 'packaging', 'daily-stable', 'automated']
|
|
});
|
|
} catch (error) {
|
|
core.warning(`Could not add labels: ${error.message}`);
|
|
}
|