@@ -10,6 +10,7 @@ import (
1010 "errors"
1111 "fmt"
1212 "log/slog"
13+ "net/url"
1314 "os"
1415 "os/exec"
1516 "path/filepath"
@@ -58,28 +59,38 @@ type Runner struct {
5859
5960 // localRepoPaths are paths to local RPM repositories to include during build.
6061 localRepoPaths []string
62+
63+ // remoteRepoPaths are URIs to remote RPM repositories (http:// or https://) to include during build.
64+ remoteRepoPaths []string
65+
66+ // remoteRepoGPGCheck controls whether GPG checking is enabled for remote repositories.
67+ // Defaults to true.
68+ remoteRepoGPGCheck bool
6169}
6270
6371// NewRunner constructs a new [Runner] that can be used to invoke kiwi-ng.
6472// The descriptionDir is the directory containing the kiwi description file (e.g., config.xml).
6573func NewRunner (ctx opctx.Ctx , descriptionDir string ) * Runner {
6674 return & Runner {
67- fs : ctx .FS (),
68- cmdFactory : ctx ,
69- verbose : ctx .Verbose (),
70- descriptionDir : descriptionDir ,
75+ fs : ctx .FS (),
76+ cmdFactory : ctx ,
77+ verbose : ctx .Verbose (),
78+ descriptionDir : descriptionDir ,
79+ remoteRepoGPGCheck : true , // GPG checking enabled by default
7180 }
7281}
7382
7483// Clone creates a deep copy of the provided [Runner] instance.
7584func (r * Runner ) Clone () * Runner {
7685 return & Runner {
77- fs : r .fs ,
78- cmdFactory : r .cmdFactory ,
79- verbose : r .verbose ,
80- descriptionDir : r .descriptionDir ,
81- targetDir : r .targetDir ,
82- localRepoPaths : deep .MustCopy (r .localRepoPaths ),
86+ fs : r .fs ,
87+ cmdFactory : r .cmdFactory ,
88+ verbose : r .verbose ,
89+ descriptionDir : r .descriptionDir ,
90+ targetDir : r .targetDir ,
91+ localRepoPaths : deep .MustCopy (r .localRepoPaths ),
92+ remoteRepoPaths : deep .MustCopy (r .remoteRepoPaths ),
93+ remoteRepoGPGCheck : r .remoteRepoGPGCheck ,
8394 }
8495}
8596
@@ -90,6 +101,19 @@ func (r *Runner) WithTargetDir(targetDir string) *Runner {
90101 return r
91102}
92103
104+ // WithRemoteRepoGPGCheck sets whether GPG checking is enabled for remote repositories.
105+ // By default, GPG checking is enabled.
106+ func (r * Runner ) WithRemoteRepoGPGCheck (enabled bool ) * Runner {
107+ r .remoteRepoGPGCheck = enabled
108+
109+ return r
110+ }
111+
112+ // RemoteRepoGPGCheck returns whether GPG checking is enabled for remote repositories.
113+ func (r * Runner ) RemoteRepoGPGCheck () bool {
114+ return r .remoteRepoGPGCheck
115+ }
116+
93117// TargetDir retrieves the target directory configured for this [Runner].
94118func (r * Runner ) TargetDir () string {
95119 return r .targetDir
@@ -108,6 +132,36 @@ func (r *Runner) LocalRepoPaths() []string {
108132 return r .localRepoPaths
109133}
110134
135+ // AddRemoteRepo adds a URI to a remote RPM repository (http:// or https://) to include during build.
136+ // Remote repositories are added with lower priority than local repositories.
137+ // Returns an error if the URI is invalid or uses an unsupported scheme.
138+ func (r * Runner ) AddRemoteRepo (repoURI string ) error {
139+ parsedURL , err := url .Parse (repoURI )
140+ if err != nil {
141+ return fmt .Errorf ("invalid repository URI %#q:\n %w" , repoURI , err )
142+ }
143+
144+ switch parsedURL .Scheme {
145+ case "http" :
146+ slog .Warn ("Using insecure HTTP for remote repository; consider using HTTPS instead" ,
147+ "uri" , repoURI )
148+ case "https" :
149+ // Valid, no warning needed
150+ default :
151+ return fmt .Errorf ("unsupported scheme %#q for remote repository %#q: only http:// and https:// are supported" ,
152+ parsedURL .Scheme , repoURI )
153+ }
154+
155+ r .remoteRepoPaths = append (r .remoteRepoPaths , repoURI )
156+
157+ return nil
158+ }
159+
160+ // RemoteRepoPaths retrieves the remote repository URIs configured for this [Runner].
161+ func (r * Runner ) RemoteRepoPaths () []string {
162+ return r .remoteRepoPaths
163+ }
164+
111165// DescriptionDir retrieves the description directory configured for this [Runner].
112166func (r * Runner ) DescriptionDir () string {
113167 return r .descriptionDir
@@ -140,18 +194,42 @@ func (r *Runner) Build(ctx context.Context) error {
140194 "--target-dir" , r .targetDir ,
141195 }
142196
197+ // Add remote repositories using kiwi's --add-repo flag.
198+ // These have lower priority (50) than local repos so local repos can override.
199+ // Format: --add-repo=<uri>,rpm-md,<alias>,<priority>,,,,,,<repo_gpgcheck>
200+ // Note: repo_gpgcheck is at position 10 (1-indexed: source,type,alias,priority,imageinclude,
201+ // package_gpgcheck,{signing_keys},components,distribution,repo_gpgcheck).
202+ if len (r .remoteRepoPaths ) > 0 && ! r .remoteRepoGPGCheck {
203+ slog .Warn ("Remote repositories are configured with GPG checking disabled" ,
204+ "count" , len (r .remoteRepoPaths ))
205+ }
206+
207+ for repoIndex , repoURI := range r .remoteRepoPaths {
208+ alias := fmt .Sprintf ("remote-%d" , repoIndex + 1 )
209+ // Priority 50 for all remote repos (lower priority than local repos at priority 1).
210+ // The trailing commas fill in: imageinclude, package_gpgcheck, signing_keys,
211+ // components, distribution, then repo_gpgcheck.
212+ gpgCheck := "true"
213+ if ! r .remoteRepoGPGCheck {
214+ gpgCheck = "false"
215+ }
216+
217+ repoArg := fmt .Sprintf ("%s,rpm-md,%s,50,,,,,,%s" , repoURI , alias , gpgCheck )
218+ kiwiArgs = append (kiwiArgs , "--add-repo" , repoArg )
219+ }
220+
143221 // Add local repositories using kiwi's --add-repo flag.
222+ // These have highest priority (1) to override both remote repos and kiwi defaults.
144223 // Format: --add-repo=dir://<abs-path>,rpm-md,<alias>,<priority>
145224 for repoIndex , repoPath := range r .localRepoPaths {
146225 absRepoPath , err := filepath .Abs (repoPath )
147226 if err != nil {
148227 return fmt .Errorf ("failed to get absolute path for local repo %#q:\n %w" , repoPath , err )
149228 }
150229
151- // Use priority starting at 1 (highest priority) for local repos.
152- priority := repoIndex + 1
153- alias := fmt .Sprintf ("local-%d" , priority )
154- repoArg := fmt .Sprintf ("dir://%s,rpm-md,%s,%d" , absRepoPath , alias , priority )
230+ // Priority 1 for all local repos (highest priority).
231+ alias := fmt .Sprintf ("local-%d" , repoIndex + 1 )
232+ repoArg := fmt .Sprintf ("dir://%s,rpm-md,%s,1" , absRepoPath , alias )
155233 kiwiArgs = append (kiwiArgs , "--add-repo" , repoArg )
156234 }
157235
0 commit comments