Adding gitea workflow
Build Fedora x86_64-v3 RPMs (Gitea) / prepare (push) Successful in 4s
Build Fedora x86_64-v3 RPMs (Gitea) / build (push) Failing after 6s

This commit is contained in:
2026-04-17 23:10:47 -04:00
parent 7de21c42ce
commit bdb2ea2eb4
3 changed files with 190 additions and 346 deletions
-343
View File
@@ -1,343 +0,0 @@
name: Build Fedora RPMs
on:
workflow_dispatch:
inputs:
package_kind:
description: "Interpret package_input as source or binary package names"
required: true
default: "source"
type: choice
options:
- source
- binary
package_input:
description: "Comma, space, or newline separated package list. Leave blank to use the full manifest."
required: false
default: ""
type: string
source_manifest:
description: "Checked-in source manifest path"
required: true
default: "manifests/fedora-43/source-packages.txt"
type: string
source_map:
description: "Checked-in binary to source map path"
required: true
default: "manifests/fedora-43/source-map.tsv"
type: string
fedora_branch:
description: "Fedora dist-git branch"
required: true
default: "f43"
type: string
fedora_release:
description: "Fedora container release"
required: true
default: "43"
type: string
builder_image:
description: "Prebuilt Fedora RPM builder image reference"
required: true
default: "ghcr.io/dawsonc/kde-x86_64-v4-fedora-builder:f43"
type: string
optimization_level:
description: "Compiler optimization level"
required: true
default: "-O3"
type: choice
options:
- -O2
- -O3
target_march:
description: "Target march override"
required: true
default: "x86-64-v4"
type: string
permissions:
contents: read
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.select.outputs.matrix }}
package_count: ${{ steps.select.outputs.package_count }}
shard_count: ${{ steps.select.outputs.shard_count }}
steps:
- uses: actions/checkout@v4
- id: select
env:
PACKAGE_KIND: ${{ inputs.package_kind }}
PACKAGE_INPUT: ${{ inputs.package_input }}
SOURCE_MANIFEST: ${{ inputs.source_manifest }}
SOURCE_MAP: ${{ inputs.source_map }}
run: |
python3 <<'PY'
import json
import os
import re
from pathlib import Path
source_manifest = Path(os.environ["SOURCE_MANIFEST"])
source_map_path = Path(os.environ["SOURCE_MAP"])
requested_source_map_path = source_map_path
package_kind = os.environ["PACKAGE_KIND"].strip()
package_input = os.environ["PACKAGE_INPUT"]
if not source_manifest.exists():
raise SystemExit(f"Source manifest not found: {source_manifest}")
if not source_map_path.exists() and source_map_path.name == "binary-map.tsv":
compatibility_path = source_map_path.with_name("source-map.tsv")
if compatibility_path.exists():
source_map_path = compatibility_path
if not source_map_path.exists():
raise SystemExit(
f"Source map not found: {requested_source_map_path}. "
f"Expected an existing TSV such as {requested_source_map_path.with_name('source-map.tsv')}"
)
source_packages = [
line.strip()
for line in source_manifest.read_text(encoding="ascii").splitlines()
if line.strip()
]
binary_to_source = {}
for line in source_map_path.read_text(encoding="ascii").splitlines():
if not line.strip():
continue
binary_name, source_name = line.split("\t", 1)
binary_to_source[binary_name] = source_name
def tokenize(raw: str):
parts = re.split(r"[\s,]+", raw.strip())
return [part for part in parts if part]
if package_input.strip():
selected = tokenize(package_input)
else:
selected = source_packages
if package_kind == "binary":
mapped = []
missing = []
for binary_name in selected:
source_name = binary_to_source.get(binary_name)
if source_name is None:
missing.append(binary_name)
else:
mapped.append(source_name)
if missing:
raise SystemExit(
"Missing binary-to-source mappings for: " + ", ".join(sorted(missing))
)
selected = mapped
deduped = []
seen = set()
for package_name in selected:
if package_name not in seen:
seen.add(package_name)
deduped.append(package_name)
max_matrix = 256
if not deduped:
matrix = []
else:
shard_size = max(1, -(-len(deduped) // max_matrix))
shards = [
deduped[index:index + shard_size]
for index in range(0, len(deduped), shard_size)
]
matrix = [
{
"shard": shard_index + 1,
"packages": shard,
"package_count": len(shard),
}
for shard_index, shard in enumerate(shards)
]
github_output = Path(os.environ["GITHUB_OUTPUT"])
with github_output.open("a", encoding="utf-8") as fh:
fh.write(f"matrix={json.dumps(matrix)}\n")
fh.write(f"package_count={len(deduped)}\n")
fh.write(f"shard_count={len(matrix)}\n")
PY
- name: Summarize selection
run: |
echo "Selected packages: ${{ steps.select.outputs.package_count }}" >> "$GITHUB_STEP_SUMMARY"
echo "Shards: ${{ steps.select.outputs.shard_count }}" >> "$GITHUB_STEP_SUMMARY"
echo '${{ steps.select.outputs.matrix }}' >> "$GITHUB_STEP_SUMMARY"
build:
needs: prepare
if: ${{ needs.prepare.outputs.package_count != '0' }}
runs-on: ubuntu-latest
container:
image: ${{ inputs.builder_image }}
strategy:
fail-fast: false
max-parallel: 128
matrix:
include: ${{ fromJSON(needs.prepare.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Cache Fedora DNF data
uses: actions/cache@v4
with:
path: |
/var/cache/dnf
/var/lib/dnf
key: dnf-fedora-${{ inputs.fedora_release }}
restore-keys: |
dnf-fedora-${{ inputs.fedora_release }}-
- name: Verify builder toolchain
run: |
command -v dnf
command -v fedpkg
command -v rpmbuild
command -v git
command -v node
command -v gcc
command -v g-ir-scanner
command -v gi-docgen
rpm -q rpm-build rpmdevtools dnf-plugins-core
- name: Build shard packages
env:
SHARD_INDEX: ${{ matrix.shard }}
PACKAGES_JSON: ${{ toJSON(matrix.packages) }}
FEDORA_BRANCH: ${{ inputs.fedora_branch }}
OPT_LEVEL: ${{ inputs.optimization_level }}
TARGET_MARCH: ${{ inputs.target_march }}
run: |
python3 <<'PY'
import json
import os
import shutil
import subprocess
from pathlib import Path
workspace = Path(os.environ["GITHUB_WORKSPACE"])
shard_index = int(os.environ["SHARD_INDEX"])
packages = json.loads(os.environ["PACKAGES_JSON"])
fedora_branch = os.environ["FEDORA_BRANCH"]
opt_level = os.environ["OPT_LEVEL"]
target_march = os.environ["TARGET_MARCH"]
optflags_override = (
f"{opt_level} -flto=auto -ffat-lto-objects -fexceptions -g "
"-grecord-gcc-switches -pipe -Wall -Wno-complain-wrong-lang "
"-Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 "
"-Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 "
"-fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 "
f"-m64 -march={target_march} -mtune=generic -fasynchronous-unwind-tables "
"-fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 "
"-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
)
shard_root = workspace / "artifacts" / f"shard-{shard_index:03d}"
shard_root.mkdir(parents=True, exist_ok=True)
rpmbuild_root = workspace / ".rpmbuild"
rpmbuild_root.mkdir(parents=True, exist_ok=True)
for package_name in packages:
package_dir = workspace / package_name
if package_dir.exists():
shutil.rmtree(package_dir)
subprocess.run(
[
"git",
"clone",
"--depth",
"1",
"--branch",
fedora_branch,
f"https://src.fedoraproject.org/rpms/{package_name}.git",
str(package_dir),
],
check=True,
)
subprocess.run(["fedpkg", "sources"], cwd=package_dir, check=True)
spec_file = next(package_dir.glob("*.spec"), None)
if spec_file is None:
raise SystemExit(f"No spec file found for {package_name}")
subprocess.run(
[
"dnf",
"-y",
"builddep",
"--setopt=keepcache=1",
"--setopt=skip_if_unavailable=True",
str(spec_file),
],
cwd=package_dir,
check=True,
)
topdir = rpmbuild_root / package_name
for subdir in ("BUILD", "BUILDROOT", "RPMS", "SOURCES", "SPECS", "SRPMS"):
(topdir / subdir).mkdir(parents=True, exist_ok=True)
subprocess.run(
[
"rpmbuild",
"-ba",
str(spec_file),
"--define",
f"optflags {optflags_override}",
"--define",
f"_topdir {topdir}",
"--define",
f"_builddir {topdir / 'BUILD'}",
"--define",
f"_buildrootdir {topdir / 'BUILDROOT'}",
"--define",
f"_rpmdir {topdir / 'RPMS'}",
"--define",
f"_srcrpmdir {topdir / 'SRPMS'}",
"--define",
f"_sourcedir {package_dir}",
"--define",
f"_specdir {package_dir}",
],
cwd=package_dir,
check=True,
)
outdir = shard_root / package_name
outdir.mkdir(parents=True, exist_ok=True)
for rpm_path in (topdir / "RPMS").rglob("*.rpm"):
shutil.copy2(rpm_path, outdir / rpm_path.name)
for src_path in (topdir / "SRPMS").rglob("*.src.rpm"):
shutil.copy2(src_path, outdir / src_path.name)
print(f"Built {package_name}")
PY
- name: Collect artifacts
env:
SHARD_INDEX: ${{ matrix.shard }}
run: |
SHARD_LABEL=$(printf "%03d" "${SHARD_INDEX}")
OUTDIR="${GITHUB_WORKSPACE}/artifacts/shard-${SHARD_LABEL}"
ls -la "${OUTDIR}"
- name: Upload RPM artifacts
uses: actions/upload-artifact@v4
with:
name: rpm-shard-${{ format('{0:03}', matrix.shard) }}
path: artifacts/shard-${{ format('{0:03}', matrix.shard) }}/
if-no-files-found: error
- name: Append build summary
if: always()
env:
SHARD_INDEX: ${{ matrix.shard }}
run: |
SHARD_LABEL=$(printf "%03d" "${SHARD_INDEX}")
echo "### shard-${SHARD_LABEL}" >> "$GITHUB_STEP_SUMMARY"
if [ -d "artifacts/shard-${SHARD_LABEL}" ]; then
find "artifacts/shard-${SHARD_LABEL}" -maxdepth 2 -type f | sort >> "$GITHUB_STEP_SUMMARY"
else
echo "No artifacts collected." >> "$GITHUB_STEP_SUMMARY"
fi
+183
View File
@@ -0,0 +1,183 @@
name: Build Fedora x86_64-v3 RPMs (Gitea)
on:
workflow_dispatch:
push:
paths:
- 'packages.txt'
- '.gitea/workflows/build-v3-rpms.yml'
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.select.outputs.matrix }}
package_count: ${{ steps.select.outputs.package_count }}
steps:
- uses: actions/checkout@v4
- id: select
run: |
python3 <<'PY'
import json
import os
from pathlib import Path
packages_file = Path("packages.txt")
if not packages_file.exists():
print("::error::packages.txt not found")
exit(1)
packages = [
line.strip()
for line in packages_file.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.startswith("#")
]
# Gitea Actions might have different limits, but 256 is generally safe for matrix
max_matrix = 256
matrix = []
if packages:
shard_size = max(1, -(-len(packages) // max_matrix))
shards = [
packages[index:index + shard_size]
for index in range(0, len(packages), shard_size)
]
matrix = [
{
"shard": shard_index + 1,
"shard_label": f"{shard_index + 1:03d}",
"packages": shard,
}
for shard_index, shard in enumerate(shards)
]
# Gitea Actions supports GITHUB_OUTPUT
output_file = os.environ.get("GITHUB_OUTPUT")
if output_file:
with open(output_file, "a") as fh:
fh.write(f"matrix={json.dumps(matrix)}\n")
fh.write(f"package_count={len(packages)}\n")
else:
print(f"::set-output name=matrix::{json.dumps(matrix)}")
print(f"::set-output name=package_count::{len(packages)}")
PY
build:
needs: prepare
if: ${{ needs.prepare.outputs.package_count != '0' }}
runs-on: ubuntu-latest
container:
image: fedora:43
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.prepare.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Install build tools
run: |
dnf -y install 'dnf-command(builddep)' fedpkg rpm-build rpmdevtools git python3
- name: Build shard packages
env:
SHARD_INDEX: ${{ matrix.shard }}
PACKAGES_JSON: ${{ toJSON(matrix.packages) }}
FEDORA_BRANCH: f43
TARGET_MARCH: x86-64-v3
run: |
python3 <<'PY'
import json
import os
import shutil
import subprocess
import time
from pathlib import Path
workspace = Path(os.environ.get("GITHUB_WORKSPACE", "."))
shard_index = int(os.environ["SHARD_INDEX"])
packages = json.loads(os.environ["PACKAGES_JSON"])
fedora_branch = os.environ["FEDORA_BRANCH"]
target_march = os.environ["TARGET_MARCH"]
# Standard Fedora optflags with march override
optflags_override = (
f"-O2 -flto=auto -ffat-lto-objects -fexceptions -g "
"-grecord-gcc-switches -pipe -Wall -Werror=format-security "
"-Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 "
"-Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 "
"-fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 "
f"-m64 -march={target_march} -mtune=generic -fasynchronous-unwind-tables "
"-fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 "
"-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
)
shard_root = workspace / "artifacts" / f"shard-{shard_index:03d}"
shard_root.mkdir(parents=True, exist_ok=True)
rpmbuild_root = workspace / ".rpmbuild"
rpmbuild_root.mkdir(parents=True, exist_ok=True)
def run_with_retry(command, *, cwd=None, cleanup_path=None, attempts=3):
for attempt in range(1, attempts + 1):
if cleanup_path is not None and cleanup_path.exists():
shutil.rmtree(cleanup_path)
try:
subprocess.run(command, cwd=cwd, check=True)
return
except subprocess.CalledProcessError:
if attempt == attempts:
raise
time.sleep(5 * attempt)
for package_name in packages:
package_dir = workspace / package_name
run_with_retry(
[
"git", "clone", "--depth", "1", "--branch", fedora_branch,
f"https://src.fedoraproject.org/rpms/{package_name}.git",
str(package_dir),
],
cleanup_path=package_dir,
)
run_with_retry(["fedpkg", "sources"], cwd=package_dir)
spec_file = next(package_dir.glob("*.spec"), None)
if not spec_file:
print(f"No spec file for {package_name}")
continue
subprocess.run(["dnf", "-y", "builddep", str(spec_file)], check=True)
topdir = rpmbuild_root / package_name
for subdir in ("BUILD", "BUILDROOT", "RPMS", "SOURCES", "SPECS", "SRPMS"):
(topdir / subdir).mkdir(parents=True, exist_ok=True)
subprocess.run(
[
"rpmbuild", "-ba", str(spec_file),
"--define", f"optflags {optflags_override}",
"--define", f"_topdir {topdir}",
"--define", f"_builddir {topdir / 'BUILD'}",
"--define", f"_buildrootdir {topdir / 'BUILDROOT'}",
"--define", f"_rpmdir {topdir / 'RPMS'}",
"--define", f"_srcrpmdir {topdir / 'SRPMS'}",
"--define", f"_sourcedir {package_dir}",
"--define", f"_specdir {package_dir}",
],
check=True,
)
for rpm_path in (topdir / "RPMS").rglob("*.rpm"):
shutil.copy2(rpm_path, shard_root / rpm_path.name)
for src_path in (topdir / "SRPMS").rglob("*.src.rpm"):
shutil.copy2(src_path, shard_root / src_path.name)
print(f"Built {package_name}")
PY
- name: Upload RPM artifacts
uses: actions/upload-artifact@v4
with:
name: rpm-shard-${{ matrix.shard_label }}
path: artifacts/shard-${{ matrix.shard_label }}/
if-no-files-found: error
+7 -3
View File
@@ -1,5 +1,9 @@
# Fedora 43 KDE GitHub Actions RPM Builder # Fedora 43 KDE Actions RPM Builder
This repository is a static GitHub Actions input repo for rebuilding Fedora 43 This repository provides CI workflows for both GitHub Actions and Gitea Actions to rebuild Fedora 43
KDE packages from Fedora dist-git with `x86-64-v3` code generation and `-O3` KDE packages from Fedora dist-git with `x86-64-v3` code generation and `-O3`
optimization. optimization.
## Workflows
- **GitHub Actions**: `.github/workflows/build-v3-rpms.yml`
- **Gitea Actions**: `.gitea/workflows/build-v3-rpms.yml`