commit 398e91bb2d6bc185e76a08b495d632caf8ac6dc5 Author: magges Date: Sun Jun 21 13:39:54 2026 +0200 Initial release diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..1831744 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,192 @@ +name: build-mesa-git + +on: + push: + branches: + - main + schedule: + - cron: "0 3 */3 * *" + workflow_dispatch: + +permissions: + contents: write + +jobs: + build-deb: + runs-on: ubuntu-latest + container: + image: debian:trixie + steps: + - name: Install build dependencies + run: | + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + bindgen \ + ca-certificates \ + cbindgen \ + cmake \ + curl \ + dpkg-dev \ + file \ + git \ + glslang-tools \ + meson \ + ninja-build \ + pkg-config \ + cargo \ + python3 \ + python3-mako \ + python3-ply \ + python3-yaml \ + rustc \ + bison \ + flex \ + gettext \ + libdisplay-info-dev \ + libdrm-dev \ + libelf-dev \ + libexpat1-dev \ + libgbm-dev \ + libglvnd-dev \ + libgles2-mesa-dev \ + libclc-19 \ + libclc-19-dev \ + libllvmspirvlib-19-dev \ + libpciaccess-dev \ + libva-dev \ + libudev-dev \ + libvulkan-dev \ + libwayland-dev \ + libwayland-egl-backend-dev \ + libx11-dev \ + libx11-xcb-dev \ + libxcb-dri2-0-dev \ + libxcb-dri3-dev \ + libxcb-glx0-dev \ + libxcb-keysyms1-dev \ + libxcb-present-dev \ + libxcb-randr0-dev \ + libxcb-shm0-dev \ + libxcb-sync-dev \ + libxcb-xfixes0-dev \ + libxcb1-dev \ + libxdamage-dev \ + libxext-dev \ + libxfixes-dev \ + libxrandr-dev \ + libxrender-dev \ + libxshmfence-dev \ + libxxf86vm-dev \ + libzstd-dev \ + llvm-dev \ + wayland-protocols \ + xz-utils \ + zlib1g-dev + - name: Checkout repository + run: | + git init . + git config --global --add safe.directory "$PWD" + git remote add origin "${{ gitea.server_url }}/${{ gitea.repository }}.git" + git -c http.extraHeader="Authorization: token ${{ secrets.GITEA_TOKEN }}" fetch --depth 1 origin "${{ gitea.sha }}" + git checkout --detach FETCH_HEAD + - name: Build mesa-git package + env: + MESA_UPSTREAM_REF: main + run: | + chmod +x scripts/build-mesa-opt.sh + ./scripts/build-mesa-opt.sh + - name: Generate release notes + env: + GITEA_SERVER_URL: ${{ gitea.server_url }} + GITEA_REPOSITORY: ${{ gitea.repository }} + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + . dist/package-info.env + chmod +x scripts/generate-release-notes.sh + RELEASE_TAG="${PACKAGE_NAME}-${PACKAGE_VERSION}" ./scripts/generate-release-notes.sh + - name: Generate apt repository + run: | + chmod +x scripts/generate-apt-repo.sh + ./scripts/generate-apt-repo.sh + - name: Upload deb package to Gitea release + run: | + . dist/package-info.env + RELEASE_TAG="${PACKAGE_NAME}-${PACKAGE_VERSION}" + RELEASE_TAG_URL="$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$RELEASE_TAG")" + PACKAGE_FILE_URL="$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$PACKAGE_FILE")" + RELEASE_API="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/releases" + + HTTP_CODE="$(curl -s -o /tmp/release.json -w '%{http_code}' \ + -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \ + "${RELEASE_API}/tags/${RELEASE_TAG_URL}")" + + if [ "$HTTP_CODE" = "200" ]; then + RELEASE_ID="$(python3 -c 'import json; print(json.load(open("/tmp/release.json"))["id"])')" + python3 -c 'import json, pathlib, sys; pathlib.Path("/tmp/release-update.json").write_text(json.dumps({ + "tag_name": sys.argv[1], + "target_commitish": sys.argv[2], + "name": sys.argv[1], + "body": pathlib.Path("dist/release-notes.md").read_text(), + "draft": False, + "prerelease": False, + }))' "$RELEASE_TAG" "$GITEA_SHA" + curl --fail-with-body \ + -X PATCH \ + -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \ + -H "Content-Type: application/json" \ + --data-binary @/tmp/release-update.json \ + "${RELEASE_API}/${RELEASE_ID}" > /tmp/release.json + elif [ "$HTTP_CODE" = "404" ]; then + python3 -c 'import json, pathlib, sys; pathlib.Path("/tmp/release-create.json").write_text(json.dumps({ + "tag_name": sys.argv[1], + "target_commitish": sys.argv[2], + "name": sys.argv[1], + "body": pathlib.Path("dist/release-notes.md").read_text(), + "draft": False, + "prerelease": False, + }))' "$RELEASE_TAG" "$GITEA_SHA" + curl --fail-with-body \ + -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \ + -H "Content-Type: application/json" \ + --data-binary @/tmp/release-create.json \ + "${RELEASE_API}" > /tmp/release.json + RELEASE_ID="$(python3 -c 'import json; print(json.load(open("/tmp/release.json"))["id"])')" + else + cat /tmp/release.json + exit 1 + fi + + curl --fail-with-body \ + -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \ + --data-binary @"dist/${PACKAGE_FILE}" \ + "${RELEASE_API}/${RELEASE_ID}/assets?name=${PACKAGE_FILE_URL}" + - name: Publish apt repository branch + run: | + APT_BRANCH="apt" + APT_WORKTREE="/tmp/apt-branch" + + rm -rf "${APT_WORKTREE}" + git init "${APT_WORKTREE}" + git -C "${APT_WORKTREE}" config user.name "gitea-actions" + git -C "${APT_WORKTREE}" config user.email "actions@local" + git -C "${APT_WORKTREE}" remote add origin "${{ gitea.server_url }}/${{ gitea.repository }}.git" + + if git -C "${APT_WORKTREE}" -c http.extraHeader="Authorization: token ${{ secrets.GITEA_TOKEN }}" fetch --depth 1 origin "${APT_BRANCH}"; then + git -C "${APT_WORKTREE}" checkout -B "${APT_BRANCH}" FETCH_HEAD + else + git -C "${APT_WORKTREE}" checkout --orphan "${APT_BRANCH}" + fi + + find "${APT_WORKTREE}" -mindepth 1 -maxdepth 1 ! -name .git -exec rm -rf {} + + cp -a dist/aptrepo/. "${APT_WORKTREE}/" + + git -C "${APT_WORKTREE}" add . + if git -C "${APT_WORKTREE}" diff --cached --quiet; then + echo "apt repository branch already up to date" + else + git -C "${APT_WORKTREE}" commit -m "Publish apt repository for ${GITEA_SHA}" + git -C "${APT_WORKTREE}" -c http.extraHeader="Authorization: token ${{ secrets.GITEA_TOKEN }}" push --force origin "${APT_BRANCH}" + fi + env: + GITEA_SHA: ${{ gitea.sha }} diff --git a/README.md b/README.md new file mode 100644 index 0000000..92c06c0 --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +# mesa-repo + +Dieses Repo baut per Gitea Actions ein eigenstaendiges `mesa-git`-Paket als `.deb`. +Das Paket installiert Mesa separat unter `/opt/mesa-git`, damit es parallel zur +System-Mesa genutzt werden kann. + +## Was gebaut wird + +- Paketname: `mesa-git` +- Installationspfad: `/opt/mesa-git` +- Wrapper: `/usr/bin/mesa-git-env` +- Ausgabe: `mesa-git__amd64.deb` + +## Build-Profil + +Standardmaessig baut das Repo Mesa mit beiden Plattformen: + +- `x11` +- `wayland` + +Und mit diesem Treiberprofil: + +- AMD: `radeonsi`, `r300`, `r600` +- Intel: `iris`, `crocus` +- NVIDIA nouveau: `nouveau` +- Fallback: `zink`, `llvmpipe`, `softpipe` +- Vulkan: `amd`, `intel`, `intel_hasvk`, `nouveau`, `swrast` + +Zusammen mit einem aktuellen `libdrm`-Snapshot, damit neue Mesa-Staende nicht an +zu alten Distributionspaketen scheitern. + +## Ablauf + +1. Gitea Actions startet auf dem `act_runner`. +2. `scripts/build-mesa-opt.sh` klont `libdrm` und Mesa direkt von Upstream. +3. `libdrm` wird zuerst gebaut und in das spaetere Prefix vorbereitet. +4. Mesa wird danach mit Meson/Ninja gebaut. +5. Das Ergebnis wird als `.deb` paketiert. +6. Ein Gitea Release wird erstellt oder aktualisiert. +7. Das `.deb` wird als Release-Asset hochgeladen. +8. Die Release-Notes werden automatisch aus der Mesa-Upstream-History erzeugt. +9. Ein apt-kompatibler Repo-Baum wird auf den Branch `apt` veroeffentlicht. + +## Release-Notes + +Die Release-Notes werden automatisch erzeugt und enthalten: + +- den verwendeten Mesa-Upstream-Commit +- das gebaute Paket +- die Mesa-Commits seit dem vorherigen `mesa-git`-Release + +Wenn kein vorheriger passender Release-Vergleich gefunden wird, nutzt der Workflow +als Fallback die juengsten Upstream-Commits. + +## Trigger + +Der Workflow laeuft bei: + +- Push auf `main` +- manuellem Start per `workflow_dispatch` +- automatischem Zeitplan alle 3 Tage + +Releases werden als normale Releases angelegt, nicht als Pre-Releases. + +## APT-Einbindung + +Der Workflow veroeffentlicht zusaetzlich einen einfachen Debian-Repo-Baum auf +dem Branch `apt`. + +Die Einbindung ist dann ueber die Raw-URL des Branches moeglich, zum Beispiel: + +```text +deb [trusted=yes] https://git.mp-mueller.de/magges/mesa-repo/raw/branch/apt stable main +``` + +Danach: + +```bash +sudo apt update +sudo apt install mesa-git +``` + +Hinweis: + +- das Repo ist aktuell unsigniert +- fuer APT wird deshalb hier `trusted=yes` verwendet +- wenn du willst, kann ich als naechsten Schritt auch noch Release-Signierung mit GPG einbauen + +## Wichtige Dateien + +- `config/mesa-opt.conf`: Paketname, Prefix, Plattformen und Treiberprofil +- `scripts/build-mesa-opt.sh`: Build und Paketierung +- `scripts/generate-release-notes.sh`: automatische Release-Notes aus Mesa-Commits +- `scripts/generate-apt-repo.sh`: erzeugt den APT-Repo-Baum +- `.gitea/workflows/build.yml`: Gitea-Workflow + +## Benutzung + +Nach der Installation kann das Paket ueber den Wrapper genutzt werden: + +```bash +mesa-git-env glxinfo +mesa-git-env vkcube +``` + +Der Wrapper setzt die noetigen Mesa-Pfade fuer `LD_LIBRARY_PATH`, +`LIBGL_DRIVERS_PATH`, `VK_LAYER_PATH` und `VK_ICD_FILENAMES`. + +## Lokaler Test + +Mit installierten Build-Abhaengigkeiten: + +```bash +./scripts/build-mesa-opt.sh +``` + +## Anpassen + +Die wichtigsten Schalter liegen in `config/mesa-opt.conf`: + +- `UPSTREAM_GIT_REF` +- `INSTALL_PREFIX` +- `PLATFORMS` +- `GALLIUM_DRIVERS` +- `VULKAN_DRIVERS` +- `VULKAN_LAYERS` diff --git a/config/mesa-opt.conf b/config/mesa-opt.conf new file mode 100644 index 0000000..23ae7d8 --- /dev/null +++ b/config/mesa-opt.conf @@ -0,0 +1,18 @@ +PACKAGE_NAME="mesa-git" +PACKAGE_VERSION_PREFIX="" +PACKAGE_RELEASE="1" +PACKAGE_ARCH="amd64" + +UPSTREAM_GIT_URL="https://gitlab.freedesktop.org/mesa/mesa.git" +UPSTREAM_GIT_REF="main" +LIBDRM_GIT_URL="https://gitlab.freedesktop.org/mesa/drm.git" +LIBDRM_GIT_REF="main" + +INSTALL_PREFIX="/opt/mesa-git" +BUILD_TYPE="release" +PLATFORMS="x11,wayland" + +# Broad desktop profile: AMD, Intel, NVIDIA nouveau plus software fallback. +GALLIUM_DRIVERS="radeonsi,r300,r600,iris,crocus,nouveau,zink,llvmpipe,softpipe" +VULKAN_DRIVERS="amd,intel,intel_hasvk,nouveau,swrast" +VULKAN_LAYERS="device-select,overlay" diff --git a/scripts/build-mesa-opt.sh b/scripts/build-mesa-opt.sh new file mode 100644 index 0000000..dde727b --- /dev/null +++ b/scripts/build-mesa-opt.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +ROOT_DIR=$(cd -- "${SCRIPT_DIR}/.." && pwd) +CONFIG_FILE="${ROOT_DIR}/config/mesa-opt.conf" + +if [[ ! -f "${CONFIG_FILE}" ]]; then + echo "missing config: ${CONFIG_FILE}" >&2 + exit 1 +fi + +# shellcheck disable=SC1090 +source "${CONFIG_FILE}" + +require_cmd() { + local cmd + for cmd in "$@"; do + command -v "${cmd}" >/dev/null 2>&1 || { + echo "missing command: ${cmd}" >&2 + exit 1 + } + done +} + +require_cmd dpkg-deb git meson ninja python3 + +WORK_DIR="${ROOT_DIR}/work" +LIBDRM_SRC_DIR="${WORK_DIR}/libdrm" +LIBDRM_BUILD_DIR="${WORK_DIR}/build-libdrm" +SRC_DIR="${WORK_DIR}/mesa" +BUILD_DIR="${WORK_DIR}/build" +PKG_DIR="${WORK_DIR}/pkg" +PREREQ_DIR="${WORK_DIR}/prereq" +DIST_DIR="${ROOT_DIR}/dist" + +mkdir -p "${WORK_DIR}" "${DIST_DIR}" +rm -rf "${LIBDRM_SRC_DIR}" "${LIBDRM_BUILD_DIR}" "${SRC_DIR}" "${BUILD_DIR}" "${PKG_DIR}" "${PREREQ_DIR}" +mkdir -p "${PKG_DIR}" + +UPSTREAM_REF="${MESA_UPSTREAM_REF:-${UPSTREAM_GIT_REF}}" +LIBDRM_REF="${LIBDRM_UPSTREAM_REF:-${LIBDRM_GIT_REF}}" + +git clone --depth 1 --branch "${LIBDRM_REF}" "${LIBDRM_GIT_URL}" "${LIBDRM_SRC_DIR}" + +meson setup "${LIBDRM_BUILD_DIR}" "${LIBDRM_SRC_DIR}" \ + --buildtype="${BUILD_TYPE}" \ + --prefix="${INSTALL_PREFIX}" + +ninja -C "${LIBDRM_BUILD_DIR}" +DESTDIR="${PREREQ_DIR}" ninja -C "${LIBDRM_BUILD_DIR}" install + +# Debian's xf86drm.h includes , while newer libdrm installs it below +# include/libdrm/. Mirror the headers into the prefix root so Mesa finds them. +if [[ -d "${PREREQ_DIR}${INSTALL_PREFIX}/include/libdrm" ]]; then + ln -sf libdrm/drm.h "${PREREQ_DIR}${INSTALL_PREFIX}/include/drm.h" + ln -sf libdrm/drm_mode.h "${PREREQ_DIR}${INSTALL_PREFIX}/include/drm_mode.h" + ln -sf libdrm/libsync.h "${PREREQ_DIR}${INSTALL_PREFIX}/include/libsync.h" +fi + +# libdrm's pkg-config metadata points to the real prefix path. Mirror the staged +# files there during the Mesa build so compiler and linker can resolve them. +mkdir -p "${INSTALL_PREFIX}" +cp -a "${PREREQ_DIR}${INSTALL_PREFIX}/." "${INSTALL_PREFIX}/" + +export PKG_CONFIG_PATH="${PREREQ_DIR}${INSTALL_PREFIX}/lib/x86_64-linux-gnu/pkgconfig:${PREREQ_DIR}${INSTALL_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH:-}" +export LD_LIBRARY_PATH="${PREREQ_DIR}${INSTALL_PREFIX}/lib/x86_64-linux-gnu:${PREREQ_DIR}${INSTALL_PREFIX}/lib:${LD_LIBRARY_PATH:-}" + +git clone --depth 1 --branch "${UPSTREAM_REF}" "${UPSTREAM_GIT_URL}" "${SRC_DIR}" + +detect_upstream_version() { + local source_dir="${1}" + + if [[ -f "${source_dir}/VERSION" ]]; then + sed -n '1p' "${source_dir}/VERSION" + return + fi + + awk -F"'" '/project\(/ { for (i = 1; i <= NF; ++i) if ($i ~ /^[0-9][0-9A-Za-z.+~:-]*$/) { print $i; exit } }' \ + "${source_dir}/meson.build" +} + +GIT_SHA=$(git -C "${SRC_DIR}" rev-parse --short=12 HEAD) +GIT_SHA_FULL=$(git -C "${SRC_DIR}" rev-parse HEAD) +UPSTREAM_VERSION="${PACKAGE_VERSION_PREFIX:-$(detect_upstream_version "${SRC_DIR}")}" +UPSTREAM_SERIES="$(printf '%s' "${UPSTREAM_VERSION}" | sed -E 's/^([0-9]+\.[0-9]+).*/\1/')" +PACKAGE_VERSION="${UPSTREAM_SERIES}+git${GIT_SHA}-${PACKAGE_RELEASE}" +OUTPUT_DEB="${DIST_DIR}/${PACKAGE_NAME}_${PACKAGE_VERSION}_${PACKAGE_ARCH}.deb" + +meson setup "${BUILD_DIR}" "${SRC_DIR}" \ + --buildtype="${BUILD_TYPE}" \ + --prefix="${INSTALL_PREFIX}" \ + -Dplatforms="${PLATFORMS}" \ + -Dgallium-drivers="${GALLIUM_DRIVERS}" \ + -Dvulkan-drivers="${VULKAN_DRIVERS}" \ + -Dvulkan-layers="${VULKAN_LAYERS}" \ + -Dglx=dri \ + -Dllvm=enabled \ + -Dshared-glapi=enabled + +ninja -C "${BUILD_DIR}" +cp -a "${PREREQ_DIR}/." "${PKG_DIR}/" +DESTDIR="${PKG_DIR}" ninja -C "${BUILD_DIR}" install + +mkdir -p \ + "${PKG_DIR}/DEBIAN" \ + "${PKG_DIR}/usr/share/doc/${PACKAGE_NAME}" \ + "${PKG_DIR}/usr/bin" + +cat > "${PKG_DIR}/DEBIAN/control" < +Depends: libc6, libexpat1, libgcc-s1, libgl1, libllvm${LLVM_RUNTIME_VERSION:-19}, libstdc++6, libvulkan1, libwayland-client0, libx11-6, zlib1g +Description: Mesa snapshot build installed below ${INSTALL_PREFIX} + Built from ${UPSTREAM_GIT_URL} (${UPSTREAM_REF}) with bundled libdrm from + ${LIBDRM_GIT_URL} (${LIBDRM_REF}) and installed into ${INSTALL_PREFIX}. +EOF + +cat > "${PKG_DIR}/usr/share/doc/${PACKAGE_NAME}/README.Debian" < "${PKG_DIR}/usr/bin/${PACKAGE_NAME}-env" < "${DIST_DIR}/package-info.env" <&2 + exit 1 +fi + +# shellcheck disable=SC1090 +source "${DIST_ENV}" + +require_cmd() { + local cmd + for cmd in "$@"; do + command -v "${cmd}" >/dev/null 2>&1 || { + echo "missing command: ${cmd}" >&2 + exit 1 + } + done +} + +require_cmd dpkg-scanpackages gzip md5sum sha256sum sha512sum stat date + +PACKAGE_ARCH="$(dpkg-deb -f "${DIST_DIR}/${PACKAGE_FILE}" Architecture)" + +APT_SUITE="${APT_SUITE:-stable}" +APT_COMPONENT="${APT_COMPONENT:-main}" +APT_ARCH="${APT_ARCH:-${PACKAGE_ARCH}}" +APT_ORIGIN="${APT_ORIGIN:-mesa-git}" +APT_LABEL="${APT_LABEL:-mesa-git}" +APT_DESCRIPTION="${APT_DESCRIPTION:-Mesa git apt repository}" + +POOL_DIR="${APT_DIR}/pool/${APT_COMPONENT}/m/${PACKAGE_NAME}" +BINARY_DIR="${APT_DIR}/dists/${APT_SUITE}/${APT_COMPONENT}/binary-${APT_ARCH}" +PACKAGE_PATH="${POOL_DIR}/${PACKAGE_FILE}" + +rm -rf "${APT_DIR}" +mkdir -p "${POOL_DIR}" "${BINARY_DIR}" + +cp "${DIST_DIR}/${PACKAGE_FILE}" "${PACKAGE_PATH}" + +( + cd "${APT_DIR}" + dpkg-scanpackages --arch "${APT_ARCH}" "pool" > "${BINARY_DIR#${APT_DIR}/}/Packages" +) + +gzip -kf "${BINARY_DIR}/Packages" + +cat > "${APT_DIR}/dists/${APT_SUITE}/Release" <> "${release_file}" + + while IFS= read -r -d '' file; do + rel_path="${file#${rel_dir}/}" + sum="$(${checksum_cmd} "${file}" | awk '{print $1}')" + size="$(stat -c '%s' "${file}")" + printf ' %s %16s %s\n' "${sum}" "${size}" "${rel_path}" >> "${release_file}" + done < <(find "${rel_dir}" -type f ! -name Release -print0 | sort -z) +} + +append_checksum_block "MD5Sum" md5sum +append_checksum_block "SHA256" sha256sum +append_checksum_block "SHA512" sha512sum diff --git a/scripts/generate-release-notes.sh b/scripts/generate-release-notes.sh new file mode 100644 index 0000000..4656fe9 --- /dev/null +++ b/scripts/generate-release-notes.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +ROOT_DIR=$(cd -- "${SCRIPT_DIR}/.." && pwd) +DIST_ENV="${ROOT_DIR}/dist/package-info.env" +MESA_SRC_DIR="${ROOT_DIR}/work/mesa" + +if [[ ! -f "${DIST_ENV}" ]]; then + echo "missing dist metadata: ${DIST_ENV}" >&2 + exit 1 +fi + +if [[ ! -d "${MESA_SRC_DIR}/.git" ]]; then + echo "missing mesa source checkout: ${MESA_SRC_DIR}" >&2 + exit 1 +fi + +# shellcheck disable=SC1090 +source "${DIST_ENV}" + +require_env() { + local name + for name in "$@"; do + if [[ -z "${!name:-}" ]]; then + echo "missing environment variable: ${name}" >&2 + exit 1 + fi + done +} + +require_env GITEA_SERVER_URL GITEA_REPOSITORY GITEA_TOKEN RELEASE_TAG + +RELEASES_JSON="$(curl -fsS \ + -H "Authorization: token ${GITEA_TOKEN}" \ + "${GITEA_SERVER_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases?limit=20")" + +PREVIOUS_SHA="$( + python3 - "${RELEASES_JSON}" "${RELEASE_TAG}" "${PACKAGE_NAME}" <<'PY' +import json +import re +import sys + +releases = json.loads(sys.argv[1]) +current_tag = sys.argv[2] +package_name = sys.argv[3] +pattern = re.compile(rf"^{re.escape(package_name)}-.*\+git([0-9a-f]{{12}})-") + +for release in releases: + tag = release.get("tag_name", "") + if tag == current_tag: + continue + match = pattern.match(tag) + if match: + print(match.group(1)) + break +PY +)" + +COMMITS_TRUNCATED=0 +COMMIT_LIMIT=50 + +if [[ -n "${PREVIOUS_SHA}" ]] && git -C "${MESA_SRC_DIR}" rev-parse --verify --quiet "${PREVIOUS_SHA}^{commit}" >/dev/null; then + COMPARE_RANGE="${PREVIOUS_SHA}..${UPSTREAM_GIT_SHA}" + mapfile -t COMMITS < <(git -C "${MESA_SRC_DIR}" log --no-merges --format='- %h %s' "${COMPARE_RANGE}") + RANGE_LABEL="Changes since \`${PREVIOUS_SHA}\`" +else + COMPARE_RANGE="${UPSTREAM_GIT_SHA}" + mapfile -t COMMITS < <(git -C "${MESA_SRC_DIR}" log --no-merges -n "${COMMIT_LIMIT}" --format='- %h %s' "${COMPARE_RANGE}") + RANGE_LABEL="Recent upstream commits" +fi + +if (( ${#COMMITS[@]} > COMMIT_LIMIT )); then + COMMITS=( "${COMMITS[@]:0:${COMMIT_LIMIT}}" ) + COMMITS_TRUNCATED=1 +fi + +{ + printf '## Mesa Upstream\n\n' + printf -- '- Upstream: `%s`\n' "${UPSTREAM_GIT_URL}" + printf -- '- Ref: `%s`\n' "${UPSTREAM_GIT_REF}" + printf -- '- Commit: `%s`\n' "${UPSTREAM_GIT_SHA_SHORT}" + printf -- '- Package: `%s`\n\n' "${PACKAGE_FILE}" + printf '## %s\n\n' "${RANGE_LABEL}" + + if (( ${#COMMITS[@]} == 0 )); then + printf -- '- No new upstream commits found for this release.\n' + else + printf '%s\n' "${COMMITS[@]}" + fi + + if (( COMMITS_TRUNCATED == 1 )); then + printf '\n_Release notes truncated to the first %d commits._\n' "${COMMIT_LIMIT}" + fi +} > "${ROOT_DIR}/dist/release-notes.md"