Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package apko for openSUSE:Factory checked in 
at 2026-08-01 18:32:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/apko (Old)
 and      /work/SRC/openSUSE:Factory/.apko.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "apko"

Sat Aug  1 18:32:02 2026 rev:130 rq:1368742 version:1.2.30

Changes:
--------
--- /work/SRC/openSUSE:Factory/apko/apko.changes        2026-07-28 
17:54:39.157639564 +0200
+++ /work/SRC/openSUSE:Factory/.apko.new.16738/apko.changes     2026-08-01 
18:35:11.135924587 +0200
@@ -1,0 +2,33 @@
+Fri Jul 31 05:53:20 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 1.2.30:
+  * build(deps): bump chainguard.dev/sdk from 0.1.156 to 0.1.158
+    (#2359)
+  * build(deps): bump chainguard-dev/actions/setup-registry from
+    1.6.28 to 1.6.29 (#2358)
+  * chore(harden-runner): allow apple endpoints to OSX builds
+    (#2361)
+  * Use slices.Concat in TestWriteCABundleChecksumsNoBundles
+    (#2349)
+  * build(deps): bump github/codeql-action/init from 4.37.2 to
+    4.37.3 (#2354)
+  * build(deps): bump google.golang.org/api from 0.289.0 to 0.290.0
+    (#2353)
+  * build(deps): bump github/codeql-action/analyze from 4.37.2 to
+    4.37.3 (#2355)
+  * build(deps): bump k8s.io/apimachinery from 0.36.2 to 0.36.3
+    (#2352)
+  * build(deps): bump chainguard.dev/sdk from 0.1.145 to 0.1.156
+    (#2351)
+  * build(deps): bump zizmorcore/zizmor-action from 0.6.0 to 0.6.1
+    (#2356)
+  * Regenerate apko-discover.lock.json golden file (#2350)
+  * build(deps): bump github/codeql-action/analyze from 4.37.1 to
+    4.37.2 (#2348)
+  * build(deps): bump github/codeql-action/init from 4.37.1 to
+    4.37.2 (#2347)
+  * build(deps): bump chainguard.dev/sdk from 0.1.140 to 0.1.145
+    (#2346)
+  * Write sha256 checksum sidecar next to CA bundles (#2331)
+
+-------------------------------------------------------------------

Old:
----
  apko-1.2.29.obscpio

New:
----
  apko-1.2.30.obscpio

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

Other differences:
------------------
++++++ apko.spec ++++++
--- /var/tmp/diff_new_pack.PnEp56/_old  2026-08-01 18:35:13.472005028 +0200
+++ /var/tmp/diff_new_pack.PnEp56/_new  2026-08-01 18:35:13.476005165 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           apko
-Version:        1.2.29
+Version:        1.2.30
 Release:        0
 Summary:        Build OCI images from APK packages directly without Dockerfile
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.PnEp56/_old  2026-08-01 18:35:13.520006681 +0200
+++ /var/tmp/diff_new_pack.PnEp56/_new  2026-08-01 18:35:13.524006818 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/chainguard-dev/apko.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">refs/tags/v1.2.29</param>
+    <param name="revision">refs/tags/v1.2.30</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.PnEp56/_old  2026-08-01 18:35:13.548007645 +0200
+++ /var/tmp/diff_new_pack.PnEp56/_new  2026-08-01 18:35:13.552007783 +0200
@@ -3,6 +3,6 @@
                 <param 
name="url">https://github.com/chainguard-dev/apko</param>
               <param 
name="changesrevision">861f83f69e6fa9114405a2f7bb5cf6585ad00421</param></service><service
 name="tar_scm">
                 <param 
name="url">https://github.com/chainguard-dev/apko.git</param>
-              <param 
name="changesrevision">e3915900849d95b35f1f5b7c7401922505332152</param></service></servicedata>
+              <param 
name="changesrevision">502643080cb38d339c5804fe7e62c9a5bd46b6d5</param></service></servicedata>
 (No newline at EOF)
 

++++++ apko-1.2.29.obscpio -> apko-1.2.30.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-1.2.29/go.mod new/apko-1.2.30/go.mod
--- old/apko-1.2.29/go.mod      2026-07-24 15:46:38.000000000 +0200
+++ new/apko-1.2.30/go.mod      2026-07-30 20:33:18.000000000 +0200
@@ -3,7 +3,7 @@
 go 1.26.0
 
 require (
-       chainguard.dev/sdk v0.1.140
+       chainguard.dev/sdk v0.1.158
        github.com/chainguard-dev/clog v1.8.1
        github.com/charmbracelet/log v1.0.0
        github.com/go-git/go-git/v5 v5.19.1
@@ -31,10 +31,10 @@
        golang.org/x/sys v0.47.0
        golang.org/x/term v0.45.0
        golang.org/x/time v0.15.0
-       google.golang.org/api v0.289.0
+       google.golang.org/api v0.290.0
        gopkg.in/ini.v1 v1.67.3
        gopkg.in/yaml.v3 v3.0.1
-       k8s.io/apimachinery v0.36.2
+       k8s.io/apimachinery v0.36.3
        sigs.k8s.io/release-utils v0.12.4
 )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-1.2.29/go.sum new/apko-1.2.30/go.sum
--- old/apko-1.2.29/go.sum      2026-07-24 15:46:38.000000000 +0200
+++ new/apko-1.2.30/go.sum      2026-07-30 20:33:18.000000000 +0200
@@ -1,7 +1,7 @@
 chainguard.dev/go-grpc-kit v0.17.17 
h1:Jwhc0zyUwQbC2hNcsi+YMeUX/JUnM+dXVCkTw6wtPzs=
 chainguard.dev/go-grpc-kit v0.17.17/go.mod 
h1:qn0meP6RtrbLicE1bgBZnnVU9dvX95eLs0x0T6kZ+b4=
-chainguard.dev/sdk v0.1.140 h1:9rV+7BG70uP+yqFC5IvU/f/fAleJ6kRdALXYMu29xZ0=
-chainguard.dev/sdk v0.1.140/go.mod 
h1:hwsZl3o558o1R4d8hXrIYHZ6E9lCAXJgeVXQMnV5bRM=
+chainguard.dev/sdk v0.1.158 h1:aOWATQ4zxYKQ8D+CCUj+hOU18wNQkbHw6tmj+/+GDAk=
+chainguard.dev/sdk v0.1.158/go.mod 
h1:WIaM60bR6qU84RvE45u4QkOh+BN2uc1nfHuZYLnRfvU=
 cloud.google.com/go/auth v0.21.0 
h1:g/QwYfYb2Ai6HH8oomAOyBaIHLbscZ4+T/F/f5JZHkE=
 cloud.google.com/go/auth v0.21.0/go.mod 
h1:M9o2Oz+YI2jAfxewJgb1vyI3vceHF+eohmxyzmrl+9s=
 cloud.google.com/go/auth/oauth2adapt v0.2.8 
h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
@@ -345,8 +345,8 @@
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
 gonum.org/v1/gonum v0.17.0/go.mod 
h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
-google.golang.org/api v0.289.0 h1:DmH0c6NigNFmsvsohM9bxv+MzVhag3aGHnojA5fFQjc=
-google.golang.org/api v0.289.0/go.mod 
h1:weJZ3lldHFYI0DBFNKpJelUDNnusTt5YaOEgxvt8ci8=
+google.golang.org/api v0.290.0 h1:eMw0Xo+IfbbMlKmW7aHvpyQRv9RCXuWx/vs8AD+0x9A=
+google.golang.org/api v0.290.0/go.mod 
h1:weJZ3lldHFYI0DBFNKpJelUDNnusTt5YaOEgxvt8ci8=
 google.golang.org/genproto v0.0.0-20260406210006-6f92a3bedf2d 
h1:N1Ec54vZnIPd7MnxRiYLW+oY4fDR4BOS/LrssdD9+ek=
 google.golang.org/genproto v0.0.0-20260406210006-6f92a3bedf2d/go.mod 
h1:c2hJ1grtnH0xUiEKGDGkjGNTJ1Hy2LrblyKOHF0sqRM=
 google.golang.org/genproto/googleapis/api v0.0.0-20260706201446-f0a921348800 
h1:admdQBe8jR3VWhBsUrAOaF2Qw6K/+p5pSm1GN8+6Fw4=
@@ -372,8 +372,8 @@
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
 gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
-k8s.io/apimachinery v0.36.2 h1:0PE/W/WNy1UX61NLbXY5TMbJ6UwLL6E6lAPkYrKFxbQ=
-k8s.io/apimachinery v0.36.2/go.mod 
h1:fvf/HOLXq9RId0rnDIbN1OEBvHXdQbLMM8nu0LcBUf4=
+k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM=
+k8s.io/apimachinery v0.36.3/go.mod 
h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE=
 pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
 pgregory.net/rapid v1.2.0/go.mod 
h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
 sigs.k8s.io/release-utils v0.12.4 
h1:kuG6WTWGCKx5uUrJwl2uFErOKOw+4Ba8WrPmOQh5J3g=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/apko-1.2.29/internal/cli/testdata/apko-discover.lock.json 
new/apko-1.2.30/internal/cli/testdata/apko-discover.lock.json
--- old/apko-1.2.29/internal/cli/testdata/apko-discover.lock.json       
2026-07-24 15:46:38.000000000 +0200
+++ new/apko-1.2.30/internal/cli/testdata/apko-discover.lock.json       
2026-07-30 20:33:18.000000000 +0200
@@ -22,16 +22,16 @@
         "content": "-----BEGIN PUBLIC 
KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyduVzi1mWm+lYo2Tqt/0\nXkCIWrDNP1QBMVPrE0/ZlU2bCGSoo2Z9FHQKz/mTyMRlhNqTfhJ5qU3U9XlyGOPJ\npiM+b91g26pnpXJ2Q2kOypSgOMOPA4cQ42PkHBEqhuzssfj9t7x47ppS94bboh46\nxLSDRff/NAbtwTpvhStV3URYkxFG++cKGGa5MPXBrxIp+iZf9GnuxVdST5PGiVGP\nODL/b69sPJQNbJHVquqUTOh5Ry8uuD2WZuXfKf7/C0jC/ie9m2+0CttNu9tMciGM\nEyKG1/Xhk5iIWO43m4SrrT2WkFlcZ1z2JSf9Pjm4C2+HovYpihwwdM/OdP8Xmsnr\nDzVB4YvQiW+IHBjStHVuyiZWc+JsgEPJzisNY0Wyc/kNyNtqVKpX6dRhMLanLmy+\nf53cCSI05KPQAcGj6tdL+D60uKDkt+FsDa0BTAobZ31OsFVid0vCXtsbplNhW1IF\nHwsGXBTVcfXg44RLyL8Lk/2dQxDHNHzAUslJXzPxaHBLmt++2COa2EI1iWlvtznk\nOk9WP8SOAIj+xdqoiHcC4j72BOVVgiITIJNHrbppZCq6qPR+fgXmXa+sDcGh30m6\n9Wpbr28kLMSHiENCWTdsFij+NQTd5S47H7XTROHnalYDuF1RpS+DpQidT5tUimaT\nJZDr++FjKrnnijbyNF8b98UCAwEAAQ==\n-----END
 PUBLIC KEY-----\n"
       },
       {
-        "name": 
"apk.cgr.dev/chainguard/chainguard-4be246965c6e2749ccbaeba0582ed0f90c7cb94f4c0397e014b322b8652e3ba4.rsa.pub",
-        "url": 
"https://apk.cgr.dev/chainguard/chainguard-4be246965c6e2749ccbaeba0582ed0f90c7cb94f4c0397e014b322b8652e3ba4.rsa.pub";,
-        "content": "-----BEGIN PUBLIC 
KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvasoSqEq9IKa4E+vcx7H\nijkwVuKbgG9vjds2+IJaQQoL/5EucLtYQ2dKSiizAnQmdb4EZIcj/M9DHFu8YlCW\nnTzrPinyj+pq8pRrAO3zj8GqZ5IjhC/pv2YdbwjRJHTijiT8miYiZflc2JyEuZb7\newuhEaB/VLcwaS8BIKG+QTjj7QDllhhqyiaeFJxs5ljSNl4EA6m+uSUCir7F+Jb5\nlM9n5b4SGB04p1w36a3eZMIT98jUqvWadxnGt+AeNDad3wT42d95xf4U303q+uwp\nwGqyIvltDR2OMfVqU5tvW7s3PytHuP25N+vUxjquwTj8GqQbaa/w5wl7+Mu8yZhT\nvlFVytrHTZSFqpPVbVgzprpb+HAu4tHohI9Z5G1NzKpKb4HmJe3QSOK1i7dPk8RU\nR2z2hPNfJ1fVn7rT6L3iyShqPxNLst9MT44StzEtrO6vL7mc4Fs0QD/nJJ/30Nyn\nTNsKywONj39cEnIyq6Df/RAfFWL1HbWNDl8w2xe2eqI3VSFGFIjoqNCUvy43jrZc\nzE/K7gqY3eKX6jNfKu1kCHU6YqXCf6S7p7PhcNYX+BaXT5rEuU2e0SDR1gT1gI8K\nNXELTNI4opfQ9JR7KhAwIOyQbUu/q22SDSNbrXp+9h85SGd7gfhqgzR9ivN03k4X\n7H5Er4P2M9cqgT66vN//8rECAwEAAQ==\n-----END
 PUBLIC KEY-----\n"
-      },
-      {
         "name": 
"apk.cgr.dev/chainguard/chainguard-7fb528a64a862d44bbea6069093f1fec29fa864ba7e9754828eeceed3f487239.rsa.pub",
         "url": 
"https://apk.cgr.dev/chainguard/chainguard-7fb528a64a862d44bbea6069093f1fec29fa864ba7e9754828eeceed3f487239.rsa.pub";,
         "content": "-----BEGIN PUBLIC 
KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnuH20LnWxNl54a7mjSb5\nPmJssMelKeFQUDfzWZSTwCfFpBHRFq4KLWcUByqtmKphXLRMLjy0xR4xux7oh8n2\nCLP1NBt6d5skqaqHNFW24BO0ThrXUbwZ6jCAI0s2xSBaEPMea4Ipn2hmqZLwox6C\nqLGbEsbtRrkKXHva4jqFCX8h8ThwdQuKCEfr/nSk5IV+fn1Uoo8WK89cMUxlj1NB\nB5rdeJCcVaNlZTt2/Zw917BY+tjodWovbIGtqvnflOa5R28R+Q6bBh9oCDvkR6IU\n38NyT7szld5QgD9ebl5sNOFwk4mJdCNdi1wK9kSrBM7D8YEsStmawezpfvhwV55S\nQJpjuo6zJab25RAzcZoj+YhpBSl91QNRaKK3x5RlqW93tBCtpDjfpNqEHgyzHjc1\n4N46SQBU1NamkYBStTwMluc56lwmmWdKfnZXU0vULxQjCyBBeNSpsz8joyO60htD\nG52ieJ+NIqCEX7ikabWGCUfvAtEXDDDmo17JTyNSarziEfBImEtTOt8P93V6nRr7\nDz1fWKQC1pv9eFn1aS2TK50hWEgKpB+lmTf/j8UGawAWHQFND1ndDqNaJnVP/DqR\n6dt7krjlrDVEGq4s3GJabYADKxh0vXt1J4gef07dfEtEa6Aj9hikVyv3bQMeqtMK\nk/o1spotQWzE9+rffQfaUl8CAwEAAQ==\n-----END
 PUBLIC KEY-----\n"
       },
       {
+        "name": 
"apk.cgr.dev/chainguard/chainguard-a758e63f677c21398431017ba63a5f1676378db460c8ee05bacf92d9227b1ba4.rsa.pub",
+        "url": 
"https://apk.cgr.dev/chainguard/chainguard-a758e63f677c21398431017ba63a5f1676378db460c8ee05bacf92d9227b1ba4.rsa.pub";,
+        "content": "-----BEGIN PUBLIC 
KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA75Fs9GZ+vxneIiuqUHgw\n32I2iGn9W+piZCYqO/kIs76fkh+/v4pESLL5jecqXMWi8LCYVkOh6y/zPPaEWrPp\ns2Ue4MKQ6AvItNmYK3g4zLY+Fy14jgIvmTflivRlKkKD/6Bm+SHdwk9ZicHjMwNA\n8JyUXGlCPbRmNrnMFKd+jMPSg2cUfyXCWVYyJcpVy82HUNNKmaX3FGWre/EYCFC+\nzXnwh2toogdcoLt4Q/UBHwsFPGLMj+hOWebQFaOKmUSH0jwwBhIMWbY07wz8Nsus\nUssCf/5NxabvQYGWPBgEHgXlgQKIapQ7BEgeC7gfYnl7wlDDczEgILaBNV7pgPAy\nZTgSewVbLzyeY/FOqLVzR+UU8PGiheXuib3MTtu08Shp3YAQ7mhtpdbH5TWbIo9R\nSOLr+KQHKxkR3vr5wREOFEh6uLeMRKXDS2HluFujcHcyEc2S7xMCoLY03Gj1u8/C\n1HiOrd2F7bdb9/W8DGm0DZ3sJNt4mzl01bCGAd/KVwN12rxSvg6xC6UI7gudNmGu\nv0t1oJ3J3LepvX4/1oZD7TEKT60dylowtwtmjPTUTWC1IKaoX12JPKcUy+dKHTzv\nK61WASFmD6lA6FvniJ6cNEHlsNTnfYxqq6hDTlQJ5N9ngXc3JRffkkI5CcYvKex3\nXkE6VrkMMBfL8HOyVM5VjDcCAwEAAQ==\n-----END
 PUBLIC KEY-----\n"
+      },
+      {
         "name": 
"apk.cgr.dev/chainguard/chainguard-e3fb44d055702ed0dddf0f2acb1a0a07fc6075967092b203c7aac7db801d65f4.rsa.pub",
         "url": 
"https://apk.cgr.dev/chainguard/chainguard-e3fb44d055702ed0dddf0f2acb1a0a07fc6075967092b203c7aac7db801d65f4.rsa.pub";,
         "content": "-----BEGIN PUBLIC 
KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs+GdB46rERN+mqR3jdGH\nAhrLuu4xxzcyIHQFDXXhFY4Cvzox2AI1/1Kv1UCZetce0w9QMgq35qGEWe61dykC\nLoShLZ1Wgr4OGbZW1J73UGdmYzYOWWJMeXSQ3cFSAFLS23ox72HEZQG7QwDApkjl\nIp9cjt4xpSu/A+25b7t8ZtJAdZgKd+yY8MLnOqxIOqgO2kHUTR+1F8QGBAQUC7AW\nu+1UkcsJbYz3wT61ybuYREGXadEUmJmef5cfCQ66eZ2q0tioSVSWiK9SQGKZwl3w\nb7XInD6UJGQxoj/f2NFzvS9gxG7Dzql4mx9boPHNbEU9X8sdVtoCBIA52Lv9dCLO\nQCVPvm9e+/l5WXlYvoEsAcRdTGlexOQkdAs0R2RjH/teqnU2D7WgjLmtor2Nk52R\nASzESzCyXiSfDH7yBpSuKPNpI4TXXnKnxgAawlz9V7TLLP54qwPpgJ8pxGHz5GaN\n5tikOt95O3If4MMoRbfjbNH0VQ0bAnMeQlE+qbWbLlLWlK3yQq9tbmApG4vVvdpc\nWKe0NPuoxnUkw1n7JQs70RxsJf3SJoC59Fio1mkl3QIsTMl+75IPfwBy3tmdYKQS\nbV5Cb0nnjuB9esVVnEmXUuAS27TQlQJcu2kpV/Uccwv0+4Df3F61MWlTLvjfkXZm\n6uEiubGXOuhXv+QtsNwYGlECAwEAAQ==\n-----END
 PUBLIC KEY-----\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-1.2.29/pkg/build/build_implementation.go 
new/apko-1.2.30/pkg/build/build_implementation.go
--- old/apko-1.2.29/pkg/build/build_implementation.go   2026-07-24 
15:46:38.000000000 +0200
+++ new/apko-1.2.30/pkg/build/build_implementation.go   2026-07-30 
20:33:18.000000000 +0200
@@ -198,6 +198,12 @@
                return nil, fmt.Errorf("failed to install certificates: %w", 
err)
        }
 
+       // Record checksums of the (possibly updated) CA bundles so downstream
+       // tooling (e.g. OpenSCAP) can verify they were not modified post-build.
+       if err := bc.writeCABundleChecksums(ctx); err != nil {
+               return nil, fmt.Errorf("failed to write CA bundle checksums: 
%w", err)
+       }
+
        if err := bc.installRuntimeKeyring(ctx); err != nil {
                return nil, fmt.Errorf("failed to install runtime keyring: %w", 
err)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-1.2.29/pkg/build/build_test.go 
new/apko-1.2.30/pkg/build/build_test.go
--- old/apko-1.2.29/pkg/build/build_test.go     2026-07-24 15:46:38.000000000 
+0200
+++ new/apko-1.2.30/pkg/build/build_test.go     2026-07-30 20:33:18.000000000 
+0200
@@ -16,6 +16,9 @@
 
 import (
        "context"
+       "crypto/sha256"
+       "encoding/hex"
+       "fmt"
        "net/http"
        "net/http/httptest"
        "path/filepath"
@@ -179,6 +182,18 @@
                _, err := fsys.Stat(p)
                require.NoError(t, err, "cert file %s should exist", p)
        }
+
+       // A sha256 sidecar should be written next to the bundle, in sha256sum 
-c
+       // format, matching the final (post-append) contents of the bundle.
+       sidecarPath := "etc/ssl/certs/.ca-certificates.crt.sha256"
+       sidecarData, err := fsys.ReadFile(sidecarPath)
+       require.NoError(t, err, "CA bundle checksum sidecar should exist at 
%s", sidecarPath)
+
+       sum := sha256.Sum256(bundleData)
+       require.Equal(t,
+               fmt.Sprintf("%s  ca-certificates.crt\n", 
hex.EncodeToString(sum[:])),
+               string(sidecarData),
+               "sidecar must record the sha256 of the updated bundle")
 }
 
 func TestBuildImageFromLockFile(t *testing.T) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-1.2.29/pkg/build/certificates.go 
new/apko-1.2.30/pkg/build/certificates.go
--- old/apko-1.2.29/pkg/build/certificates.go   2026-07-24 15:46:38.000000000 
+0200
+++ new/apko-1.2.30/pkg/build/certificates.go   2026-07-30 20:33:18.000000000 
+0200
@@ -260,6 +260,59 @@
        return nil
 }
 
+// caBundleChecksumSidecar returns the sidecar checksum path for a given CA
+// bundle path, e.g. "etc/ssl/certs/ca-certificates.crt" becomes
+// "etc/ssl/certs/.ca-certificates.crt.sha256".
+func caBundleChecksumSidecar(bundlePath string) string {
+       return filepath.Join(filepath.Dir(bundlePath), 
"."+filepath.Base(bundlePath)+".sha256")
+}
+
+// writeCABundleChecksums writes a sha256sum-compatible sidecar file next to 
each
+// existing CA bundle and Java truststore so that downstream integrity tooling
+// (e.g. OpenSCAP) can later verify they have not been modified since build 
time.
+// It runs unconditionally after certificate installation, so every image that
+// ships a CA bundle or truststore gets a baseline, whether or not additional
+// certificates were configured.
+func (bc *Context) writeCABundleChecksums(ctx context.Context) error {
+       _, span := otel.Tracer("apko").Start(ctx, "writeCABundleChecksums")
+       defer span.End()
+
+       builtTime, err := bc.GetBuildDateEpoch()
+       if err != nil {
+               return fmt.Errorf("failed to get build date epoch: %w", err)
+       }
+
+       // PEM CA bundles plus the binary Java truststore(s). For the 
truststore the
+       // checksum is a plain file-level hash of the JKS keystore as written.
+       for _, bundlePath := range slices.Concat(caBundlePaths, 
javaTruststorePaths) {
+               data, err := bc.fs.ReadFile(bundlePath)
+               if err != nil {
+                       if errors.Is(err, fs.ErrNotExist) {
+                               // No file at this path, nothing to checksum.
+                               continue
+                       }
+                       return fmt.Errorf("failed to read certificate store %s: 
%w", bundlePath, err)
+               }
+
+               sum := sha256.Sum256(data)
+               // sha256sum-compatible line ("<hex>  <basename>\n"). Using the 
basename
+               // keeps the sidecar verifiable with `sha256sum -c` from the 
file's dir.
+               line := fmt.Sprintf("%s  %s\n", hex.EncodeToString(sum[:]), 
filepath.Base(bundlePath))
+
+               sidecar := caBundleChecksumSidecar(bundlePath)
+               // Read-only (r--r--r--): a baseline that shouldn't be casually
+               // overwritten, matching the mode used for /etc/apko.json.
+               if err := bc.fs.WriteFile(sidecar, []byte(line), 0o444); err != 
nil {
+                       return fmt.Errorf("failed to write certificate store 
checksum %s: %w", sidecar, err)
+               }
+               if err := bc.fs.Chtimes(sidecar, builtTime, builtTime); err != 
nil {
+                       return fmt.Errorf("failed to change times on 
certificate store checksum %s: %w", sidecar, err)
+               }
+       }
+
+       return nil
+}
+
 // loadJavaTruststores loads all existing Java truststores from the configured 
paths.
 // It is ok if no truststores exist; in that case, an empty slice is returned.
 func (bc *Context) loadJavaTruststores() ([]loadedTruststore, error) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/apko-1.2.29/pkg/build/certificates_test.go 
new/apko-1.2.30/pkg/build/certificates_test.go
--- old/apko-1.2.29/pkg/build/certificates_test.go      2026-07-24 
15:46:38.000000000 +0200
+++ new/apko-1.2.30/pkg/build/certificates_test.go      2026-07-30 
20:33:18.000000000 +0200
@@ -18,9 +18,12 @@
        "archive/tar"
        "bytes"
        "context"
+       "crypto/sha256"
+       "encoding/hex"
        "fmt"
        "io/fs"
        "path/filepath"
+       "slices"
        "strings"
        "testing"
        "time"
@@ -648,3 +651,86 @@
                })
        }
 }
+
+func TestWriteCABundleChecksums(t *testing.T) {
+       epoch := time.Unix(1337, 0)
+       t.Setenv("SOURCE_DATE_EPOCH", fmt.Sprintf("%d", epoch.Unix()))
+
+       // sha256sum -c compatible line for the given content and basename.
+       sumLine := func(content []byte, name string) []byte {
+               sum := sha256.Sum256(content)
+               return fmt.Appendf(nil, "%s  %s\n", hex.EncodeToString(sum[:]), 
name)
+       }
+
+       bundle := []byte("-----BEGIN CERTIFICATE-----\nbundle\n-----END 
CERTIFICATE-----\n")
+       awsBundle := []byte("-----BEGIN CERTIFICATE-----\naws\n-----END 
CERTIFICATE-----\n")
+       truststore := []byte("not-really-jks-but-bytes-are-hashed-as-is")
+
+       fsys := apkfs.NewMemFS()
+       existing := map[string][]byte{
+               caBundlePaths[0]:       bundle,     // 
etc/ssl/certs/ca-certificates.crt
+               caBundlePaths[1]:       awsBundle,  // AWS ECS bundle
+               javaTruststorePaths[0]: truststore, // Java cacerts
+       }
+       for path, content := range existing {
+               if err := fsys.MkdirAll(filepath.Dir(path), 0o755); err != nil {
+                       t.Fatalf("failed to create dir for %s: %v", path, err)
+               }
+               if err := fsys.WriteFile(path, content, 0o644); err != nil {
+                       t.Fatalf("failed to write %s: %v", path, err)
+               }
+       }
+
+       bc := &Context{
+               o:  options.Options{SourceDateEpoch: epoch},
+               fs: fsys,
+       }
+       if err := bc.writeCABundleChecksums(context.Background()); err != nil {
+               t.Fatalf("writeCABundleChecksums() error = %v", err)
+       }
+
+       wantSidecars := map[string][]byte{
+               caBundleChecksumSidecar(caBundlePaths[0]):       
sumLine(bundle, "ca-certificates.crt"),
+               caBundleChecksumSidecar(caBundlePaths[1]):       
sumLine(awsBundle, "tls-ca-bundle.pem"),
+               caBundleChecksumSidecar(javaTruststorePaths[0]): 
sumLine(truststore, "cacerts"),
+       }
+       for path, want := range wantSidecars {
+               got, err := fsys.ReadFile(path)
+               if err != nil {
+                       t.Fatalf("expected sidecar %s: %v", path, err)
+               }
+               if diff := cmp.Diff(want, got); diff != "" {
+                       t.Errorf("sidecar content mismatch for %s (-want 
+got):\n%s", path, diff)
+               }
+               stat, err := fsys.Stat(path)
+               if err != nil {
+                       t.Fatalf("failed to stat sidecar %s: %v", path, err)
+               }
+               if stat.Mode().Perm() != 0o444 {
+                       t.Errorf("sidecar %s has mode %v, want 0444", path, 
stat.Mode().Perm())
+               }
+               if !stat.ModTime().Equal(epoch) {
+                       t.Errorf("sidecar %s has mod time %v, want %v", path, 
stat.ModTime(), epoch)
+               }
+       }
+}
+
+func TestWriteCABundleChecksumsNoBundles(t *testing.T) {
+       epoch := time.Unix(1337, 0)
+       t.Setenv("SOURCE_DATE_EPOCH", fmt.Sprintf("%d", epoch.Unix()))
+
+       fsys := apkfs.NewMemFS()
+       bc := &Context{
+               o:  options.Options{SourceDateEpoch: epoch},
+               fs: fsys,
+       }
+       // No bundles present: should be a no-op, not an error.
+       if err := bc.writeCABundleChecksums(context.Background()); err != nil {
+               t.Fatalf("writeCABundleChecksums() error = %v", err)
+       }
+       for _, p := range slices.Concat(caBundlePaths, javaTruststorePaths) {
+               if _, err := fsys.Stat(caBundleChecksumSidecar(p)); err == nil {
+                       t.Errorf("unexpected sidecar created for missing bundle 
%s", p)
+               }
+       }
+}

++++++ apko.obsinfo ++++++
--- /var/tmp/diff_new_pack.PnEp56/_old  2026-08-01 18:35:16.136096764 +0200
+++ /var/tmp/diff_new_pack.PnEp56/_new  2026-08-01 18:35:16.168097865 +0200
@@ -1,5 +1,5 @@
 name: apko
-version: 1.2.29
-mtime: 1784900798
-commit: e3915900849d95b35f1f5b7c7401922505332152
+version: 1.2.30
+mtime: 1785436398
+commit: 502643080cb38d339c5804fe7e62c9a5bd46b6d5
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/apko/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.apko.new.16738/vendor.tar.gz differ: char 31, line 1

Reply via email to