Files
Gleb Chesnokov dc506a0474 .github/workflows: Select PR checks by changed paths
Pull requests that only change development guides or independent tooling
still compile kernels and run the VM suites. Select Ginkgo, KUnit, Clang
and kernel regression through one shared path policy before expensive
work. Compare the whole PR against its merge base, retaining deleted
paths and both sides of renames. Run checks for unclassified inputs.

Keep path rules in .github/ci-checks.toml and validate their structure,
check names, literal paths and conflicting entries before selection.
Provide a validation-only command. Changes to the config or selector
exercise every check.

Select kernel regression once in the preparation job and gate the build
job before expanding its matrix. Unrelated PRs do not allocate a runner
for every kernel. Selection failures fail the workflow and successful
skips include a reason in the job summary.

Run the Packages workflow only after pushes to master, preserving its
DEB/RPM builds and publication. Keep the separate Clang DEB build on PRs.
Retain full master and manual checks and the existing Checkpatch runs.
Cover path ownership, config validation and Git histories with tests,
and shorten the CI guide around all workflows, selection and results.

Quote the CC environment key so Checkpatch does not interpret unchanged
YAML diff context as a Cc trailer.
2026-10-19 13:44:33 +03:00

296 lines
9.0 KiB
YAML

name: Packages
on:
push:
branches:
- master
permissions:
contents: read
env:
WERROR: 'y'
jobs:
prepare_matrix:
name: Prepare RPM matrix
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
outputs:
rpm: ${{ steps.matrix.outputs.rpm }}
steps:
- name: Checkout code
uses: actions/checkout@main
- name: Resolve RPM matrix
id: matrix
shell: bash
run: |
matrix="$(bash scripts/kernel/kernel-matrix rpm)"
printf 'rpm=%s\n' "${matrix}" >>"${GITHUB_OUTPUT}"
build_rpm:
name: ${{ matrix.name }} x86_64
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
needs: prepare_matrix
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare_matrix.outputs.rpm) }}
steps:
- name: Checkout code
uses: actions/checkout@main
with:
fetch-depth: 0
- name: Build RPM packages
run: |
make docker-rpm \
DOCKER_RPM_TARGET=${{ matrix.target }} \
DOCKER_RPM_BASE_IMAGE=${{ matrix.base_image }} \
DOCKER_RPM_KERNEL_PACKAGE=${{ matrix.kernel_package }} \
DOCKER_RPM_KERNEL_VERSION=${{ matrix.kernel_version }} \
DOCKER_RPM_KERNEL_REPOSITORY=${{ matrix.kernel_repository }}
- name: Upload RPM packages
uses: actions/upload-artifact@main
with:
name: scst-rpm-${{ matrix.target }}-x86_64-${{ github.sha }}
path: |
docker-rpmbuilddir/${{ matrix.target }}/RPMS/**/*.rpm
docker-rpmbuilddir/${{ matrix.target }}/SRPMS/*.rpm
docker-rpmbuilddir/${{ matrix.target }}/SHA256SUMS
if-no-files-found: error
build_deb:
name: Ubuntu ${{ matrix.ubuntu }} DKMS and user space x86_64
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ubuntu: ['20.04', '24.04']
container:
image: ubuntu:${{ matrix.ubuntu }}
env:
DEBIAN_FRONTEND: noninteractive
defaults:
run:
shell: bash
steps:
- name: Install build dependencies
run: |
apt-get update
apt-get install -y \
build-essential \
ca-certificates \
debhelper \
devscripts \
dpkg-dev \
git \
libelf-dev \
lintian \
linux-headers-generic \
openssl \
quilt
- name: Checkout code
uses: actions/checkout@main
with:
fetch-depth: 0
- name: Configure Git safe directory
run: git config --global --add safe.directory "${GITHUB_WORKSPACE}"
- name: Build DEB packages
run: |
mapfile -t kernel_dirs < <(
find /usr/src -maxdepth 1 -type d \
-name 'linux-headers-*-generic' -print | sort -V
)
if [[ ${#kernel_dirs[@]} -ne 1 ]]; then
echo "Expected one generic kernel header tree, found ${#kernel_dirs[@]}." >&2
exit 1
fi
kernel_dir="${kernel_dirs[0]}"
kernel_release="${kernel_dir##*/linux-headers-}"
if [[ ! -f "${kernel_dir}/.config" ]]; then
echo "Missing kernel configuration: ${kernel_dir}/.config" >&2
exit 1
fi
install -D -m 0644 "${kernel_dir}/.config" \
"/boot/config-${kernel_release}"
make KDIR="${kernel_dir}" KVER="${kernel_release}" dpkg
- name: Verify published DEB set
shell: bash
run: |
set -euo pipefail
patterns=(
'dpkg/scst-dkms_*.deb'
'dpkg/scstadmin_*.deb'
'dpkg/iscsi-scst_*.deb'
'dpkg/*.dsc'
'dpkg/*.debian.tar.*'
'dpkg/*.orig.tar.*'
)
for pattern in "${patterns[@]}"; do
mapfile -t matches < <(compgen -G "${pattern}" || true)
if [[ ${#matches[@]} -ne 1 ]]; then
echo "Expected one package matching ${pattern}, found ${#matches[@]}." >&2
exit 1
fi
done
- name: Upload DEB packages
uses: actions/upload-artifact@main
with:
name: scst-deb-ubuntu-${{ matrix.ubuntu }}-x86_64-${{ github.sha }}
path: |
dpkg/scst-dkms_*.deb
dpkg/scstadmin_*.deb
dpkg/iscsi-scst_*.deb
dpkg/*.dsc
dpkg/*.debian.tar.*
dpkg/*.orig.tar.*
if-no-files-found: error
publish_master:
name: Publish master package snapshot
if: >-
github.event_name == 'push' &&
github.ref == 'refs/heads/master' &&
github.repository == 'SCST-project/scst'
needs: [prepare_matrix, build_rpm, build_deb]
runs-on: ubuntu-latest
permissions:
actions: read
contents: write
concurrency:
group: packages-master-release
cancel-in-progress: false
steps:
- name: Checkout code
uses: actions/checkout@main
- name: Download RPM packages
uses: actions/download-artifact@main
with:
pattern: scst-rpm-*-x86_64-${{ github.sha }}
path: package-artifacts/rpm
- name: Download DEB packages
uses: actions/download-artifact@main
with:
pattern: scst-deb-ubuntu-*-x86_64-${{ github.sha }}
path: package-artifacts/deb
- name: Prepare release assets
env:
RPM_MATRIX: ${{ needs.prepare_matrix.outputs.rpm }}
RELEASE_OUTPUT_DIR: ${{ runner.temp }}/master-package-release
run: bash scripts/release/prepare-package-release
- name: Publish rolling master snapshot
env:
GH_TOKEN: ${{ github.token }}
RELEASE_OUTPUT_DIR: ${{ runner.temp }}/master-package-release
shell: bash
run: |
set -euo pipefail
readonly tag=master-rpm
get_master_sha() {
gh api "repos/${GITHUB_REPOSITORY}/git/ref/heads/master" \
--jq '.object.sha'
}
delete_tag_releases() {
local release_ids release_id
release_ids="$(
gh api --paginate \
"repos/${GITHUB_REPOSITORY}/releases?per_page=100" \
--jq '.[] | select(.tag_name == "master-rpm") | .id'
)"
while IFS= read -r release_id; do
[[ -n "${release_id}" ]] || continue
gh api --method DELETE \
"repos/${GITHUB_REPOSITORY}/releases/${release_id}"
done <<<"${release_ids}"
}
delete_release_tag() {
local tag_status
tag_status="$(
curl --silent --show-error --output /dev/null \
--write-out '%{http_code}' \
--header 'Accept: application/vnd.github+json' \
--header "Authorization: Bearer ${GH_TOKEN}" \
--header 'X-GitHub-Api-Version: 2022-11-28' \
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/git/ref/tags/${tag}"
)"
case "${tag_status}" in
200)
gh api --method DELETE \
"repos/${GITHUB_REPOSITORY}/git/refs/tags/${tag}"
;;
404) ;;
*)
echo "Unable to inspect ${tag} (HTTP ${tag_status})." >&2
return 1
;;
esac
}
master_sha="$(get_master_sha)"
if [[ "${master_sha}" != "${GITHUB_SHA}" ]]; then
echo "Skipping stale package snapshot for ${GITHUB_SHA}."
exit 0
fi
delete_tag_releases
delete_release_tag
shopt -s nullglob
assets=("${RELEASE_OUTPUT_DIR}"/scst-master-*)
[[ ${#assets[@]} -gt 0 ]] || {
echo 'No release assets were prepared.' >&2
exit 1
}
notes="$(printf '%s\n\n%s\n%s\n' \
'Automated development package snapshot from the master branch.' \
"Commit: ${GITHUB_SHA}" \
"Workflow: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}")"
gh release create "${tag}" "${assets[@]}" \
--target "${GITHUB_SHA}" \
--title 'Latest master package snapshot' \
--notes "${notes}" \
--prerelease \
--latest=false \
--draft
master_sha="$(get_master_sha)"
if [[ "${master_sha}" != "${GITHUB_SHA}" ]]; then
echo "Discarding stale package snapshot for ${GITHUB_SHA}."
delete_tag_releases
delete_release_tag
exit 0
fi
gh release edit "${tag}" \
--draft=false \
--prerelease \
--latest=false
master_sha="$(get_master_sha)"
if [[ "${master_sha}" != "${GITHUB_SHA}" ]]; then
echo "Removing stale package snapshot for ${GITHUB_SHA}."
delete_tag_releases
delete_release_tag
fi