Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package apko for openSUSE:Factory checked in 
at 2024-06-03 17:41:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/apko (Old)
 and      /work/SRC/openSUSE:Factory/.apko.new.24587 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "apko"

Mon Jun  3 17:41:57 2024 rev:11 rq:1178037 version:0.14.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/apko/apko.changes        2024-05-31 
22:15:57.658150200 +0200
+++ /work/SRC/openSUSE:Factory/.apko.new.24587/apko.changes     2024-06-03 
17:42:11.720237989 +0200
@@ -1,0 +2,19 @@
+Sat Jun 01 09:23:29 UTC 2024 - [email protected]
+
+- Update to version 0.14.7:
+  * ensure homedir respects non-defaults
+  * build(deps): bump github/codeql-action from 3.25.6 to 3.25.7
+
+-------------------------------------------------------------------
+Sat Jun 01 09:10:13 UTC 2024 - [email protected]
+
+- Update to version 0.14.6:
+  * plumb through HomeDir as optional build configuration
+  * Pull in the auth fix in go-apk (#1145)
+  * Update internal/cli/build.go
+  * Update internal/cli/publish.go
+  * This fixes the boolean logic to pass auth.
+  * go mod tidy
+  * support basic HTTP auth
+
+-------------------------------------------------------------------

Old:
----
  apko-0.14.5.obscpio

New:
----
  apko-0.14.7.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ apko.spec ++++++
--- /var/tmp/diff_new_pack.aDIWcw/_old  2024-06-03 17:42:12.608270429 +0200
+++ /var/tmp/diff_new_pack.aDIWcw/_new  2024-06-03 17:42:12.608270429 +0200
@@ -19,7 +19,7 @@
 %define __arch_install_post export NO_BRP_STRIP_DEBUG=true
 
 Name:           apko
-Version:        0.14.5
+Version:        0.14.7
 Release:        0
 Summary:        Build OCI images from APK packages directly without Dockerfile
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.aDIWcw/_old  2024-06-03 17:42:12.644271744 +0200
+++ /var/tmp/diff_new_pack.aDIWcw/_new  2024-06-03 17:42:12.648271891 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/chainguard-dev/apko</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v0.14.5</param>
+    <param name="revision">v0.14.7</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.aDIWcw/_old  2024-06-03 17:42:12.664272475 +0200
+++ /var/tmp/diff_new_pack.aDIWcw/_new  2024-06-03 17:42:12.668272621 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/chainguard-dev/apko</param>
-              <param 
name="changesrevision">b69d852e8fc29b2eb2f412e0fdee150aed03645c</param></service></servicedata>
+              <param 
name="changesrevision">f5aa053346e01a693dedca1e7d86a2df76dec6ab</param></service></servicedata>
 (No newline at EOF)
 

++++++ apko-0.14.5.obscpio -> apko-0.14.7.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/.github/workflows/codeql.yaml 
new/apko-0.14.7/.github/workflows/codeql.yaml
--- old/apko-0.14.5/.github/workflows/codeql.yaml       2024-05-29 
19:10:29.000000000 +0200
+++ new/apko-0.14.7/.github/workflows/codeql.yaml       2024-05-31 
18:54:55.000000000 +0200
@@ -29,7 +29,7 @@
         check-latest: true
 
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@9fdb3e49720b44c48891d036bb502feb25684276
+      uses: github/codeql-action/init@f079b8493333aace61c81488f8bd40919487bd9f
       with:
         languages: go
 
@@ -37,4 +37,4 @@
       run: make apko
 
     - name: Perform CodeQL Analysis
-      uses: 
github/codeql-action/analyze@9fdb3e49720b44c48891d036bb502feb25684276
+      uses: 
github/codeql-action/analyze@f079b8493333aace61c81488f8bd40919487bd9f
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/go.mod new/apko-0.14.7/go.mod
--- old/apko-0.14.5/go.mod      2024-05-29 19:10:29.000000000 +0200
+++ new/apko-0.14.7/go.mod      2024-05-31 18:54:55.000000000 +0200
@@ -4,7 +4,7 @@
 
 require (
        github.com/chainguard-dev/clog v1.3.1
-       github.com/chainguard-dev/go-apk v0.0.0-20240529154108-3de67a94ddad
+       github.com/chainguard-dev/go-apk v0.0.0-20240530214935-2ff9aee8385a
        github.com/charmbracelet/log v0.4.0
        github.com/dominodatalab/os-release v0.0.0-20190522011736-bcdb4a3e3c2f
        github.com/go-git/go-git/v5 v5.12.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/go.sum new/apko-0.14.7/go.sum
--- old/apko-0.14.5/go.sum      2024-05-29 19:10:29.000000000 +0200
+++ new/apko-0.14.7/go.sum      2024-05-31 18:54:55.000000000 +0200
@@ -28,8 +28,8 @@
 github.com/cespare/xxhash/v2 v2.2.0/go.mod 
h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/chainguard-dev/clog v1.3.1 
h1:CDNCty5WKQhJzoOPubk0GdXt+bPQyargmfClqebrpaQ=
 github.com/chainguard-dev/clog v1.3.1/go.mod 
h1:cV516KZWqYc/phZsCNwF36u/KMGS+Gj5Uqeb8Hlp95Y=
-github.com/chainguard-dev/go-apk v0.0.0-20240529154108-3de67a94ddad 
h1:MweFfBg9pmE4X+3SdlqJy3SVwbm3XEOze94IkXb3uwY=
-github.com/chainguard-dev/go-apk v0.0.0-20240529154108-3de67a94ddad/go.mod 
h1:4UVB5GXk5yVOVwe3QPdmMLMVTpYbvzygjXlRrJxJPMc=
+github.com/chainguard-dev/go-apk v0.0.0-20240530214935-2ff9aee8385a 
h1:E8EgiRgZsmq1Twz6H2gyyzDB0OxHfZ+h3g8R9BimdAU=
+github.com/chainguard-dev/go-apk v0.0.0-20240530214935-2ff9aee8385a/go.mod 
h1:4UVB5GXk5yVOVwe3QPdmMLMVTpYbvzygjXlRrJxJPMc=
 github.com/charmbracelet/lipgloss v0.10.0 
h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
 github.com/charmbracelet/lipgloss v0.10.0/go.mod 
h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
 github.com/charmbracelet/log v0.4.0 
h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/internal/cli/build.go 
new/apko-0.14.7/internal/cli/build.go
--- old/apko-0.14.5/internal/cli/build.go       2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/internal/cli/build.go       2024-05-31 18:54:55.000000000 
+0200
@@ -22,6 +22,7 @@
        "log/slog"
        "os"
        "path/filepath"
+       "strings"
        "sync"
 
        "github.com/chainguard-dev/clog"
@@ -91,6 +92,18 @@
                        }
                        defer os.RemoveAll(tmp)
 
+                       var user, pass string
+                       if auth, ok := os.LookupEnv("HTTP_AUTH"); !ok {
+                               // Fine, no auth.
+                       } else if parts := strings.SplitN(auth, ":", 4); 
len(parts) != 4 {
+                               return fmt.Errorf("HTTP_AUTH must be in the 
form 'basic:REALM:USERNAME:PASSWORD' (got %d parts)", len(parts))
+                       } else if parts[0] != "basic" {
+                               return fmt.Errorf("HTTP_AUTH must be in the 
form 'basic:REALM:USERNAME:PASSWORD' (got %q for first part)", parts[0])
+                       } else {
+                               // NB: parts[1] is the realm, which we ignore.
+                               user, pass = parts[2], parts[3]
+                       }
+
                        return BuildCmd(cmd.Context(), args[1], args[2], archs,
                                []string{args[1]},
                                writeSBOM,
@@ -109,6 +122,7 @@
                                build.WithCacheDir(cacheDir, offline),
                                build.WithLockFile(lockfile),
                                build.WithTempDir(tmp),
+                               build.WithAuth(user, pass),
                        )
                },
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/internal/cli/publish.go 
new/apko-0.14.7/internal/cli/publish.go
--- old/apko-0.14.5/internal/cli/publish.go     2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/internal/cli/publish.go     2024-05-31 18:54:55.000000000 
+0200
@@ -99,6 +99,18 @@
                        }
                        defer os.RemoveAll(tmp)
 
+                       var user, pass string
+                       if auth, ok := os.LookupEnv("HTTP_AUTH"); !ok {
+                               // Fine, no auth.
+                       } else if parts := strings.SplitN(auth, ":", 4); 
len(parts) != 4 {
+                               return fmt.Errorf("HTTP_AUTH must be in the 
form 'basic:REALM:USERNAME:PASSWORD' (got %d parts)", len(parts))
+                       } else if parts[0] != "basic" {
+                               return fmt.Errorf("HTTP_AUTH must be in the 
form 'basic:REALM:USERNAME:PASSWORD' (got %q for first part)", parts[0])
+                       } else {
+                               // NB: parts[1] is the realm, which we ignore.
+                               user, pass = parts[2], parts[3]
+                       }
+
                        if err := PublishCmd(cmd.Context(), imageRefs, archs, 
remoteOpts,
                                sbomPath,
                                []build.Option{
@@ -115,6 +127,7 @@
                                        build.WithAnnotations(annotations),
                                        build.WithCacheDir(cacheDir, offline),
                                        build.WithTempDir(tmp),
+                                       build.WithAuth(user, pass),
                                },
                                []PublishOption{
                                        // these are extra here just for 
publish; everything before is the same for BuildCmd as PublishCmd
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/apko-0.14.5/internal/cli/testdata/packages/melange.rsa.pub 
new/apko-0.14.7/internal/cli/testdata/packages/melange.rsa.pub
--- old/apko-0.14.5/internal/cli/testdata/packages/melange.rsa.pub      
1970-01-01 01:00:00.000000000 +0100
+++ new/apko-0.14.7/internal/cli/testdata/packages/melange.rsa.pub      
2024-05-31 18:54:55.000000000 +0200
@@ -0,0 +1,14 @@
+-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuE9aHvpBoe7HNnWxhp2p
+x+HGjbPhzP0CyQYMNMcHjd76UcaPwWNTVqJI8JMT2u72mPsEXpC+J6KqjIggJoOa
+QYg87oYEdthoJZjyDaKzezNZKndzVQkg4RfQPiCPQkm4r9v6So0MCDa4rwRYnqrf
+s3Je9/wi8B/wG1sz7P4wOG23djxpORDsMI9CyZhnAKfNg/uqmF/sxEwOL4FaDZMg
+0oo7Kx3FjtqqKTV8uFbCDsTxV3CR0pm3WJdX9TNfjXLXfp2a6QDYk1JoYl++UUHK
++7izMXro6xgY7OPT+F48/YNYxS/ciH90DmN7ysJnQ2otZHSqhOkJV4UrYCKBHY55
+XjpDe7+nmwXaqVyAlCS6pDqHeYUUpYTpnv4b9bbst9NtYPRY8W00Oc5Cs3KdHeV6
+LqvHAGwNTZziv91UTpi0hMf27I+MLaXx+jNWm5j40a+ZyswLAQSLI+u3LxfPlHda
+lhpaQw+CoM3ucX9rcnJaBgowXclDAAvRNIj7EJNW5sk+3SbpmKKDkrD7Cl0rMSrd
+1dixDZZPzA8UtwheNTmV+I+0r1kQMcNYcB8iUKsoWIpaur0CBCww02WTHpOMcMGw
++rVr/wzPP3Iqo1+EVrzVI5kSnZ7VLRtO5VdMLw0PlIK4ShJ+X5OtVtWnJ9jIiLaI
+se0tr8lpqU40eV862X+jKz0CAwEAAQ==
+-----END PUBLIC KEY-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/accounts.go 
new/apko-0.14.7/pkg/build/accounts.go
--- old/apko-0.14.5/pkg/build/accounts.go       2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/pkg/build/accounts.go       2024-05-31 18:54:55.000000000 
+0200
@@ -44,11 +44,14 @@
        if user.Shell == "" {
                user.Shell = "/bin/sh"
        }
+       if user.HomeDir == "" {
+               user.HomeDir = "/home/" + user.UserName
+       }
        return passwd.UserEntry{
                UserName: user.UserName,
                UID:      user.UID,
                GID:      user.GID,
-               HomeDir:  "/home/" + user.UserName,
+               HomeDir:  user.HomeDir,
                Password: "x",
                Info:     "Account created by apko",
                Shell:    user.Shell,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/build.go 
new/apko-0.14.7/pkg/build/build.go
--- old/apko-0.14.5/pkg/build/build.go  2024-05-29 19:10:29.000000000 +0200
+++ new/apko-0.14.7/pkg/build/build.go  2024-05-31 18:54:55.000000000 +0200
@@ -267,6 +267,10 @@
                log.Warnf("cache disabled because cache dir was not set, and 
cannot determine system default: %v", err)
        }
 
+       if bc.o.User != "" || bc.o.Pass != "" {
+               apkOpts = append(apkOpts, apk.WithAuth(bc.o.User, bc.o.Pass))
+       }
+
        if bc.ic.Contents.BaseImage != nil {
                baseImg, err := baseimg.New(bc.ic.Contents.BaseImage.Image, 
bc.ic.Contents.BaseImage.APKIndex, bc.Arch(), bc.o.TempDir())
                if err != nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/build_test.go 
new/apko-0.14.7/pkg/build/build_test.go
--- old/apko-0.14.5/pkg/build/build_test.go     2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/pkg/build/build_test.go     2024-05-31 18:54:55.000000000 
+0200
@@ -16,6 +16,8 @@
 
 import (
        "context"
+       "net/http"
+       "net/http/httptest"
        "path/filepath"
        "testing"
 
@@ -23,6 +25,7 @@
        "github.com/stretchr/testify/require"
 
        "chainguard.dev/apko/pkg/build"
+       "chainguard.dev/apko/pkg/build/types"
 )
 
 func TestBuildLayer(t *testing.T) {
@@ -102,3 +105,75 @@
                "locked package pretend-baselayout has missing checksum (please 
regenerate the lock file with Apko >=0.13)",
                err.Error())
 }
+
+func TestAuth_good(t *testing.T) {
+       called := false
+       testUser, testPass := "user", "pass"
+       s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r 
*http.Request) {
+               w.Header().Set("ETag", "123")
+               if r.Method == http.MethodHead {
+                       return
+               }
+
+               called = true
+               if gotuser, gotpass, ok := r.BasicAuth(); !ok || gotuser != 
testUser || gotpass != testPass {
+                       t.Logf("got user: %q, pass: %q", gotuser, gotpass)
+                       w.WriteHeader(http.StatusForbidden)
+                       return
+               }
+               http.FileServer(http.Dir("testdata/packages")).ServeHTTP(w, r)
+       }))
+       defer s.Close()
+
+       ctx := context.Background()
+       bc, err := build.New(ctx, fs.NewMemFS(),
+               build.WithAuth(testUser, testPass),
+               build.WithImageConfiguration(types.ImageConfiguration{
+                       Contents: types.ImageContents{
+                               Repositories: []string{s.URL},
+                               Keyring:      []string{s.URL + 
"/melange.rsa.pub"},
+                               Packages:     []string{"pretend-baselayout"},
+                       },
+                       Archs: types.ParseArchitectures([]string{"amd64", 
"arm64"}),
+               }),
+       )
+       if err != nil {
+               t.Fatal(err)
+       }
+       err = bc.BuildImage(ctx)
+       require.NoError(t, err, "build image failed")
+       require.True(t, called)
+}
+
+func TestAuth_bad(t *testing.T) {
+       called := false
+       testUser, testPass := "user", "pass"
+       s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r 
*http.Request) {
+               w.Header().Set("ETag", "123")
+               if r.Method == http.MethodHead {
+                       return
+               }
+
+               called = true
+               if gotuser, gotpass, ok := r.BasicAuth(); !ok || gotuser != 
testUser || gotpass != testPass {
+                       w.WriteHeader(http.StatusForbidden)
+                       return
+               }
+               http.FileServer(http.Dir("testdata/packages")).ServeHTTP(w, r)
+       }))
+       defer s.Close()
+
+       ctx := context.Background()
+       _, err := build.New(ctx, fs.NewMemFS(),
+               build.WithAuth("baduser", "badpass"),
+               build.WithImageConfiguration(types.ImageConfiguration{
+                       Contents: types.ImageContents{
+                               Keyring: []string{s.URL + "/melange.rsa.pub"},
+                               // We don't even need to specify repository or 
packages, since keyring init will fail without auth.
+                       },
+                       Archs: types.ParseArchitectures([]string{"amd64", 
"arm64"}),
+               }),
+       )
+       require.Error(t, err, "build should have failed to init keyring")
+       require.True(t, called)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/options.go 
new/apko-0.14.7/pkg/build/options.go
--- old/apko-0.14.5/pkg/build/options.go        2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/pkg/build/options.go        2024-05-31 18:54:55.000000000 
+0200
@@ -207,3 +207,11 @@
                return nil
        }
 }
+
+func WithAuth(user, pass string) Option {
+       return func(bc *Context) error {
+               bc.o.User = user
+               bc.o.Pass = pass
+               return nil
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/types/image_configuration.go 
new/apko-0.14.7/pkg/build/types/image_configuration.go
--- old/apko-0.14.5/pkg/build/types/image_configuration.go      2024-05-29 
19:10:29.000000000 +0200
+++ new/apko-0.14.7/pkg/build/types/image_configuration.go      2024-05-31 
18:54:55.000000000 +0200
@@ -164,7 +164,7 @@
                }
        }
 
-       for _, u := range ic.Accounts.Users {
+       for i, u := range ic.Accounts.Users {
                if u.UserName == "" {
                        return fmt.Errorf("configured user %v has no configured 
user name", u)
                }
@@ -172,6 +172,10 @@
                if u.UID == 0 {
                        return fmt.Errorf("configured user %v has UID 0 (to run 
as root, use `run-as: 0`)", u)
                }
+
+               if u.HomeDir == "" {
+                       ic.Accounts.Users[i].HomeDir = "/home/" + u.UserName
+               }
        }
 
        for _, g := range ic.Accounts.Groups {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/apko-0.14.5/pkg/build/types/image_configuration_test.go 
new/apko-0.14.7/pkg/build/types/image_configuration_test.go
--- old/apko-0.14.5/pkg/build/types/image_configuration_test.go 2024-05-29 
19:10:29.000000000 +0200
+++ new/apko-0.14.7/pkg/build/types/image_configuration_test.go 2024-05-31 
18:54:55.000000000 +0200
@@ -36,3 +36,19 @@
        require.ElementsMatch(t, ic.Contents.Keyring, []string{"key"})
        require.ElementsMatch(t, ic.Contents.Packages, []string{"package", 
"other_package"})
 }
+
+func TestUserContents(t *testing.T) {
+       ctx := context.Background()
+
+       configPath := filepath.Join("testdata", "users.apko.yaml")
+       hasher := sha256.New()
+       ic := types.ImageConfiguration{}
+
+       require.NoError(t, ic.Load(ctx, configPath, hasher))
+       if err := ic.Validate(); err != nil {
+               t.Fatal(err)
+       }
+
+       require.Equal(t, "/not/home", ic.Accounts.Users[0].HomeDir)
+       require.Equal(t, "/home/user", ic.Accounts.Users[1].HomeDir)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/types/schema.json 
new/apko-0.14.7/pkg/build/types/schema.json
--- old/apko-0.14.5/pkg/build/types/schema.json 2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/pkg/build/types/schema.json 2024-05-31 18:54:55.000000000 
+0200
@@ -274,7 +274,11 @@
         },
         "shell": {
           "type": "string",
-          "description": "Required: The user's shell"
+          "description": "Optional: The user's shell"
+        },
+        "homedir": {
+          "type": "string",
+          "description": "Optional: The user's home directory"
         }
       },
       "additionalProperties": false,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/types/testdata/users.apko.yaml 
new/apko-0.14.7/pkg/build/types/testdata/users.apko.yaml
--- old/apko-0.14.5/pkg/build/types/testdata/users.apko.yaml    1970-01-01 
01:00:00.000000000 +0100
+++ new/apko-0.14.7/pkg/build/types/testdata/users.apko.yaml    2024-05-31 
18:54:55.000000000 +0200
@@ -0,0 +1,17 @@
+contents:
+  repositories:
+    - "repository"
+  keyring:
+    - "key"
+  packages:
+    - "package"
+
+accounts:
+  users:
+    - gid: 1
+      uid: 2
+      homedir: "/not/home"
+      username: "something-else"
+    - gid: 2
+      uid: 3
+      username: "user"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/build/types/types.go 
new/apko-0.14.7/pkg/build/types/types.go
--- old/apko-0.14.5/pkg/build/types/types.go    2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/pkg/build/types/types.go    2024-05-31 18:54:55.000000000 
+0200
@@ -30,8 +30,10 @@
        UID uint32 `json:"uid,omitempty"`
        // Required: The user's group ID
        GID uint32 `json:"gid,omitempty"`
-       // Required: The user's shell
+       // Optional: The user's shell
        Shell string `json:"shell,omitempty"`
+       // Optional: The user's home directory
+       HomeDir string `json:"homedir,omitempty"`
 }
 
 type Group struct {
@@ -138,9 +140,9 @@
        // Required: The user to run the container as. This can be a username 
or UID.
        RunAs string `json:"run-as,omitempty" yaml:"run-as"`
        // Required: List of users to populate the image with
-       Users []User `json:"users,omitempty"`
+       Users []User `json:"users,omitempty" yaml:"users"`
        // Required: List of groups to populate the image with
-       Groups []Group `json:"groups,omitempty"`
+       Groups []Group `json:"groups,omitempty" yaml:"groups"`
 }
 
 type ImageConfiguration struct {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-0.14.5/pkg/options/options.go 
new/apko-0.14.7/pkg/options/options.go
--- old/apko-0.14.5/pkg/options/options.go      2024-05-29 19:10:29.000000000 
+0200
+++ new/apko-0.14.7/pkg/options/options.go      2024-05-31 18:54:55.000000000 
+0200
@@ -48,6 +48,8 @@
        CacheDir                string             `json:"cacheDir,omitempty"`
        Offline                 bool               `json:"offline,omitempty"`
        Lockfile                string             `json:"lockfile,omitempty"`
+       User                    string             `json:"user"`
+       Pass                    string             `json:"-"`
 }
 
 var Default = Options{

++++++ apko.obsinfo ++++++
--- /var/tmp/diff_new_pack.aDIWcw/_old  2024-06-03 17:42:12.868279928 +0200
+++ /var/tmp/diff_new_pack.aDIWcw/_new  2024-06-03 17:42:12.872280074 +0200
@@ -1,5 +1,5 @@
 name: apko
-version: 0.14.5
-mtime: 1717002629
-commit: b69d852e8fc29b2eb2f412e0fdee150aed03645c
+version: 0.14.7
+mtime: 1717174495
+commit: f5aa053346e01a693dedca1e7d86a2df76dec6ab
 

++++++ vendor.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/cache.go 
new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/cache.go
--- old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/cache.go        
2024-05-30 10:59:08.000000000 +0200
+++ new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/cache.go        
2024-06-01 11:23:30.000000000 +0200
@@ -54,7 +54,9 @@
        // Do all the expensive things inside the once.
        once, _ := e.etags.LoadOrStore(url, &sync.Once{})
        once.(*sync.Once).Do(func() {
-               resp, rerr := t.wrapped.Head(url)
+               req := request.Clone(request.Context())
+               req.Method = http.MethodHead
+               resp, rerr := t.wrapped.Do(req)
                if resp != nil {
                        // We don't expect any body from a HEAD so just always 
close it to appease the linter.
                        resp.Body.Close()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/implementation.go 
new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/implementation.go
--- old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/implementation.go       
2024-05-30 10:59:08.000000000 +0200
+++ new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/implementation.go       
2024-06-01 11:23:30.000000000 +0200
@@ -65,6 +65,7 @@
        cache              *cache
        ignoreSignatures   bool
        noSignatureIndexes []string
+       user, pass         string
 
        // filename to owning package, last write wins
        installedFiles map[string]*Package
@@ -93,6 +94,8 @@
                cache:              opt.cache,
                noSignatureIndexes: opt.noSignatureIndexes,
                installedFiles:     map[string]*Package{},
+               user:               opt.user,
+               pass:               opt.pass,
        }, nil
 }
 
@@ -377,7 +380,7 @@
 
                        var asURL *url.URL
                        var err error
-                       if strings.HasPrefix(element, "https://";) {
+                       if strings.HasPrefix(element, "https://";) || 
strings.HasPrefix(element, "http://";) {
                                asURL, err = url.Parse(element)
                        } else {
                                // Attempt to parse non-https elements into 
URI's so they are translated into
@@ -395,7 +398,7 @@
                                if err != nil {
                                        return fmt.Errorf("failed to read apk 
key: %w", err)
                                }
-                       case "https": //nolint:goconst
+                       case "https", "http": //nolint:goconst
                                client := a.client
                                if a.cache != nil {
                                        client = a.cache.client(client, true)
@@ -404,11 +407,15 @@
                                if err != nil {
                                        return err
                                }
+
                                // if the URL contains HTTP Basic Auth 
credentials, add them to the request
                                if asURL.User != nil {
                                        user := asURL.User.Username()
                                        pass, _ := asURL.User.Password()
                                        req.SetBasicAuth(user, pass)
+                                       req.URL.User = nil
+                               } else if a.user != "" && a.pass != "" {
+                                       req.SetBasicAuth(a.user, a.pass)
                                }
 
                                resp, err := client.Do(req)
@@ -714,6 +721,7 @@
        if err != nil {
                return err
        }
+       // NB: Not setting basic auth, since we know Alpine doesn't support it.
        res, err := client.Do(req)
        if err != nil {
                return fmt.Errorf("failed to fetch alpine releases: %w", err)
@@ -748,6 +756,7 @@
                if err != nil {
                        return err
                }
+               // NB: Not setting basic auth, since we know Alpine doesn't 
support it.
                res, err := client.Do(req)
                if err != nil {
                        return fmt.Errorf("failed to fetch alpine key %s: %w", 
u, err)
@@ -995,7 +1004,7 @@
 func packageAsURI(pkg InstallablePackage) (uri.URI, error) {
        u := pkg.URL()
 
-       if strings.HasPrefix(u, "https://";) {
+       if strings.HasPrefix(u, "https://";) || strings.HasPrefix(u, "http://";) {
                return uri.Parse(u)
        }
 
@@ -1035,7 +1044,7 @@
                        return nil, fmt.Errorf("failed to read repository 
package apk %s: %w", u, err)
                }
                return f, nil
-       case "https":
+       case "https", "http":
                client := a.client
                if a.cache != nil {
                        client = a.cache.client(client, false)
@@ -1044,6 +1053,9 @@
                if err != nil {
                        return nil, err
                }
+               if a.user != "" && a.pass != "" {
+                       req.SetBasicAuth(a.user, a.pass)
+               }
 
                // This will return a body that retries requests using Range 
requests if Read() hits an error.
                rrt := newRangeRetryTransport(ctx, client)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/index.go 
new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/index.go
--- old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/index.go        
2024-05-30 10:59:08.000000000 +0200
+++ new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/index.go        
2024-06-01 11:23:30.000000000 +0200
@@ -64,7 +64,7 @@
 }
 
 func (i *indexCache) get(ctx context.Context, u string, keys 
map[string][]byte, arch string, opts *indexOpts) (*APKIndex, error) {
-       if strings.HasPrefix(u, "https://";) {
+       if strings.HasPrefix(u, "https://";) || strings.HasPrefix(u, "http://";) {
                // We don't want remote indexes to change while we're running.
                once, _ := i.onces.LoadOrStore(u, &sync.Once{})
                once.(*sync.Once).Do(func() {
@@ -173,7 +173,7 @@
        return true
 }
 
-func getRepositoryIndex(ctx context.Context, u string, keys map[string][]byte, 
arch string, opts *indexOpts) (*APKIndex, error) {
+func getRepositoryIndex(ctx context.Context, u string, keys map[string][]byte, 
arch string, opts *indexOpts) (*APKIndex, error) { //nolint:gocyclo
        // Normalize the repo as a URI, so that local paths
        // are translated into file:// URLs, allowing them to be parsed
        // into a url.URL{}.
@@ -182,7 +182,7 @@
                asURL *url.URL
                err   error
        )
-       if strings.HasPrefix(u, "https://";) {
+       if strings.HasPrefix(u, "https://";) || strings.HasPrefix(u, "http://";) {
                asURL, err = url.Parse(u)
        } else {
                // Attempt to parse non-https elements into URI's so they are 
translated into
@@ -202,7 +202,7 @@
                        }
                        return nil, nil
                }
-       case "https":
+       case "https", "http":
                client := opts.httpClient
                req, err := http.NewRequestWithContext(ctx, http.MethodGet, 
asURL.String(), nil)
                if err != nil {
@@ -213,6 +213,8 @@
                        user := asURL.User.Username()
                        pass, _ := asURL.User.Password()
                        req.SetBasicAuth(user, pass)
+               } else if opts.user != "" || opts.pass != "" {
+                       req.SetBasicAuth(opts.user, opts.pass)
                }
 
                // This will return a body that retries requests using Range 
requests if Read() hits an error.
@@ -318,6 +320,7 @@
        ignoreSignatures   bool
        noSignatureIndexes []string
        httpClient         *http.Client
+       user, pass         string
 }
 type IndexOption func(*indexOpts)
 
@@ -338,3 +341,10 @@
                o.httpClient = c
        }
 }
+
+func WithIndexAuth(user, pass string) IndexOption {
+       return func(o *indexOpts) {
+               o.user = user
+               o.pass = pass
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/options.go 
new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/options.go
--- old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/options.go      
2024-05-30 10:59:08.000000000 +0200
+++ new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/options.go      
2024-06-01 11:23:30.000000000 +0200
@@ -30,6 +30,7 @@
        version            string
        cache              *cache
        noSignatureIndexes []string
+       user, pass         string
 }
 
 type Option func(*opts) error
@@ -104,6 +105,14 @@
                return nil
        }
 }
+
+func WithAuth(user, pass string) Option {
+       return func(o *opts) error {
+               o.user = user
+               o.pass = pass
+               return nil
+       }
+}
 
 func defaultOpts() *opts {
        return &opts{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/repo.go 
new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/repo.go
--- old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/repo.go 2024-05-30 
10:59:08.000000000 +0200
+++ new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/repo.go 2024-06-01 
11:23:30.000000000 +0200
@@ -176,7 +176,11 @@
        if a.cache != nil {
                httpClient = a.cache.client(httpClient, true)
        }
-       return GetRepositoryIndexes(ctx, repos, keys, arch, 
WithIgnoreSignatures(ignoreSignatures), WithHTTPClient(httpClient), 
WithIgnoreSignatureForIndexes(a.noSignatureIndexes...))
+       return GetRepositoryIndexes(ctx, repos, keys, arch,
+               WithIgnoreSignatures(ignoreSignatures),
+               WithIgnoreSignatureForIndexes(a.noSignatureIndexes...),
+               WithHTTPClient(httpClient),
+               WithIndexAuth(a.user, a.pass))
 }
 
 // PkgResolver resolves packages from a list of indexes.
@@ -193,7 +197,7 @@
        nameMap      map[string][]*repositoryPackage
        installIfMap map[string][]*repositoryPackage // contains any package 
that should be installed if the named package is installed
 
-       parsedVersions map[string]packageVersion
+       parsedVersions map[string]Version
        depForVersion  map[string]parsedConstraint
 }
 
@@ -211,7 +215,7 @@
        )
        p := &PkgResolver{
                indexes:        indexes,
-               parsedVersions: map[string]packageVersion{},
+               parsedVersions: map[string]Version{},
                depForVersion:  map[string]parsedConstraint{},
        }
 
@@ -695,7 +699,7 @@
 
                        if allowSelfFulfill && pkg.Name == name {
                                var (
-                                       actualVersion, requiredVersion 
packageVersion
+                                       actualVersion, requiredVersion Version
                                        err1, err2                     error
                                )
                                actualVersion, err1 = 
p.parseVersion(pkg.Version)
@@ -787,13 +791,13 @@
        return dependencies, conflicts, nil
 }
 
-func (p *PkgResolver) parseVersion(version string) (packageVersion, error) {
+func (p *PkgResolver) parseVersion(version string) (Version, error) {
        pkg, ok := p.parsedVersions[version]
        if ok {
                return pkg, nil
        }
 
-       parsed, err := parseVersion(version)
+       parsed, err := ParseVersion(version)
        if err != nil {
                return parsed, err
        }
@@ -906,9 +910,9 @@
                        // If j fails to parse, prefer i.
                        return -1
                }
-               versions := compareVersions(iVersion, jVersion)
+               versions := CompareVersions(iVersion, jVersion)
                if versions != equal {
-                       return -1 * int(versions)
+                       return -1 * versions
                }
                // if versions are equal, they might not be the same as the 
package versions
                if iVersionStr != a.Version || jVersionStr != b.Version {
@@ -921,9 +925,9 @@
                                // If j fails to parse, prefer i.
                                return -1
                        }
-                       versions := compareVersions(iVersion, jVersion)
+                       versions := CompareVersions(iVersion, jVersion)
                        if versions != equal {
-                               return -1 * int(versions)
+                               return -1 * versions
                        }
                }
                // if versions are equal, compare names
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/version.go 
new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/version.go
--- old/vendor/github.com/chainguard-dev/go-apk/pkg/apk/version.go      
2024-05-30 10:59:08.000000000 +0200
+++ new/vendor/github.com/chainguard-dev/go-apk/pkg/apk/version.go      
2024-06-01 11:23:30.000000000 +0200
@@ -67,7 +67,7 @@
        packageVersionPostModifierMax  packageVersionPostModifier = 1000
 )
 
-type packageVersion struct {
+type Version struct {
        numbers          []int
        letter           rune
        preSuffix        packageVersionPreModifier
@@ -77,21 +77,22 @@
        revision         int
 }
 
-func parseVersion(version string) (packageVersion, error) {
+// ParseVersion parses a version string into a Version struct.
+func ParseVersion(version string) (Version, error) {
        parts := versionRegex.FindAllStringSubmatch(version, -1)
        if len(parts) == 0 {
-               return packageVersion{}, fmt.Errorf("invalid version %s, could 
not parse", version)
+               return Version{}, fmt.Errorf("invalid version %s, could not 
parse", version)
        }
        actuals := parts[0]
        numbers := make([]int, 0, 10)
        if len(actuals) != 14 {
-               return packageVersion{}, fmt.Errorf("invalid version %s, could 
not find enough components", version)
+               return Version{}, fmt.Errorf("invalid version %s, could not 
find enough components", version)
        }
 
        // get the first version number
        num, err := strconv.Atoi(actuals[1])
        if err != nil {
-               return packageVersion{}, fmt.Errorf("invalid version %s, first 
part is not number: %w", version, err)
+               return Version{}, fmt.Errorf("invalid version %s, first part is 
not number: %w", version, err)
        }
        numbers = append(numbers, num)
 
@@ -104,7 +105,7 @@
                        }
                        num, err := strconv.Atoi(s)
                        if err != nil {
-                               return packageVersion{}, fmt.Errorf("invalid 
version %s, part %d is not number: %w", version, i, err)
+                               return Version{}, fmt.Errorf("invalid version 
%s, part %d is not number: %w", version, i, err)
                        }
                        numbers = append(numbers, num)
                }
@@ -126,13 +127,13 @@
        case "":
                preSuffix = packageVersionPreModifierNone
        default:
-               return packageVersion{}, fmt.Errorf("invalid version %s, 
pre-suffix %s is not valid", version, actuals[6])
+               return Version{}, fmt.Errorf("invalid version %s, pre-suffix %s 
is not valid", version, actuals[6])
        }
        var preSuffixNumber int
        if actuals[7] != "" {
                num, err := strconv.Atoi(actuals[7])
                if err != nil {
-                       return packageVersion{}, fmt.Errorf("invalid version 
%s, suffix %s number %s is not number: %w", version, actuals[6], actuals[7], 
err)
+                       return Version{}, fmt.Errorf("invalid version %s, 
suffix %s number %s is not number: %w", version, actuals[6], actuals[7], err)
                }
                preSuffixNumber = num
        }
@@ -152,13 +153,13 @@
        case "":
                postSuffix = packageVersionPostModifierNone
        default:
-               return packageVersion{}, fmt.Errorf("invalid version %s, suffix 
%s is not valid", version, actuals[9])
+               return Version{}, fmt.Errorf("invalid version %s, suffix %s is 
not valid", version, actuals[9])
        }
        var postSuffixNumber int
        if actuals[10] != "" {
                num, err := strconv.Atoi(actuals[10])
                if err != nil {
-                       return packageVersion{}, fmt.Errorf("invalid version 
%s, post-suffix %s number %s is not number: %w", version, actuals[9], 
actuals[10], err)
+                       return Version{}, fmt.Errorf("invalid version %s, 
post-suffix %s number %s is not number: %w", version, actuals[9], actuals[10], 
err)
                }
                postSuffixNumber = num
        }
@@ -167,11 +168,11 @@
        if actuals[13] != "" {
                num, err := strconv.Atoi(actuals[13])
                if err != nil {
-                       return packageVersion{}, fmt.Errorf("invalid version 
%s, revision %s is not number: %w", version, actuals[13], err)
+                       return Version{}, fmt.Errorf("invalid version %s, 
revision %s is not number: %w", version, actuals[13], err)
                }
                revision = num
        }
-       return packageVersion{
+       return Version{
                numbers:          numbers,
                letter:           letter,
                preSuffix:        preSuffix,
@@ -182,29 +183,14 @@
        }, nil
 }
 
-type versionCompare int
-
 const (
-       greater versionCompare = 1
-       equal   versionCompare = 0
-       less    versionCompare = -1
+       greater = 1
+       equal   = 0
+       less    = -1
 )
 
-func (vc versionCompare) String() string {
-       switch vc {
-       case greater:
-               return ">"
-       case equal:
-               return "="
-       case less:
-               return "<"
-       default:
-               return "???"
-       }
-}
-
-// compare versions based on 
https://dev.gentoo.org/~ulm/pms/head/pms.html#x1-250003.2
-func compareVersions(actual, required packageVersion) versionCompare {
+// CompareVersions compares versions based on 
https://dev.gentoo.org/~ulm/pms/head/pms.html#x1-250003.2
+func CompareVersions(actual, required Version) int {
        for i := 0; i < len(actual.numbers) && i < len(required.numbers); i++ {
                if actual.numbers[i] > required.numbers[i] {
                        return greater
@@ -283,7 +269,7 @@
 }
 
 // includesVersion returns true if the actual version is a strict subset of 
the required version
-func includesVersion(actual, required packageVersion) bool {
+func includesVersion(actual, required Version) bool {
        // if more required numbers than actual numbers, than require is more 
specific,
        // so no match
        if len(actual.numbers) < len(required.numbers) {
@@ -340,11 +326,11 @@
        versionTilde
 )
 
-func (v versionDependency) satisfies(actualVersion, requiredVersion 
packageVersion) bool {
+func (v versionDependency) satisfies(actualVersion, requiredVersion Version) 
bool {
        if v == versionTilde {
                return includesVersion(actualVersion, requiredVersion)
        }
-       c := compareVersions(actualVersion, requiredVersion)
+       c := CompareVersions(actualVersion, requiredVersion)
        switch v {
        case versionAny:
                return true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt
--- old/vendor/modules.txt      2024-05-30 10:59:09.000000000 +0200
+++ new/vendor/modules.txt      2024-06-01 11:23:31.000000000 +0200
@@ -46,7 +46,7 @@
 # github.com/chainguard-dev/clog v1.3.1
 ## explicit; go 1.21.2
 github.com/chainguard-dev/clog
-# github.com/chainguard-dev/go-apk v0.0.0-20240529154108-3de67a94ddad
+# github.com/chainguard-dev/go-apk v0.0.0-20240530214935-2ff9aee8385a
 ## explicit; go 1.22.3
 github.com/chainguard-dev/go-apk/internal/tarfs
 github.com/chainguard-dev/go-apk/pkg/apk

Reply via email to