15 Commits
Author SHA1 Message Date
matthias 63c0599045 chore: replace Syft with Trivy for SBOM generation in build and release workflows
KIWI-NG Lint & Build / kiwi-job (push) Successful in 2m46s
KIWI-NG Release & Harvester Deployment / release (push) Successful in 2m40s
2026-08-16 11:33:18 +02:00
matthias a399cde4d2 chore: update syft SBOM output formats to spdx-json@2.2 and cyclonedx-json@1.6
KIWI-NG Lint & Build / kiwi-job (push) Successful in 2m59s
2026-08-16 10:48:42 +02:00
matthias 2ee4348598 feat: add CycloneDX SBOM generation to build and release workflows
KIWI-NG Lint & Build / kiwi-job (push) Successful in 2m58s
2026-08-16 10:38:37 +02:00
matthias d0c87455e5 feat: integrate Syft into build and release pipelines to generate and upload SPDX SBOMs
KIWI-NG Lint & Build / kiwi-job (push) Successful in 3m12s
2026-08-16 10:19:07 +02:00
matthias 3fec296130 .gitea/workflows/kiwi-release.yaml aktualisiert
KIWI-NG Lint & Build / kiwi-job (push) Successful in 2m50s
2026-08-16 07:51:27 +00:00
matthias be1780b3c0 .gitea/workflows/kiwi-release.yaml aktualisiert
KIWI-NG Lint & Build / kiwi-job (push) Successful in 3m13s
2026-08-14 20:13:54 +00:00
matthias b3475b403f refactor: remove locale and vconsole configuration to simplify image initialization
KIWI-NG Lint & Build / kiwi-job (push) Successful in 3m3s
KIWI-NG Release & Harvester Deployment / release (push) Successful in 2m45s
2026-08-07 03:31:42 +02:00
matthias 3bf7d6e238 refactor: update Harvester URL and variable syntax in release workflow and remove self-referencing path ignore in build workflow
KIWI-NG Lint & Build / kiwi-job (push) Successful in 2m58s
KIWI-NG Release & Harvester Deployment / release (push) Successful in 2m47s
2026-08-07 02:21:04 +02:00
matthias 9a27f209fa feat: add localization preferences and reorganize package definitions in Minimal.kiwi
KIWI-NG Lint & Build / kiwi-job (push) Successful in 3m0s
KIWI-NG Release & Harvester Deployment / release (push) Failing after 2m48s
2026-08-07 02:04:07 +02:00
matthias 8d9d4cc994 chore: update release workflow container image to bci/kiwi and remove device volume mount 2026-08-07 01:57:57 +02:00
matthias 01ba8caefa feat: add en_US locale to configuration and remove trailing comment character in config.sh
KIWI-NG Lint & Build / kiwi-job (push) Successful in 3m2s
KIWI-NG Release & Harvester Deployment / release (push) Failing after 20s
2026-08-07 01:48:39 +02:00
matthias c7afbd2465 chore: update checkout action, add commit SHA variable, and switch to alternative gitea-release action 2026-08-07 01:38:28 +02:00
matthias 6ea7fb1b99 .gitea/workflows/kiwi-release.yaml aktualisiert 2026-08-06 23:28:35 +00:00
matthias c9052cca59 feat: add Gitea workflow for automated image releases
KIWI-NG Lint & Build / kiwi-job (push) Successful in 2m58s
KIWI-NG Release & Harvester Deployment / release (push) Failing after 2s
2026-08-07 01:22:49 +02:00
matthias f1060caf62 refactor: update build workflow to use short SHA and add project documentation
KIWI-NG Lint & Build / kiwi-job (push) Successful in 3m1s
2026-08-07 01:04:34 +02:00
5 changed files with 230 additions and 46 deletions
+30 -25
View File
@@ -34,11 +34,19 @@ jobs:
zypper if python3-kiwi
echo "========================"
zypper --non-interactive in nodejs libxml2-tools git
zypper --non-interactive in nodejs libxml2-tools git curl
- name: Install Trivy
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
- name: Checkout Repository
uses: actions/checkout@v7
- name: Set Short SHA
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Lint XML Configuration
run: |
echo "Validating config.xml against RNG schema..."
@@ -56,31 +64,28 @@ jobs:
kiwi-ng result bundle \
--target-dir /tmp/build \
--bundle-dir ./dist \
--id gitea-build-${{ github.sha }}
--id gitea-build-${{ steps.vars.outputs.sha_short }}
- name: Upload Image Artifact
- name: Generate SBOM
run: |
trivy fs --format spdx-json --output ./dist/openSUSE-Leap-16.0-Minimal-gitea-build-${{ steps.vars.outputs.sha_short }}.spdx.json /tmp/build/build/image-root
trivy fs --format cyclonedx --output ./dist/openSUSE-Leap-16.0-Minimal-gitea-build-${{ steps.vars.outputs.sha_short }}.cdx.json /tmp/build/build/image-root
- name: Upload Disk Image
uses: actions/upload-artifact@v7
with:
name: kiwi-image-${{ github.sha }}
path: ./dist/
name: kiwi-disk-image-${{ steps.vars.outputs.sha_short }}
path: ./dist/*.qcow2 # oder *.raw.xz
retention-days: 7
# Step: Upload des gebauten KIWI-Images direkt in Harvester
- name: Upload Image to Harvester Cluster
env:
HARVESTER_URL: "https://harvester.ui" # Oder IP deines VIP/LoadBalancers
HARVESTER_TOKEN: ${{ secrets.HARVESTER_TOKEN }}
NAMESPACE: "default" # Ziel-Namespace in Harvester
IMAGE_NAME: "leap-16-minimal-${{ github.sha }}"
run: |
# 1. Pfad zur komprimierten Image-Datei ermitteln (z. B. .raw.xz oder .qcow2)
IMAGE_FILE=$(find ./dist -name "*.raw.xz" -o -name "*.qcow2" -o -name "*.raw" | head -n 1)
echo "Uploading $IMAGE_FILE to Harvester as $IMAGE_NAME..."
# 2. Upload per cURL an die Harvester Image Upload API
curl -k -f -X POST "${HARVESTER_URL}/v1/harvester/harvesterhci.io.virtualmachineimages/${NAMESPACE}/${IMAGE_NAME}?action=upload" \
-H "Authorization: Bearer ${HARVESTER_TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary "@${IMAGE_FILE}"
echo "Upload erfolgreich abgeschlossen!"
- name: Upload Build Manifests & Logs
uses: actions/upload-artifact@v7
with:
name: kiwi-build-manifests-${{ steps.vars.outputs.sha_short }}
path: |
./dist/*.packages
./dist/*.changes
./dist/*.verified
./dist/*.spdx.json
./dist/*.cdx.json
retention-days: 7
+85
View File
@@ -0,0 +1,85 @@
name: KIWI-NG Release & Harvester Deployment
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: kiwi-builder
container:
image: registry.opensuse.org/opensuse/bci/kiwi:10
options: --privileged
steps:
- name: Prepare environment
run: |
zypper --non-interactive in nodejs libxml2-tools git curl jq
- name: Install Trivy
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
- name: Checkout Repository
uses: actions/checkout@v7
- name: Set Short SHA
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Build Image for Release
run: |
kiwi-ng --profile Cloud system build --description ./opensuse-leap-16-minimal --target-dir /tmp/build
kiwi-ng result bundle --target-dir /tmp/build --bundle-dir ./dist --id ${{ github.ref_name }}
- name: Generate SBOM
run: |
trivy fs --format spdx-json --output ./dist/openSUSE-Leap-16.0-Minimal-${{ github.ref_name }}.spdx.json /tmp/build/build/image-root
trivy fs --format cyclonedx --output ./dist/openSUSE-Leap-16.0-Minimal-${{ github.ref_name }}.cdx.json /tmp/build/build/image-root
# 1. Gitea Release erstellen und Image-Datei als Asset anhängen
- name: Create Gitea Release
uses: akkuman/gitea-release-action@v1
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
body: "Official KIWI-NG Build for Tag ${{ github.ref_name }}"
draft: false
prerelease: false
files: |-
./dist/*.qcow2
./dist/*.raw.xz
./dist/*.spdx.json
./dist/*.cdx.json
# 2. Harvester triggern (zieht sich die Datei aus dem Release)
- name: Trigger Harvester Download
env:
HARVESTER_URL: ${{ secrets.HARVESTER_URL }}
HARVESTER_TOKEN: ${{ secrets.HARVESTER_TOKEN }}
NAMESPACE: "default"
run: |
IMAGE_FILENAME=$(basename $(find ./dist -name "*.qcow2" -o -name "*.raw" -o -name "*.raw.xz" | head -n 1))
DOWNLOAD_URL="${{ github.server_url }}/${{ github.repository }}/releases/download/${{ github.ref_name }}/${IMAGE_FILENAME}"
RESOURCE_NAME="leap-16-minimal-${{ github.ref_name }}"
RESOURCE_NAME=$(echo "$RESOURCE_NAME" | sed 's/\./-/g' | tr '[:upper:]' '[:lower:]')
curl -k -f -X POST "${HARVESTER_URL}/apis/harvesterhci.io/v1beta1/namespaces/${NAMESPACE}/virtualmachineimages" \
-H "Authorization: Bearer ${HARVESTER_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"apiVersion": "harvesterhci.io/v1beta1",
"kind": "VirtualMachineImage",
"metadata": {
"name": "'"${RESOURCE_NAME}"'",
"namespace": "'"${NAMESPACE}"'"
},
"spec": {
"displayName": "openSUSE-Leap-16.0-Minimal-${{ github.ref_name }}",
"description": "Gebaute KIWI-NG Vorlage aus Tag ${{ github.ref_name }}",
"sourceType": "download",
"url": "'"${DOWNLOAD_URL}"'"
}
}'
+102
View File
@@ -0,0 +1,102 @@
# KIWI Image Builder Configurations
Dieses Repository enthält Konfigurationen zur Erstellung von angepassten Betriebssystem-Images mit dem **KIWI Image Appliance Builder (KIWI-NG)**. Die fertigen Images werden automatisiert über eine CI/CD-Pipeline gebaut und direkt in ein Harvester-Cluster hochgeladen.
## Repository-Struktur
```text
├── .gitea/
│ └── workflows/
│ └── kiwi-build.yaml # Gitea Actions Workflow für Linting, Build und Deploy
├── opensuse-leap-16-minimal/
│ ├── Minimal.kiwi # KIWI-Bildbeschreibung (XML) mit Profilen und Paketen
│ └── config.sh # Konfigurationsskript für die Chroot-Phase des Builds
├── renovate.json # Konfiguration für den Renovate Bot
└── README.md # Dieses Dokument
```
---
## Enthaltene Images
### 1. openSUSE Leap 16.0 Minimal (`opensuse-leap-16-minimal`)
Dieses Verzeichnis enthält die Konfiguration für ein minimales openSUSE Leap 16.0 Image. Es stehen zwei Profile zur Verfügung:
| Profil | Zielplattform | Dateisystem | Format | Firmware | Besonderheiten |
| :--- | :--- | :--- | :--- | :--- | :--- |
| `kvm-and-xen` | KVM & Xen Hypervisoren | `btrfs` | `qcow2` | UEFI | Inklusive Snapper-Snapshots, Rollback-Helper, Firewalld und `jeos-firstboot` |
| `Cloud` (Default in CI) | Cloud-Umgebungen (z. B. Harvester) | `xfs` | `qcow2` | UEFI | Inklusive `cloud-init`, `qemu-guest-agent` und optimierter serieller Konsole |
#### Wichtige Voreinstellungen in `config.sh`:
- **Zeitzone & Keymap:** Standardmäßig auf `Europe/Zurich` und Tastaturlayout `us` konfiguriert.
- **Hostname:** Voreingestellt auf `rke2-node`.
- **Systemd Firstboot:** Die Datei `/etc/machine-id` wird auf `uninitialized` gesetzt, um systemd zu signalisieren, dass Firstboot-Presets ausgeführt werden sollen.
- **Dienste:** `sshd`, `NetworkManager` (falls vorhanden) und `chronyd` werden automatisch aktiviert.
- **Snapper (nur für `kvm-and-xen`):** Vorkonfiguriert ohne Timeline-Snapshots (`TIMELINE_CREATE="no"`) und mit optimierten Limits für automatische Aufräumarbeiten.
- **Speicheroptimierung:** Deaktivierung der Installation von Dokumentationen (`rpm.install.excludedocs = yes`) sowie Deaktivierung von empfohlenen Paketen (`solver.onlyRequires = true`) in `/etc/zypp/zypp.conf`.
---
## Lokales Bauen der Images
Um die Images lokal auf einem Linux-Host zu bauen, wird `kiwi-ng` benötigt.
### Voraussetzungen
1. Installiere KIWI-NG auf deinem Host-System:
```bash
# Auf openSUSE/SUSE
sudo zypper in python3-kiwi
```
2. Stelle sicher, dass Virtualisierungsunterstützung und KVM aktiviert sind (KIWI nutzt intern chroot und mountet loop devices).
### Build-Befehle
Führe den Build-Befehl im Root-Verzeichnis des Repositories aus:
#### KVM & Xen Profil (`btrfs`):
```bash
sudo kiwi-ng --profile kvm-and-xen system build \
--description ./opensuse-leap-16-minimal \
--target-dir ./build-kvm
```
#### Cloud Profil (`xfs`):
```bash
sudo kiwi-ng --profile Cloud system build \
--description ./opensuse-leap-16-minimal \
--target-dir ./build-cloud
```
Die fertigen `.qcow2`-Images und die Metadaten werden im angegebenen `--target-dir` abgelegt.
---
## CI/CD Pipeline (Gitea Actions)
Das Repository ist für Gitea Actions vorkonfiguriert (`.gitea/workflows/kiwi-build.yaml`). Der Workflow läuft auf einem Runner mit dem Label `kiwi-builder` und wird bei Pushes/Pull-Requests auf `main` oder `master` sowie bei Tag-Pushes mit dem Muster `v*` gestartet. Er führt folgende Schritte aus:
1. **RNG Schema-Validierung (Linting):**
Validiert die XML-Struktur von `Minimal.kiwi` gegen das offizielle KIWI-RNG-Schema (`kiwi.rng`), um Konfigurationsfehler vor dem Bauen zu vermeiden.
2. **Build:**
Baut das Image mit dem Profil `Cloud` im privilegierten Docker-Container (`registry.opensuse.org/opensuse/bci/kiwi:10`).
3. **Bundling:**
Paketiert die Ergebnisse und benennt sie passend zur kurzen Commit-SHA (Short-SHA).
4. **Upload Image Artifact:**
Archiviert das gebaute Image als Gitea-Artefakt mit der Short-SHA im Namen.
5. **Harvester-Upload:**
Lädt das fertige Image über die Harvester REST API direkt in den Ziel-Namespace des Harvester-Clusters hoch. Wenn die Pipeline durch einen Tag-Push gestartet wurde, entspricht der Image-Name dem Tag-Namen (z. B. `leap-16-minimal-v1.0.0`), ansonsten wird die Short-SHA verwendet.
6. **Gitea-Release-Erstellung (nur bei Tag-Pushes):**
Wenn der Push einen Git-Tag (z. B. `v1.0.0`) betrifft, wird automatisch ein Gitea-Release erstellt und das Image-File aus `./dist/*` als Release-Asset angehängt.
### Erforderliche Secrets für die Pipeline:
- `HARVESTER_TOKEN`: API-Token zur Authentifizierung am Harvester-Cluster.
Die Gitea-Release-Erstellung nutzt das standardmäßig bereitgestellte `GITHUB_TOKEN`. Die Cluster-URL für Harvester ist im Workflow als `https://harvester.ui` hinterlegt.
---
## Updates & Dependency Management
Dieses Repository verwendet **Renovate**, um Paketquellen, Basis-Images und GitHub-Aktionen automatisch auf dem neuesten Stand zu halten. Die Steuerung erfolgt über die Datei `renovate.json`.
+10 -9
View File
@@ -6,13 +6,18 @@
<contact>crc@suse.com</contact>
<specification>openSUSE Leap 16.0 Minimal</specification>
</description>
<profiles>
<profile name="kvm-and-xen" description="Minimal for KVM and Xen" arch="x86_64"/>
<profile name="Cloud" description="Minimal for Cloud" arch="aarch64,x86_64"/>
</profiles>
<preferences profiles="kvm-and-xen">
<version>16.0.0</version>
<packagemanager>zypper</packagemanager>
<locale>en_US</locale>
<keytable>us</keytable>
<timezone>Europe/Zurich</timezone>
<bootsplash-theme>openSUSE</bootsplash-theme>
<bootloader-theme>openSUSE</bootloader-theme>
<rpm-excludedocs>true</rpm-excludedocs>
@@ -32,9 +37,11 @@
<size unit="G">24</size>
</type>
</preferences>
<preferences profiles="Cloud">
<version>16.0.0</version>
<packagemanager>zypper</packagemanager>
<locale>en_US</locale>
<keytable>us</keytable>
<timezone>Europe/Zurich</timezone>
<bootsplash-theme>openSUSE</bootsplash-theme>
@@ -95,23 +102,17 @@
<package name="snapper"/>
<package name="jeos-firstboot"/>
<package name="firewalld"/>
<package name="grub2-snapper-plugin"/>
<package name="xen-tools-domU" arch="x86_64"/>
<package name="xen-libs" arch="x86_64"/>
</packages>
<packages type="image" profiles="kvm-and-xen,Cloud">
<package name="shim" arch="aarch64,x86_64"/>
<package name="grub2"/>
<package name="grub2-branding-openSUSE" arch="aarch64,x86_64"/>
<package name="grub2-arm64-efi" arch="aarch64"/>
<package name="grub2-s390x-emu" arch="s390x"/>
<package name="grub2-x86_64-efi" arch="x86_64"/>
<package name="patterns-base-bootloader"/>
<package name="grub2-powerpc-ieee1275" arch="ppc64le"/>
</packages>
<packages type="image" profiles="kvm-and-xen">
<package name="grub2-snapper-plugin"/>
<package name="xen-tools-domU" arch="x86_64"/>
<package name="xen-libs" arch="x86_64"/>
</packages>
<packages type="image" profiles="kvm-and-xen,Cloud">
<package name="kernel-default-base"/>
<package name="qemu-guest-agent"/>
</packages>
+3 -12
View File
@@ -18,7 +18,7 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#======================================
# Functions...
#--------------------------------------
@@ -64,19 +64,10 @@ baseSetRunlevel 3
#--------------------------------------
suseImportBuildKey
# 1. Alle Locale-Variablen (inkl. LC_MESSAGES) vollständig setzen
cat <<'EOF' > /etc/locale.conf
LANG=en_US.UTF-8
LC_MESSAGES=en_US.UTF-8
LC_ALL=en_US.UTF-8
EOF
# 2. Keymap und Hostname vordefinieren
echo "KEYMAP=us" > /etc/vconsole.conf
# 1. Hostname vordefinieren
echo "rke2-node" > /etc/hostname
ln -sf /usr/share/zoneinfo/Europe/Zurich /etc/localtime
# 3. Der entscheidende Trick für systemd: "Preset" als initialisiert markieren
# 2. Der entscheidende Trick für systemd: "Preset" als initialisiert markieren
# Eine leere /etc/machine-id ODER /etc/machine-info signalisiert systemd,
# dass Firstboot bereits gelaufen ist.
echo "uninitialized" > /etc/machine-id