Skip to content

feat(suse): add SLES15 rpm/container build target - #1152

Open
djshah19 wants to merge 15 commits into
project-dalec:mainfrom
djshah19:user/dhwanishah/suse-target
Open

feat(suse): add SLES15 rpm/container build target#1152
djshah19 wants to merge 15 commits into
project-dalec:mainfrom
djshah19:user/dhwanishah/suse-target

Conversation

@djshah19

@djshah19 djshah19 commented Jul 20, 2026

Copy link
Copy Markdown

Add SUSE Linux Enterprise 15 as a new rpm distro target built with zypper.

  • suse/sles15.go, suse/common.go: ConfigSLES15 distro config (bci-base:15.7 worker, zypper installer, /etc/zypp/repos.d repo layout, native-arch only)
  • distro/zypper_install.go: ZypperInstall installer reusing the shared dnfInstallConfig plumbing (--non-interactive, key import, no --releasever)
  • distro.go/worker.go: CrossArchInstallUnsupported flag; worker paths fail fast for SUSE since zypper lacks dnf's --forcearch/--installroot
  • plugin/init.go: register sles15 routes
  • test/target_suse_test.go: TestSLES15 with SUSE helpers (no %{?dist} tag, createrepo_c/zypp repo dir, rpmsign via rpm-build)
  • docs: add sles15 to targets.md and examples/targets.md

Copilot-Session: 89d10fb5-5e8e-4819-84f8-f0a96dc28fcd

What this PR does / why we need it:

This PR adds SUSE Linux Enterprise 15 (SLES 15) as a first-class rpm build target
(sles15/rpm, sles15/container, sles15/worker, sles15/container/depsonly), so
dalec specs can produce and package rpms for SLES the same way they already do for
azlinux, almalinux, and rockylinux. SLES is a widely deployed enterprise Linux that
consumers of dalec need to ship packages for, and it was previously unsupported.

The main difference from the existing rpm targets is the package manager: SLES uses
zypper/libzypp, not dnf. Rather than fork the rpm build path, this PR reuses the
shared dnfInstallConfig plumbing and adds a zypper-specific install step:

  • Distro config (suse/sles15.go, suse/common.go): ConfigSLES15 pins the
    registry.suse.com/bci/bci-base worker, wires up the zypper installer, and uses
    SUSE's repo layout (/etc/zypp/repos.d).
  • Installer (distro/zypper_install.go): ZypperInstall runs zypper with
    --non-interactive and license/vendor flags, imports repo signing keys, and omits
    dnf-only concepts such as --releasever. Documentation exclusion (the default, since
    IncludeDocs is false) is handled via libzypp's rpm.install.excludedocs in
    zypp.conf — zypper has no CLI flag equivalent to dnf's --setopt=tsflags=nodocs.
  • Native-arch-only guard (distro/distro.go, distro/worker.go): zypper has no
    equivalent of dnf's --forcearch/--installroot, so cross-architecture installs are
    not supported. A new CrossArchInstallUnsupported flag makes the worker paths fail
    fast for SLES instead of producing a broken foreign-arch rootfs.
  • Registration (plugin/init.go): registers the sles15/* build routes.
  • Tests (test/target_suse_test.go): TestSLES15 exercises the target through the
    shared linux test harness, with SUSE-specific helpers that account for SLES quirks —
    an empty %{?dist} tag (unlike el9/azl3), repo creation with createrepo_c, and
    package signing with rpmsign (shipped in rpm-build, not a separate rpm-sign
    package).
  • Docs: adds sles15 to website/docs/targets.md and examples/targets.md.

Which issue(s) this PR fixes (optional, using fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when the PR gets merged):
Fixes #

Special notes for your reviewer:

  • Worker base image is pinned to bci-base:15.7 (not 15.6). SLES 15 SP6 (15.6)
    reached end of general support on 2025-12-31, so builds start from the currently
    maintained 15.7 BCI. Bumping the tag also requires updating the expected OS release
    (VersionID) in the test config.
  • Cross-architecture builds are intentionally unsupported. zypper cannot install
    into a foreign-arch root, so ConfigSLES15 sets CrossArchInstallUnsupported: true
    and the worker fails fast rather than silently producing a wrong-arch image. The SLES
    target is therefore validated on its native architecture only.
  • Doc exclusion via zypp.conf, not a CLI flag. An earlier revision passed
    --rpm-installexcludedocs, which is not a valid zypper 1.14 option and failed every
    install; this now sets rpm.install.excludedocs = yes in zypp.conf (honoring
    --root) when docs are excluded, matching the dnf targets' tsflags=nodocs behavior.
  • The diff also includes an in-flight merge with main, so some unrelated upstream
    changes (e.g. the worker-resolution test refactor in platform_worker_test.go, the
    GomodEdits Drop field, and dependency bumps) appear in the file list. The
    SUSE-specific changes are the suse/, zypper_install.go, distro.go/worker.go,
    plugin/init.go, target_suse_test.go, and docs entries listed above.

Copilot AI review requested due to automatic review settings July 20, 2026 21:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a native-architecture SLES 15 RPM and container target using zypper.

Changes:

  • Adds SLES configuration, routes, and zypper installation support.
  • Rejects unsupported cross-architecture worker builds.
  • Adds integration coverage and target documentation.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
website/docs/targets.md Documents the SLES target.
website/docs/examples/targets.md Lists generated SLES routes.
test/target_suse_test.go Adds SLES integration tests.
targets/plugin/init.go Registers SLES routes.
targets/linux/rpm/suse/sles15.go Defines the SLES 15 configuration.
targets/linux/rpm/suse/common.go Defines SUSE packages and repositories.
targets/linux/rpm/distro/zypper_install.go Implements zypper installation.
targets/linux/rpm/distro/worker.go Rejects unsupported cross-architecture builds.
targets/linux/rpm/distro/distro.go Adds the cross-architecture capability flag.

Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
Comment thread targets/linux/rpm/suse/sles15.go Outdated
Comment thread test/target_suse_test.go Outdated
@invidian
invidian requested a review from cpuguy83 July 21, 2026 07:52

@invidian invidian left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits, otherwise LGTM. Perhaps @cpuguy83 would also like to have a look, since I might be missing stuff.

Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
Comment thread targets/linux/rpm/distro/zypper_install.go Outdated

@invidian invidian left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure changes to matrix.json file are missing, generated by go generate ./....

And DCO. I also wonder why CI hasn't kicked in...

@netlify

netlify Bot commented Jul 22, 2026

Copy link
Copy Markdown

Deploy Preview for dalec ready!

Name Link
🔨 Latest commit 00809dd
🔍 Latest deploy log https://app.netlify.com/projects/dalec/deploys/6a63f1e0a221c60008bc1e5d
😎 Deploy Preview https://deploy-preview-1152--dalec.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@djshah19

Copy link
Copy Markdown
Author

Some nits, otherwise LGTM. Perhaps @cpuguy83 would also like to have a look, since I might be missing stuff.

@invidian Thanks for taking a look. I addressed your comments. Could you please review again? Thanks

Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
@djshah19
djshah19 force-pushed the user/dhwanishah/suse-target branch 2 times, most recently from 071e394 to 5e90c7f Compare July 22, 2026 15:29
@cpuguy83

Copy link
Copy Markdown
Collaborator

It seems like this needs a rebase? There's a bunch of content that was already merged in the diff.

djshah19 and others added 6 commits July 22, 2026 09:12
Add SUSE Linux Enterprise 15 as a new rpm distro target built with zypper.

- suse/sles15.go, suse/common.go: ConfigSLES15 distro config (bci-base:15.6
  worker, zypper installer, /etc/zypp/repos.d repo layout, native-arch only)
- distro/zypper_install.go: ZypperInstall installer reusing the shared
  dnfInstallConfig plumbing (--non-interactive, key import, no --releasever)
- distro.go/worker.go: CrossArchInstallUnsupported flag; worker paths fail
  fast for SUSE since zypper lacks dnf's --forcearch/--installroot
- plugin/init.go: register sles15 routes
- test/target_suse_test.go: TestSLES15 with SUSE helpers (no %{?dist} tag,
  createrepo_c/zypp repo dir, rpmsign via rpm-build)
- docs: add sles15 to targets.md and examples/targets.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d10fb5-5e8e-4819-84f8-f0a96dc28fcd
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
…flag

The '--rpm-installexcludedocs' argument is not a valid zypper option; zypper
rejects it as unknown and fails the install before any package is laid down.
Since includeDocs defaults to false, this broke every SLES15 install.

Replace it with the libzypp-native mechanism: set 'rpm.install.excludedocs = yes'
in zypp.conf (honoring --root) for the invocation when docs should be excluded,
preserving parity with the dnf targets' --setopt=tsflags=nodocs behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d10fb5-5e8e-4819-84f8-f0a96dc28fcd
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
SLES 15 SP6 (bci-base:15.6) reached end of general support on 2025-12-31,
so builds would start from a base without regular public security
maintenance. Move the base worker image to the currently-supported 15.7
BCI and update the expected OS release VersionID accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d10fb5-5e8e-4819-84f8-f0a96dc28fcd
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
testTargetPlatform selects any platform different from the BuildKit worker's
native platform. On an arm64 runner it would pick amd64 for the SUSE target
and expect a successful cross-architecture build -- but SUSE sets
CrossArchInstallUnsupported and fails fast, so the generic success path would
spuriously fail.

Add a CrossArchUnsupported test setting: when set, the cross-platform subtest
skips the generic success case and instead asserts the worker guard's
'cross-architecture builds are not supported' error. Enable it for SLES15.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d10fb5-5e8e-4819-84f8-f0a96dc28fcd
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
@djshah19
djshah19 force-pushed the user/dhwanishah/suse-target branch from c1805e3 to 2f48787 Compare July 22, 2026 16:15
@djshah19

Copy link
Copy Markdown
Author

It seems like this needs a rebase? There's a bunch of content that was already merged in the diff.

I had rebased my branch it got polluted white fixing DCO, but I rebased again

Comment thread targets/linux/rpm/distro/worker.go Outdated
@cpuguy83

Copy link
Copy Markdown
Collaborator

It looks like the CI workflow also needs to have sles15 added to the integration suite (sorry, this does't have a go generate yet).

djshah19 added 2 commits July 22, 2026 09:43
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
@cpuguy83 cpuguy83 added this to the v0.22 milestone Jul 22, 2026
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Comment thread packaging/linux/rpm/template.go Outdated
Comment thread packaging/linux/rpm/template.go Outdated
Comment thread targets/linux/rpm/distro/distro.go Outdated
Comment thread targets/linux/rpm/distro/worker.go Outdated
Comment thread targets/linux/rpm/distro/worker.go Outdated
Comment thread test/target_suse_test.go Outdated
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Comment thread packaging/linux/rpm/template.go Outdated
Comment thread packaging/linux/rpm/template.go Outdated
Comment thread test/linux_target_test.go Outdated
if err := validatePathAndPermissions(ctx, ref, "/usr/libexec/no_name_no_subpath", 0o755); err != nil {
// %{_libexecdir} is distro-dependent: dnf-based distros (and Tumbleweed)
// use /usr/libexec, while openSUSE Leap / SLE 15 use /usr/lib.
libexecDir := testConfig.LibexecDir

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe flip the logic so we use more common value as default and then optionally override with specific, rather than other way around?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It already defaults to the common /usr/libexec (empty → /usr/libexec); only SLE15/Leap overrides to /usr/lib. Can switch to a UsesFHSLibexec bool if you prefer that shape.

// packages, not part of coreutils).
"system-user-root": {},
"system-user-nobody": {},
"coreutils": {},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot for base runtime dependencies. All our other distros only define tzdata and ca-certificates as default runtime dependencies, since we aim to produce as small images as possible.

Also, standalone binaries and containers actually rarely actually depend on shell utilities, so that doesn't seem like a right selection.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for size — SUSE builds from llb.Scratch() (no bci-base underneath), so this is the minimal userland. Without system-user-nobody/grep, the artifacts and disable_strip tests fail. azlinux gets the same set for free via distroless-packages-minimal; SUSE ships no equivalent meta-package. Open to layering on bci-base instead if you prefer.

File: &dalec.SourceInlineFile{
Permissions: 0o644,
Contents: `NAME="SLES"
VERSION="15-SP7"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this could be pulled somehow from worker image while bootstrapping an image to avoid keeping an explicit copy here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could extract /etc/os-release from the worker image during bootstrap instead of inlining — happy to switch if you prefer that over the hardcoded copy.

Permissions: 0o644,
Contents: `NAME="SLES"
VERSION="15-SP7"
VERSION_ID="15.7"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if we decide to keep it, it should probably be part of targets/linux/rpm/suse/sles15.go?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — if we keep it, I will move it into sles15.go next to the other SLES15-specific config.

Comment thread targets/linux/rpm/distro/zypper_install.go
Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
Comment thread targets/linux/rpm/distro/zypper_install.go Outdated
djshah19 added 2 commits July 24, 2026 16:07
Signed-off-by: Dhwani Shah <dhwanishah@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants