Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package forgejo-runner for openSUSE:Factory 
checked in at 2026-03-26 21:09:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/forgejo-runner (Old)
 and      /work/SRC/openSUSE:Factory/.forgejo-runner.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "forgejo-runner"

Thu Mar 26 21:09:45 2026 rev:42 rq:1342725 version:12.7.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/forgejo-runner/forgejo-runner.changes    
2026-03-17 19:07:32.472239766 +0100
+++ /work/SRC/openSUSE:Factory/.forgejo-runner.new.8177/forgejo-runner.changes  
2026-03-27 06:39:46.741919992 +0100
@@ -1,0 +2,7 @@
+Thu Mar 26 08:18:42 UTC 2026 - Richard Rahl <[email protected]>
+
+- Update to version 12.7.3:
+  * feat: set a custom user-agent header for all gRPC requests
+  * fix: replace logger.Panicf with panics that have a useful error message
+
+-------------------------------------------------------------------

Old:
----
  _servicedata
  forgejo-runner-12.7.2.obscpio

New:
----
  forgejo-runner-12.7.3.obscpio

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

Other differences:
------------------
++++++ forgejo-runner.spec ++++++
--- /var/tmp/diff_new_pack.L6iB21/_old  2026-03-27 06:39:47.597954920 +0100
+++ /var/tmp/diff_new_pack.L6iB21/_new  2026-03-27 06:39:47.601955083 +0100
@@ -18,7 +18,7 @@
 
 %define services %{name}.service
 Name:           forgejo-runner
-Version:        12.7.2
+Version:        12.7.3
 Release:        0
 Summary:        Daemon that connects to a Forgejo instance and runs CI jobs
 License:        GPL-3.0-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.L6iB21/_old  2026-03-27 06:39:47.641956715 +0100
+++ /var/tmp/diff_new_pack.L6iB21/_new  2026-03-27 06:39:47.649957042 +0100
@@ -2,7 +2,7 @@
   <service name="obs_scm" mode="manual">
     <param name="url">https://code.forgejo.org/forgejo/runner</param>
     <param name="scm">git</param>
-    <param name="revision">refs/tags/v12.7.2</param>
+    <param name="revision">refs/tags/v12.7.3</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">disable</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ forgejo-runner-12.7.2.obscpio -> forgejo-runner-12.7.3.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/forgejo-runner-12.7.2/.forgejo/workflows/build-release-integration.yml 
new/forgejo-runner-12.7.3/.forgejo/workflows/build-release-integration.yml
--- old/forgejo-runner-12.7.2/.forgejo/workflows/build-release-integration.yml  
2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/.forgejo/workflows/build-release-integration.yml  
2026-03-24 15:02:59.000000000 +0100
@@ -19,7 +19,7 @@
 enable-email-notifications: true
 
 env:
-  FORGEJO_VERSION: 11.0.10 # renovate: datasource=docker 
depName=data.forgejo.org/forgejo/forgejo
+  FORGEJO_VERSION: 11.0.11 # renovate: datasource=docker 
depName=data.forgejo.org/forgejo/forgejo
 
 jobs:
   release-simulation:
@@ -29,7 +29,7 @@
       - uses:  https://data.forgejo.org/actions/checkout@v4
 
       - id: forgejo
-        uses: https://data.forgejo.org/actions/[email protected]
+        uses: https://data.forgejo.org/actions/[email protected]
         with:
           user: root
           password: admin1234
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/forgejo-runner-12.7.2/.forgejo/workflows/docker-build-push-action-in-lxc.yml
 
new/forgejo-runner-12.7.3/.forgejo/workflows/docker-build-push-action-in-lxc.yml
--- 
old/forgejo-runner-12.7.2/.forgejo/workflows/docker-build-push-action-in-lxc.yml
    2026-03-09 17:04:00.000000000 +0100
+++ 
new/forgejo-runner-12.7.3/.forgejo/workflows/docker-build-push-action-in-lxc.yml
    2026-03-24 15:02:59.000000000 +0100
@@ -21,7 +21,7 @@
 enable-email-notifications: true
 
 env:
-  FORGEJO_VERSION: 11.0.10 # renovate: datasource=docker 
depName=data.forgejo.org/forgejo/forgejo
+  FORGEJO_VERSION: 11.0.11 # renovate: datasource=docker 
depName=data.forgejo.org/forgejo/forgejo
   FORGEJO_USER: root
   FORGEJO_PASSWORD: admin1234
 
@@ -34,7 +34,7 @@
 
       - name: install Forgejo so it can be used as a container registry
         id: registry
-        uses: https://data.forgejo.org/actions/[email protected]
+        uses: https://data.forgejo.org/actions/[email protected]
         with:
           user: ${{ env.FORGEJO_USER }}
           password: ${{ env.FORGEJO_PASSWORD }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/forgejo-runner-12.7.2/.forgejo/workflows/example-lxc-systemd.yml 
new/forgejo-runner-12.7.3/.forgejo/workflows/example-lxc-systemd.yml
--- old/forgejo-runner-12.7.2/.forgejo/workflows/example-lxc-systemd.yml        
2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/.forgejo/workflows/example-lxc-systemd.yml        
2026-03-24 15:02:59.000000000 +0100
@@ -14,7 +14,7 @@
   SERIAL: "30"
   LIFETIME: "60"
   SYSTEMD_OPTIONS: "--no-pager --full"
-  USE_VERSION: 11.0.10 # renovate: datasource=docker 
depName=data.forgejo.org/forgejo/forgejo
+  USE_VERSION: 11.0.11 # renovate: datasource=docker 
depName=data.forgejo.org/forgejo/forgejo
 
 jobs:
   example-lxc-systemd:
@@ -54,7 +54,7 @@
            done
 
        - id: forgejo
-         uses: https://data.forgejo.org/actions/[email protected]
+         uses: https://data.forgejo.org/actions/[email protected]
          with:
            user: root
            password: admin1234
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/forgejo-runner-12.7.2/.forgejo/workflows/example-on-demand.yml 
new/forgejo-runner-12.7.3/.forgejo/workflows/example-on-demand.yml
--- old/forgejo-runner-12.7.2/.forgejo/workflows/example-on-demand.yml  
2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/.forgejo/workflows/example-on-demand.yml  
2026-03-24 15:02:59.000000000 +0100
@@ -29,7 +29,7 @@
 
       - uses: https://data.forgejo.org/actions/checkout@v5
 
-      - uses: https://data.forgejo.org/actions/[email protected]
+      - uses: https://data.forgejo.org/actions/[email protected]
         with:
           user: "${{ env.username }}"
           password: "${{ env.password }}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/Makefile 
new/forgejo-runner-12.7.3/Makefile
--- old/forgejo-runner-12.7.2/Makefile  2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/Makefile  2026-03-24 15:02:59.000000000 +0100
@@ -14,7 +14,7 @@
 GOFILES := $(shell find . -type f -name "*.go" -o -name "go.mod" ! -name 
"generated.*")
 
 MOCKERY_PACKAGE ?= github.com/vektra/mockery/[email protected] # renovate: 
datasource=go
-GOLANGCI_LINT_PACKAGE ?= 
github.com/golangci/golangci-lint/v2/cmd/[email protected] # renovate: 
datasource=go
+GOLANGCI_LINT_PACKAGE ?= 
github.com/golangci/golangci-lint/v2/cmd/[email protected] # renovate: 
datasource=go
 
 DOCKER_IMAGE ?= gitea/act_runner
 DOCKER_TAG ?= nightly
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/act/artifactcache/handler.go 
new/forgejo-runner-12.7.3/act/artifactcache/handler.go
--- old/forgejo-runner-12.7.2/act/artifactcache/handler.go      2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/act/artifactcache/handler.go      2026-03-24 
15:02:59.000000000 +0100
@@ -25,7 +25,7 @@
 var fatal = func(logger logrus.FieldLogger, err error) {
        logger.Errorf("unrecoverable error in the cache: %v", err)
        if err := common.Suicide(common.CacheUnrecoverableError); err != nil {
-               logger.Panicf("unrecoverable error in the cache: failed to send 
the TERM signal to shutdown the daemon %v", err)
+               panic(fmt.Sprintf("unrecoverable error in the cache: failed to 
send the TERM signal to shutdown the daemon %v", err))
        }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/act/common/git/git.go 
new/forgejo-runner-12.7.3/act/common/git/git.go
--- old/forgejo-runner-12.7.2/act/common/git/git.go     2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/act/common/git/git.go     2026-03-24 
15:02:59.000000000 +0100
@@ -2,6 +2,7 @@
 
 import (
        "context"
+       "encoding/base64"
        "errors"
        "fmt"
        "net/url"
@@ -9,6 +10,7 @@
        "os/exec"
        "path/filepath"
        "regexp"
+       "runtime"
        "strings"
 
        log "github.com/sirupsen/logrus"
@@ -442,41 +444,16 @@
                        return "", fmt.Errorf("failed to parse remote URL %q to 
use git token: %w", options.remoteURL, err)
                }
 
-               credentialsFile, err := os.CreateTemp("", 
"forgejo-runner-git-token-")
-               if err != nil {
-                       return "", fmt.Errorf("failed to create temporary file 
to store Git token: %w", err)
-               }
-
-               credentialsPath := credentialsFile.Name()
-               defer func() {
-                       _ = credentialsFile.Close()
-                       if err := os.Remove(credentialsPath); err != nil {
-                               log.Warnf("Unable to remove temporary file to 
store Git token %s: %v", credentialsPath, err)
-                       }
-               }()
-
-               // Git credential store expects an URL with embedded 
credentials.
-               // Use a fixed username to keep behaviour consistent across 
providers.
-               remoteURL.User = url.UserPassword("x-access-token", 
options.token)
-               if remoteURL.Path == "" {
-                       remoteURL.Path = "/"
-               }
-
-               _, err = credentialsFile.Write([]byte(remoteURL.String() + 
"\n"))
-               if err != nil {
-                       return "", fmt.Errorf("failed to write Git token to 
temporary file %s: %w", credentialsPath, err)
-               }
-               err = credentialsFile.Close()
-               if err != nil {
-                       return "", fmt.Errorf("failed to close temporary file 
%s that stores Git token: %w", credentialsPath, err)
-               }
-
-               gitArguments = append(gitArguments, "-c", 
fmt.Sprintf("credential.helper=store --file=%s", credentialsPath))
-               gitArguments = append(gitArguments, "-c", 
"credential.useHttpPath=true")
+               const envVarName = "GIT_AUTH_HEADER"
+               scopedExtraHeader := fmt.Sprintf("http.%s://%s/.extraHeader", 
remoteURL.Scheme, remoteURL.Host)
+               gitArguments = append(gitArguments, "--config-env", 
fmt.Sprintf("%s=%s", scopedExtraHeader, envVarName))
        }
        if options.ignoreInvalidCertificates {
                gitArguments = append(gitArguments, "-c", 
"http.sslVerify=false")
        }
+       if runtime.GOOS == "windows" {
+               gitArguments = append(gitArguments, "-c", "core.longpaths=true")
+       }
        if options.workingDirectory != "" {
                gitArguments = append(gitArguments, "-C", 
options.workingDirectory)
        }
@@ -487,6 +464,13 @@
        logger.Debugf("  git %s", strings.Join(gitArguments, " "))
 
        cmd := exec.CommandContext(ctx, "git", gitArguments...)
+
+       if options.token != "" {
+               auth := "x-access-token:" + options.token
+               authHeader := "Authorization: Basic " + 
base64.StdEncoding.EncodeToString([]byte(auth))
+               cmd.Env = append(os.Environ(), "GIT_AUTH_HEADER="+authHeader)
+       }
+
        output, err := cmd.Output()
        trimmedOutput := strings.TrimSpace(string(output))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/act/common/git/git_test.go 
new/forgejo-runner-12.7.3/act/common/git/git_test.go
--- old/forgejo-runner-12.7.2/act/common/git/git_test.go        2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/act/common/git/git_test.go        2026-03-24 
15:02:59.000000000 +0100
@@ -747,7 +747,6 @@
        }))
        defer srv.Close()
 
-       // Any path is fine; useHttpPath=true makes git include the path in 
credential lookup.
        url := srv.URL + "/org/repo"
 
        _, err := Clone(t.Context(), CloneInput{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/act/container/docker_run.go 
new/forgejo-runner-12.7.3/act/container/docker_run.go
--- old/forgejo-runner-12.7.2/act/container/docker_run.go       2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/act/container/docker_run.go       2026-03-24 
15:02:59.000000000 +0100
@@ -103,16 +103,13 @@
 // supportsContainerImagePlatform returns true if the underlying Docker server
 // API version is 1.41 and beyond
 func supportsContainerImagePlatform(ctx context.Context, cli client.APIClient) 
bool {
-       logger := common.Logger(ctx)
        ver, err := cli.ServerVersion(ctx)
        if err != nil {
-               logger.Panicf("Failed to get Docker API Version: %s", err)
-               return false
+               panic(fmt.Sprintf("Failed to get Docker API Version: %s", err))
        }
        sv, err := semver.NewVersion(ver.APIVersion)
        if err != nil {
-               logger.Panicf("Failed to unmarshal Docker Version: %s", err)
-               return false
+               panic(fmt.Sprintf("Failed to unmarshal Docker Version: %s", 
err))
        }
        constraint, _ := semver.NewConstraint(">= 1.41")
        return constraint.Check(sv)
@@ -121,16 +118,13 @@
 // supportsImageInspectPlatform returns true if the underlying Docker server 
supports using
 // `client.ImageInspectWithPlatform`, which is API version 1.49 and beyond.
 func supportsImageInspectPlatform(ctx context.Context, cli client.APIClient) 
bool {
-       logger := common.Logger(ctx)
        ver, err := cli.ServerVersion(ctx)
        if err != nil {
-               logger.Panicf("Failed to get Docker API Version: %s", err)
-               return false
+               panic(fmt.Sprintf("Failed to get Docker API Version: %s", err))
        }
        sv, err := semver.NewVersion(ver.APIVersion)
        if err != nil {
-               logger.Panicf("Failed to unmarshal Docker Version: %s", err)
-               return false
+               panic(fmt.Sprintf("Failed to unmarshal Docker Version: %s", 
err))
        }
        constraint, _ := semver.NewConstraint(">= 1.49")
        return constraint.Check(sv)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/forgejo-runner-12.7.2/examples/docker-compose/compose-forgejo-and-runner.yml
 
new/forgejo-runner-12.7.3/examples/docker-compose/compose-forgejo-and-runner.yml
--- 
old/forgejo-runner-12.7.2/examples/docker-compose/compose-forgejo-and-runner.yml
    2026-03-09 17:04:00.000000000 +0100
+++ 
new/forgejo-runner-12.7.3/examples/docker-compose/compose-forgejo-and-runner.yml
    2026-03-24 15:02:59.000000000 +0100
@@ -51,7 +51,7 @@
       - 8080:3000
 
   runner-register:
-    image: data.forgejo.org/forgejo/runner:12.7.1
+    image: data.forgejo.org/forgejo/runner:12.7.2
     links:
       - docker-in-docker
       - forgejo
@@ -77,7 +77,7 @@
       '
 
   runner-daemon:
-    image: data.forgejo.org/forgejo/runner:12.7.1
+    image: data.forgejo.org/forgejo/runner:12.7.2
     links:
       - docker-in-docker
       - forgejo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/forgejo-runner-12.7.2/examples/lxc-systemd/forgejo-runner-service.sh 
new/forgejo-runner-12.7.3/examples/lxc-systemd/forgejo-runner-service.sh
--- old/forgejo-runner-12.7.2/examples/lxc-systemd/forgejo-runner-service.sh    
2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/examples/lxc-systemd/forgejo-runner-service.sh    
2026-03-24 15:02:59.000000000 +0100
@@ -22,7 +22,7 @@
 : ${INPUTS_LIFETIME:=7d}
 DEFAULT_LXC_HELPERS_VERSION=1.1.3 # renovate: datasource=forgejo-tags 
depName=forgejo/lxc-helpers
 : ${INPUTS_LXC_HELPERS_VERSION:=$DEFAULT_LXC_HELPERS_VERSION}
-DEFAULT_RUNNER_VERSION=12.7.1 # renovate: datasource=forgejo-releases 
depName=forgejo/runner
+DEFAULT_RUNNER_VERSION=12.7.2 # renovate: datasource=forgejo-releases 
depName=forgejo/runner
 : ${INPUTS_RUNNER_VERSION:=$DEFAULT_RUNNER_VERSION}
 
 : ${KILL_AFTER:=21600} # 6h == 21600
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/go.mod 
new/forgejo-runner-12.7.3/go.mod
--- old/forgejo-runner-12.7.2/go.mod    2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/go.mod    2026-03-24 15:02:59.000000000 +0100
@@ -31,6 +31,7 @@
        github.com/moby/patternmatcher v0.6.0
        github.com/opencontainers/image-spec v1.1.1
        github.com/opencontainers/selinux v1.13.0
+       github.com/powerman/fileuri v0.2.0
        github.com/rhysd/actionlint v1.7.10
        github.com/sirupsen/logrus v1.9.4
        github.com/spf13/cobra v1.10.2
@@ -40,7 +41,7 @@
        go.etcd.io/bbolt v1.4.3
        go.yaml.in/yaml/v3 v3.0.4
        golang.org/x/sys v0.42.0
-       golang.org/x/term v0.40.0
+       golang.org/x/term v0.41.0
        golang.org/x/time v0.15.0
        google.golang.org/protobuf v1.36.11
        gotest.tools/v3 v3.5.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/go.sum 
new/forgejo-runner-12.7.3/go.sum
--- old/forgejo-runner-12.7.2/go.sum    2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/go.sum    2026-03-24 15:02:59.000000000 +0100
@@ -160,6 +160,8 @@
 github.com/pkg/errors v0.9.1/go.mod 
h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 
h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod 
h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/powerman/fileuri v0.2.0 
h1:+CsMkkrY8HtSXUpoZNp2F53R20hA7caiBjpU2jYnY1g=
+github.com/powerman/fileuri v0.2.0/go.mod 
h1:nFHerdvcP+wa5FNgLCbXpG4wdZfHSswr2O4dpggGFTs=
 github.com/rhysd/actionlint v1.7.10 
h1:FL3XIEs72G4/++168vlv5FKOWMSWvWIQw1kBCadyOcM=
 github.com/rhysd/actionlint v1.7.10/go.mod 
h1:ZHX/hrmknlsJN73InPTKsKdXpAv9wVdrJy8h8HAwFHg=
 github.com/rivo/uniseg v0.2.0/go.mod 
h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -255,8 +257,8 @@
 golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
 golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod 
h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
-golang.org/x/term v0.40.0/go.mod 
h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
+golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
+golang.org/x/term v0.41.0/go.mod 
h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
 golang.org/x/text v0.31.0/go.mod 
h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/internal/app/cmd/cmd.go 
new/forgejo-runner-12.7.3/internal/app/cmd/cmd.go
--- old/forgejo-runner-12.7.2/internal/app/cmd/cmd.go   2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/internal/app/cmd/cmd.go   2026-03-24 
15:02:59.000000000 +0100
@@ -55,7 +55,9 @@
                Use:   "one-job",
                Short: "Run only one job",
                Args:  cobra.MaximumNArgs(1),
-               RunE:  runJob(ctx, &configFile, &runJobArgs),
+               RunE: func(cmd *cobra.Command, args []string) error {
+                       return runJob(ctx, &configFile, &runJobArgs)
+               },
        }
        jobCmd.Flags().BoolVarP(&runJobArgs.wait, "wait", "w", false, "waits 
until task has been assigned")
        rootCmd.AddCommand(jobCmd)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/internal/app/cmd/job.go 
new/forgejo-runner-12.7.3/internal/app/cmd/job.go
--- old/forgejo-runner-12.7.2/internal/app/cmd/job.go   2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/internal/app/cmd/job.go   2026-03-24 
15:02:59.000000000 +0100
@@ -6,107 +6,75 @@
 import (
        "context"
        "fmt"
-       "os"
-       "strings"
 
        log "github.com/sirupsen/logrus"
-       "github.com/spf13/cobra"
 
        "code.forgejo.org/forgejo/runner/v12/act/cacheproxy"
        "code.forgejo.org/forgejo/runner/v12/internal/app/job"
        "code.forgejo.org/forgejo/runner/v12/internal/app/run"
-       "code.forgejo.org/forgejo/runner/v12/internal/pkg/client"
        "code.forgejo.org/forgejo/runner/v12/internal/pkg/config"
-       "code.forgejo.org/forgejo/runner/v12/internal/pkg/envcheck"
-       "code.forgejo.org/forgejo/runner/v12/internal/pkg/ver"
 )
 
 type runJobArgs struct {
        wait bool
 }
 
-func runJob(ctx context.Context, configFile *string, runJobArgs *runJobArgs) 
func(cmd *cobra.Command, args []string) error {
-       return func(cmd *cobra.Command, args []string) error {
-               cfg, err := config.New(
-                       config.FromFile(*configFile),
-                       config.FromRegistration,
-               )
-               if err != nil {
-                       return fmt.Errorf("invalid configuration: %w", err)
-               } else if len(cfg.Server.Connections) != 1 {
-                       return fmt.Errorf("one-job is only supported with a 
single connection, but %d connections are configured", 
len(cfg.Server.Connections))
-               }
-
-               var connName string
-               var conn *config.Connection
-               for name, c := range cfg.Server.Connections {
-                       connName = name
-                       conn = c
-               }
-
-               initLogging(cfg)
-               log.Infoln("Starting job")
-
-               requireDocker := false
-               for _, conn := range cfg.Server.Connections {
-                       if conn.Labels.RequireDocker() {
-                               requireDocker = true
-                               break
-                       }
-               }
-               if requireDocker {
-                       dockerSocketPath, err := 
getDockerSocketPath(cfg.Container.DockerHost)
-                       if err != nil {
-                               return err
-                       }
-                       if err := envcheck.CheckIfDockerRunning(ctx, 
dockerSocketPath); err != nil {
-                               return err
-                       }
-                       // if dockerSocketPath passes the check, override 
DOCKER_HOST with dockerSocketPath
-                       os.Setenv("DOCKER_HOST", dockerSocketPath)
-                       // cfg.Container.DockerHost set to "automount" means 
act_runner need to find an available docker host automatically
-                       // and assign the path to cfg.Container.DockerHost
-                       if cfg.Container.DockerHost == "automount" {
-                               cfg.Container.DockerHost = dockerSocketPath
-                       }
-                       // check the scheme, if the scheme is not npipe or unix
-                       // set cfg.Container.DockerHost to "-" because it can't 
be mounted to the job container
-                       if protoIndex := 
strings.Index(cfg.Container.DockerHost, "://"); protoIndex != -1 {
-                               scheme := cfg.Container.DockerHost[:protoIndex]
-                               if !strings.EqualFold(scheme, "npipe") && 
!strings.EqualFold(scheme, "unix") {
-                                       cfg.Container.DockerHost = "-"
-                               }
-                       }
-               }
+var initializeRunJobConfig = func(configFile *string) (*config.Config, error) {
+       cfg, err := config.New(
+               config.FromFile(*configFile),
+               config.FromRegistration,
+       )
+       if err != nil {
+               return nil, fmt.Errorf("invalid configuration: %w", err)
+       }
+       return cfg, nil
+}
 
-               cli := client.New(
-                       conn.URL.String(),
-                       cfg.Runner.Insecure,
-                       conn.UUID.String(),
-                       conn.Token,
-                       ver.Version(),
-                       conn.FetchInterval,
-               )
-
-               var cacheProxy *cacheproxy.Handler
-               if cfg.Cache.Enabled {
-                       cacheProxy = run.SetupCache(cfg)
-                       defer func() {
-                               if cacheProxy != nil {
-                                       err := cacheProxy.Close()
-                                       if err != nil {
-                                               
log.WithError(err).Error("failed to close cache")
-                                       }
-                               }
-                       }()
-               }
+func runJob(ctx context.Context, configFile *string, runJobArgs *runJobArgs) 
error {
+       cfg, err := initializeRunJobConfig(configFile)
+       if err != nil {
+               return err
+       } else if len(cfg.Server.Connections) != 1 {
+               return fmt.Errorf("one-job is only supported with a single 
connection, but %d connections are configured", len(cfg.Server.Connections))
+       }
 
-               runner, _, _, err := createRunner(ctx, connName, cfg, cli, 
conn.Labels, cacheProxy)
-               if err != nil {
-                       return err
-               }
+       var connName string
+       var conn *config.Connection
+       for name, c := range cfg.Server.Connections {
+               connName = name
+               conn = c
 
-               j := job.NewJob(cfg, cli, runner)
-               return j.Run(ctx, runJobArgs.wait)
+               // We always take the first (and only) connection.
+               break
        }
+
+       initLogging(cfg)
+       log.Infoln("Starting job")
+
+       err = configCheck(ctx, cfg)
+       if err != nil {
+               return err
+       }
+
+       var cacheProxy *cacheproxy.Handler
+       if cfg.Cache.Enabled {
+               cacheProxy = run.SetupCache(cfg)
+               defer func() {
+                       if cacheProxy != nil {
+                               err := cacheProxy.Close()
+                               if err != nil {
+                                       log.WithError(err).Error("failed to 
close cache")
+                               }
+                       }
+               }()
+       }
+
+       client := createClient(cfg, conn)
+       runner, _, _, err := createRunner(ctx, connName, cfg, client, 
conn.Labels, cacheProxy)
+       if err != nil {
+               return err
+       }
+
+       j := job.NewJob(cfg, client, runner)
+       return j.Run(ctx, runJobArgs.wait)
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/internal/app/cmd/job_test.go 
new/forgejo-runner-12.7.3/internal/app/cmd/job_test.go
--- old/forgejo-runner-12.7.2/internal/app/cmd/job_test.go      1970-01-01 
01:00:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/internal/app/cmd/job_test.go      2026-03-24 
15:02:59.000000000 +0100
@@ -0,0 +1,88 @@
+// Copyright 2026 The Forgejo Authors
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package cmd
+
+import (
+       "context"
+       "os"
+       "path/filepath"
+       "testing"
+
+       runnerv1 "code.forgejo.org/forgejo/actions-proto/runner/v1"
+       "code.forgejo.org/forgejo/runner/v12/act/cacheproxy"
+       "code.forgejo.org/forgejo/runner/v12/internal/app/run"
+       mock_runner "code.forgejo.org/forgejo/runner/v12/internal/app/run/mocks"
+       "code.forgejo.org/forgejo/runner/v12/internal/pkg/client"
+       mock_client 
"code.forgejo.org/forgejo/runner/v12/internal/pkg/client/mocks"
+       "code.forgejo.org/forgejo/runner/v12/internal/pkg/config"
+       "code.forgejo.org/forgejo/runner/v12/internal/pkg/labels"
+       "code.forgejo.org/forgejo/runner/v12/testutils"
+       "connectrpc.com/connect"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+       "github.com/stretchr/testify/require"
+)
+
+func TestRunJob(t *testing.T) {
+       rawConfig := `
+cache:
+  enabled: false
+server:
+  connections:
+    example:
+      url: https://example.com/forgejo
+      uuid: 41414141-4141-4141-4141-414141414141
+      token: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+`
+
+       tempDir := t.TempDir()
+       configPath := filepath.Join(tempDir, "config.yaml")
+
+       err := os.WriteFile(configPath, []byte(rawConfig), 0o644)
+       require.NoError(t, err)
+
+       mockClient := mock_client.NewClient(t)
+       mockClient.
+               On("FetchTask", mock.Anything, 
connect.NewRequest(&runnerv1.FetchTaskRequest{})).
+               Return(connect.NewResponse(&runnerv1.FetchTaskResponse{Task: 
&runnerv1.Task{}, TasksVersion: int64(1)}), nil)
+
+       mockRunner := mock_runner.NewRunnerInterface(t)
+       mockRunner.
+               On("Run", mock.Anything, mock.Anything).
+               Run(func(args mock.Arguments) {})
+
+       defer testutils.MockVariable(&initLogging, func(cfg *config.Config) 
{})()
+       defer testutils.MockVariable(&createClient, func(cfg *config.Config, 
conn *config.Connection) client.Client {
+               assert.Equal(t, "https://example.com/forgejo";, 
conn.URL.String())
+               assert.Equal(t, "41414141-4141-4141-4141-414141414141", 
conn.UUID.String())
+               assert.Equal(t, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 
conn.Token)
+
+               return mockClient
+       })()
+       defer testutils.MockVariable(&createRunner, func(ctx context.Context, 
name string, cfg *config.Config, cli client.Client, ls labels.Labels, 
cacheProxy *cacheproxy.Handler) (run.RunnerInterface, string, bool, error) {
+               if name == "example" {
+                       return mockRunner, "example", false, nil
+               }
+               t.Fatalf("unexpected connection name: %q", name)
+               return nil, "", false, nil
+       })()
+
+       mockSignalContext, cancelSignal := context.WithCancel(t.Context())
+       runJobCompleted := make(chan any)
+       go func() {
+               err := runJob(mockSignalContext, &configPath, &runJobArgs{})
+               require.NoError(t, err)
+
+               // Signal that runJob() has completed.
+               close(runJobCompleted)
+       }()
+
+       mockRunner.On("Run", mock.Anything, mock.Anything)
+
+       // Cancel the goroutine that runs runJob().
+       cancelSignal()
+
+       // Wait for the goroutine that executes runJob() to stop.
+       <-runJobCompleted
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/internal/pkg/client/header.go 
new/forgejo-runner-12.7.3/internal/pkg/client/header.go
--- old/forgejo-runner-12.7.2/internal/pkg/client/header.go     2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/internal/pkg/client/header.go     2026-03-24 
15:02:59.000000000 +0100
@@ -7,4 +7,5 @@
        UUIDHeader       = "x-runner-uuid"
        TokenHeader      = "x-runner-token"
        RequestKeyHeader = "x-runner-request-key"
+       UserAgentHeader  = "user-agent"
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/internal/pkg/client/http.go 
new/forgejo-runner-12.7.3/internal/pkg/client/http.go
--- old/forgejo-runner-12.7.2/internal/pkg/client/http.go       2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/internal/pkg/client/http.go       2026-03-24 
15:02:59.000000000 +0100
@@ -6,6 +6,7 @@
 import (
        "context"
        "crypto/tls"
+       "fmt"
        "net/http"
        "os"
        "strconv"
@@ -73,6 +74,7 @@
                        if client.requestKey != nil {
                                req.Header().Set(RequestKeyHeader, 
client.requestKey.String())
                        }
+                       req.Header().Set(UserAgentHeader, 
fmt.Sprintf("forgejo-runner/%s", version))
                        return next(ctx, req)
                }
        })))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/forgejo-runner-12.7.2/internal/pkg/config/config.go 
new/forgejo-runner-12.7.3/internal/pkg/config/config.go
--- old/forgejo-runner-12.7.2/internal/pkg/config/config.go     2026-03-09 
17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/internal/pkg/config/config.go     2026-03-24 
15:02:59.000000000 +0100
@@ -16,6 +16,7 @@
        "code.forgejo.org/forgejo/runner/v12/internal/pkg/labels"
        gouuid "github.com/google/uuid"
        "github.com/joho/godotenv"
+       "github.com/powerman/fileuri"
        log "github.com/sirupsen/logrus"
        "go.yaml.in/yaml/v3"
 )
@@ -216,7 +217,7 @@
                if config.Runner.Envs == nil {
                        config.Runner.Envs = make(map[string]string, 
len(s.Envs))
                }
-               env, err := readEnvFile(s.EnvFile)
+               env, err := readEnvFile(filepath.FromSlash(s.EnvFile))
                if err != nil {
                        return err
                }
@@ -403,7 +404,7 @@
 
 func (s *serializedHostSettings) applyTo(config *Config) error {
        if s.WorkdirParent != "" {
-               config.Host.WorkdirParent = s.WorkdirParent
+               config.Host.WorkdirParent = filepath.FromSlash(s.WorkdirParent)
        }
 
        return nil
@@ -624,9 +625,11 @@
        hostname := fileURL.Hostname()
        if hostname != "" {
                log.Warnf("Ignoring hostname %q in secret: %q", hostname, input)
+               fileURL.Host = ""
        }
 
-       value, err := os.ReadFile(fileURL.Path)
+       filePath, _ := fileuri.ToFilePath(fileURL)
+       value, err := os.ReadFile(filePath)
        if err != nil {
                return "", fmt.Errorf("cannot read secret %q: %w", input, err)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/forgejo-runner-12.7.2/internal/pkg/config/config_test.go 
new/forgejo-runner-12.7.3/internal/pkg/config/config_test.go
--- old/forgejo-runner-12.7.2/internal/pkg/config/config_test.go        
2026-03-09 17:04:00.000000000 +0100
+++ new/forgejo-runner-12.7.3/internal/pkg/config/config_test.go        
2026-03-24 15:02:59.000000000 +0100
@@ -9,14 +9,17 @@
        "os"
        "path/filepath"
        "reflect"
+       "runtime"
        "strings"
        "testing"
        "time"
 
        "code.forgejo.org/forgejo/runner/v12/internal/pkg/labels"
        gouuid "github.com/google/uuid"
+       "github.com/powerman/fileuri"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
+       "gotest.tools/v3/skip"
 )
 
 func TestNew(t *testing.T) {
@@ -24,7 +27,7 @@
                config, err := New(FromFile("does-not-exist"))
 
                assert.Nil(t, config)
-               assert.ErrorContains(t, err, "open does-not-exist: no such file 
or directory")
+               assert.ErrorContains(t, err, "open does-not-exist:")
        })
 
        t.Run("Malformed configuration file results in error", func(t 
*testing.T) {
@@ -38,7 +41,7 @@
                config, err := New(FromFile(configPath))
 
                assert.Nil(t, config)
-               assert.ErrorContains(t, err, fmt.Sprintf(`cannot parse config 
file "%s"`, configPath))
+               assert.ErrorContains(t, err, fmt.Sprintf(`cannot parse config 
file %q`, configPath))
        })
 
        t.Run("Without configuration file", func(t *testing.T) {
@@ -259,7 +262,7 @@
   external_server: https://external.example.com/
   actions_cache_url_override: https://override.example.com/
   secret: vruvRdu5Rm
-  secret_url: 
+  secret_url:
 container:
   network: host
   network_mode: bridge
@@ -377,7 +380,7 @@
                assert.True(t, config.Container.ForceRebuild)
 
                assert.NotEqual(t, defaultConfig.Host.WorkdirParent, 
config.Host.WorkdirParent)
-               assert.True(t, strings.HasSuffix(config.Host.WorkdirParent, 
"some/path"))
+               assert.True(t, strings.HasSuffix(config.Host.WorkdirParent, 
filepath.FromSlash("some/path")))
                assert.True(t, filepath.IsAbs(config.Host.WorkdirParent))
 
                assert.NotEqual(t, len(defaultConfig.Server.Connections), 
len(config.Server.Connections))
@@ -390,12 +393,31 @@
                assert.Equal(t, 
labels.MustParse("debian:docker://node:24-trixie"), 
config.Server.Connections["example"].Labels[0])
        })
 
-       t.Run("Imports optional env file", func(t *testing.T) {
+       t.Run("Imports optional env file configured with os-native path", 
func(t *testing.T) {
                tempDir := t.TempDir()
                configFile := filepath.Join(tempDir, "config.yaml")
                envFile := filepath.Join(tempDir, ".env")
 
-               rawConfig := fmt.Sprintf(`{ runner: { env_file: "%s" } }`, 
envFile)
+               rawConfig := fmt.Sprintf(`{ runner: { env_file: %q } }`, 
envFile)
+               err := os.WriteFile(configFile, []byte(rawConfig), 0o644)
+               require.NoError(t, err)
+
+               err = os.WriteFile(envFile, []byte("SOME_ENV_VAR=some-value"), 
0o644)
+               require.NoError(t, err)
+
+               config, err := New(FromFile(configFile))
+               require.NoError(t, err)
+
+               assert.Equal(t, envFile, config.Runner.EnvFile)
+               assert.Equal(t, map[string]string{"SOME_ENV_VAR": 
"some-value"}, config.Runner.Envs)
+       })
+
+       t.Run("Imports optional env file configured with UNIX path", func(t 
*testing.T) {
+               tempDir := t.TempDir()
+               configFile := filepath.Join(tempDir, "config.yaml")
+               envFile := filepath.ToSlash(filepath.Join(tempDir, ".env"))
+
+               rawConfig := fmt.Sprintf(`{ runner: { env_file: %q } }`, 
envFile)
                err := os.WriteFile(configFile, []byte(rawConfig), 0o644)
                require.NoError(t, err)
 
@@ -418,7 +440,7 @@
 runner:
   envs:
     MY_VARIABLE: value
-  env_file: "%s"
+  env_file: %q
 `, envFile)
                err := os.WriteFile(configFile, []byte(rawConfig), 0o644)
                require.NoError(t, err)
@@ -438,7 +460,7 @@
                configFile := filepath.Join(tempDir, "config.yaml")
                envFile := filepath.Join(tempDir, ".env")
 
-               rawConfig := fmt.Sprintf(`{ runner: { env_file: "%s" } }`, 
envFile)
+               rawConfig := fmt.Sprintf(`{ runner: { env_file: %q } }`, 
envFile)
                err := os.WriteFile(configFile, []byte(rawConfig), 0o644)
                require.NoError(t, err)
 
@@ -454,7 +476,7 @@
                configFile := filepath.Join(tempDir, "config.yaml")
                envFile := filepath.Join(tempDir, ".env")
 
-               rawConfig := fmt.Sprintf(`{ runner: { env_file: "%s" } }`, 
envFile)
+               rawConfig := fmt.Sprintf(`{ runner: { env_file: %q } }`, 
envFile)
                err := os.WriteFile(configFile, []byte(rawConfig), 0o644)
                require.NoError(t, err)
 
@@ -913,6 +935,9 @@
                err := os.WriteFile(secretPath, []byte("y114lUUM"), 0o644)
                require.NoError(t, err)
 
+               secretURL, err := fileuri.FromFilePath(secretPath)
+               require.NoError(t, err)
+
                booleanTrue := true
                settings := serializedCacheSettings{
                        Enabled:                 &booleanTrue,
@@ -923,7 +948,7 @@
                        ExternalServer:          "external.local",
                        ActionsCacheURLOverride: "https://example.com/";,
                        Secret:                  "",
-                       SecretURL:               fmt.Sprintf("file:%s", 
secretPath),
+                       SecretURL:               secretURL.String(),
                }
 
                config := Config{}
@@ -1253,11 +1278,14 @@
                serverURL, err := url.Parse("https://example.com/";)
                require.NoError(t, err)
 
+               tokenURL, err := fileuri.FromFilePath(secretPath)
+               require.NoError(t, err)
+
                serialized := serializedConnectionSettings{
                        URL:      serverURL.String(),
                        UUID:     "009e3230-0881-4690-8e0e-43ce2c01d2f9",
                        Token:    "",
-                       TokenURL: fmt.Sprintf("file:%s", secretPath),
+                       TokenURL: tokenURL.String(),
                        Labels:   []string{"label-1"},
                }
 
@@ -1365,7 +1393,10 @@
                err := os.WriteFile(secretPath, []byte(rawSecret), 0o644)
                require.NoError(t, err)
 
-               secret, err := resolveSecretURL(fmt.Sprintf("file://%s", 
secretPath))
+               secretURL, err := fileuri.FromFilePath(secretPath)
+               require.NoError(t, err)
+
+               secret, err := resolveSecretURL(secretURL.String())
                require.NoError(t, err)
 
                assert.Equal(t, rawSecret, secret)
@@ -1394,7 +1425,10 @@
                err := os.WriteFile(secretPath, []byte(rawSecret), 0o644)
                require.NoError(t, err)
 
-               secret, err := resolveFileSecret(fmt.Sprintf("file://%s", 
secretPath))
+               secretURL, err := fileuri.FromFilePath(secretPath)
+               require.NoError(t, err)
+
+               secret, err := resolveFileSecret(secretURL.String())
                require.NoError(t, err)
 
                assert.Equal(t, rawSecret, secret)
@@ -1409,7 +1443,10 @@
                err := os.WriteFile(secretPath, []byte(rawSecret), 0o644)
                require.NoError(t, err)
 
-               secret, err := resolveFileSecret(fmt.Sprintf("file:%s", 
secretPath))
+               secretURL, err := fileuri.FromFilePath(secretPath)
+               require.NoError(t, err)
+
+               secret, err := resolveFileSecret(secretURL.String())
                require.NoError(t, err)
 
                assert.Equal(t, rawSecret, secret)
@@ -1423,14 +1460,18 @@
 
                err := os.WriteFile(secretPath, []byte(rawSecret), 0o644)
                require.NoError(t, err)
+               secretURL, err := fileuri.FromFilePath(secretPath)
+               require.NoError(t, err)
+               secretURL.Host = "some-host"
 
-               secret, err := 
resolveFileSecret(fmt.Sprintf("file://some-host%s", secretPath))
+               secret, err := resolveFileSecret(secretURL.String())
                require.NoError(t, err)
 
                assert.Equal(t, rawSecret, secret)
        })
 
        t.Run("with env variable CREDENTIALS_DIRECTORY", func(t *testing.T) {
+               skip.If(t, runtime.GOOS != "linux") // The 
$CREDENTIALS_DIRECTORY environment variable is only relevant on Linux.
                rawSecret := "zoN4nQX"
 
                tempDir := t.TempDir()
@@ -1462,7 +1503,10 @@
                err := os.WriteFile(secretPath, []byte{}, 0o644)
                require.NoError(t, err)
 
-               secret, err := resolveFileSecret(fmt.Sprintf("file://%s", 
secretPath))
+               secretURL, err := fileuri.FromFilePath(secretPath)
+               require.NoError(t, err)
+
+               secret, err := resolveFileSecret(secretURL.String())
                require.NoError(t, err)
 
                assert.Empty(t, secret)

++++++ forgejo-runner.obsinfo ++++++
--- /var/tmp/diff_new_pack.L6iB21/_old  2026-03-27 06:39:50.754083696 +0100
+++ /var/tmp/diff_new_pack.L6iB21/_new  2026-03-27 06:39:50.826086633 +0100
@@ -1,5 +1,5 @@
 name: forgejo-runner
-version: 12.7.2
-mtime: 1773072240
-commit: 7d42cbf894cb44b28171604c1fd7e9e2cc927540
+version: 12.7.3
+mtime: 1774360979
+commit: f89f3e3cdb1c89b51c925c78028752d78c2478c1
 

++++++ vendor.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/.editorconfig 
new/vendor/github.com/powerman/fileuri/.editorconfig
--- old/vendor/github.com/powerman/fileuri/.editorconfig        1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/.editorconfig        2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,25 @@
+# Doc: https://EditorConfig.org
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+max_line_length = 94
+
+[*.md]
+indent_size = 2
+
+[*.{yml,yaml}]
+indent_size = 2
+
+[{*.go,go.mod,go.work}]
+indent_style = tab
+indent_size = unset
+
+[*.proto]
+indent_size = 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/.gitattributes 
new/vendor/github.com/powerman/fileuri/.gitattributes
--- old/vendor/github.com/powerman/fileuri/.gitattributes       1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/.gitattributes       2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,8 @@
+# /name     - apply (* doesn't match /) to file "name"  beginning in project 
root
+# na/me     - apply (* doesn't match /) to file "na/me" anywhere
+# name      - apply (* do      match /) to file "name"  anywhere
+# name/**   - apply …                   to dir  …
+# **/name   - apply (* doesn't match /) to file "name"  in any dir including 
project root
+# na/**/me  - apply (* doesn't match /) to file "na/me", "na/*/me", 
"na/*/*/me", …
+go.sum binary
+*.*.go binary
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/.gitignore 
new/vendor/github.com/powerman/fileuri/.gitignore
--- old/vendor/github.com/powerman/fileuri/.gitignore   1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/.gitignore   2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,11 @@
+# /name     - exclude path (* doesn't match /) to file/dir "name"  beginning 
in project root
+# na/me     - exclude path (* doesn't match /) to file/dir "na/me" anywhere
+# name      - exclude path (* do      match /) to file/dir "name"  anywhere
+# name/     - exclude path (* doesn't match /) to      dir "name"  anywhere
+# **/name   - exclude path (* doesn't match /) to file/dir "name"  in any dir 
including project root
+# na/**/me  - exclude path (* doesn't match /) to file/dir "na/me", "na/*/me", 
"na/*/*/me", …
+# !name     - include previously excluded path …
+/.cache/
+
+**/*mise.local.toml
+**/*mise/config.local.toml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/.golangci.yml 
new/vendor/github.com/powerman/fileuri/.golangci.yml
--- old/vendor/github.com/powerman/fileuri/.golangci.yml        1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/.golangci.yml        2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,413 @@
+# Origin: https://github.com/powerman/golangci-lint-strict version 2.4.0
+version: "2"
+linters:
+  default: all
+  disable:
+    - containedctx # Questionable.
+    - contextcheck # Questionable.
+    - cyclop # Prefer gocognit.
+    - dogsled # Questionable (assignment to how many blank identifiers is not 
okay?).
+    - dupl
+    - forcetypeassert # Questionable (often we actually want panic).
+    - gocyclo # Prefer gocognit.
+    - interfacebloat # Questionable.
+    - ireturn # Questionable (is returning unexported types better?).
+    - lll # Questionable (sometimes long lines improve readability).
+    - nlreturn # Questionable (often no blank line before return improve 
readability).
+    - nonamedreturns # Questionable (named return act as a documentation).
+    - perfsprint # Questionable (force performance over readability and 
sometimes safety).
+    - varnamelen
+    - wrapcheck # Questionable (see 
https://github.com/tomarrell/wrapcheck/issues/1).
+    - wsl # Questionable (too much style differences, hard to consider).
+    - wsl_v5 # Questionable (too much style differences, hard to consider).
+  settings:
+    decorder:
+      disable-init-func-first-check: false # `init` funcs have to be declared 
before all other functions.
+    depguard:
+      rules:
+        main:
+          deny:
+            - pkg: math/rand$
+              desc: use math/rand/v2
+            - pkg: github.com/prometheus/common/log
+              desc: Should be replaced by standard lib log/slog package
+            - pkg: github.com/sirupsen/logrus
+              desc: Should be replaced by standard lib log/slog package
+            - pkg: github.com/go-errors/errors
+              desc: Should be replaced by standard lib errors package
+            - pkg: github.com/pkg/errors
+              desc: Should be replaced by standard lib errors package
+            - pkg: github.com/prometheus/client_golang/prometheus/promauto
+              desc: Not allowed because it uses global variables
+            - pkg: github.com/golang/protobuf
+              desc: Should be replaced by google.golang.org/protobuf package
+    dupl:
+      threshold: 100
+    embeddedstructfieldcheck:
+      forbid-mutex: true
+    errcheck:
+      exclude-functions:
+        - encoding/json.Marshal # Required because of 
errchkjson.check-error-free-encoding.
+        - encoding/json.MarshalIndent # Required because of 
errchkjson.check-error-free-encoding.
+    errchkjson:
+      check-error-free-encoding: true
+      report-no-exported: true # Encoded struct must have exported fields.
+    exhaustive:
+      check:
+        - switch
+        - map
+      explicit-exhaustive-map: true # Only check maps with 
"//exhaustive:enforce" comment.
+    exhaustruct:
+      include:
+        - ^$ # Only check structs which domain.tld/package/name.structname 
match this regexp.
+    fatcontext:
+      check-struct-pointers: true
+    forbidigo:
+      forbid:
+        - pattern: ^print(ln)?$
+      exclude-godoc-examples: false
+      analyze-types: true
+    funcorder:
+      struct-method: false
+    gochecksumtype:
+      default-signifies-exhaustive: false
+      include-shared-interfaces: true
+    gocognit:
+      min-complexity: 20
+    gocritic:
+      enable-all: true
+      disabled-checks:
+        - exposedSyncMutex # Questionable.
+        - hugeParam # Premature optimization.
+        - paramTypeCombine # Questionable.
+        - switchTrue # Questionable.
+        - todoCommentWithoutDetail # Questionable.
+        - yodaStyleExpr # Questionable.
+      settings:
+        captLocal:
+          paramsOnly: false # Do not restrict checker to params only.
+        ruleguard:
+          failOn: all
+        truncateCmp:
+          skipArchDependent: false # Do not skip int/uint/uintptr types.
+        underef:
+          skipRecvDeref: false
+        unnamedResult:
+          checkExported: true
+    godot:
+      exclude:
+        - :$ # Allow line followed by details in next line(s).
+        - '^\s*- ' # Allow line with a list item.
+    godox:
+      keywords:
+        - BUG # Marks issues that should be moved to issue tracker before 
merging.
+        - FIXME # Marks issues that should be resolved before merging.
+        - DEBUG # Marks temporary code that should be removed before merging.
+    gomodguard:
+      blocked:
+        versions:
+          - github.com/cenkalti/backoff:
+              version: < 4.0.0
+              reason: use actual version
+    gosec:
+      excludes:
+        - G104 # Audit errors not checked
+      config:
+        global:
+          audit: true
+    govet:
+      enable-all: true
+      disable:
+        - fieldalignment
+      settings:
+        shadow:
+          strict: true
+    grouper:
+      import-require-single-import: true # Use a single 'import' declaration.
+    iface:
+      enable:
+        - identical # Identifies interfaces in the same package that have 
identical method sets.
+        - unused # Identifies interfaces that are not used anywhere in the 
same package where the interface is defined.
+        - opaque # Identifies functions that return interfaces, but the actual 
returned value is always a single concrete implementation.
+        - unexported # Identifies interfaces that are not exported but are 
used in exported functions or methods.
+    importas:
+      alias:
+        - pkg: errors
+          alias: ""
+        - pkg: net/url
+          alias: urlpkg
+    loggercheck:
+      require-string-key: true # Logging keys must be inlined constant strings.
+      no-printf-like: true
+    misspell:
+      mode: restricted # Check only comments.
+    nestif:
+      min-complexity: 4
+    nilnil:
+      detect-opposite: true
+    nolintlint:
+      require-explanation: true # Disable linters this way: 
//nolint:first,second // Reason here.
+      require-specific: true # Do not allow //nolint without specific linter 
name(s).
+    paralleltest:
+      ignore-missing: true # Do not require `t.Parallel()` everywhere.
+      ignore-missing-subtests: true # Do not require `t.Parallel()` in all 
subtests.
+    reassign:
+      patterns:
+        - .* # Check all global variables.
+    revive:
+      rules:
+        - name: add-constant
+          disabled: true # Duplicates goconst and mnd linters.
+        - name: argument-limit
+          disabled: true # Questionable.
+        - name: atomic
+        - name: banned-characters
+          arguments: [] # [ "Ω","Σ","σ", "7" ]
+        - name: bare-return
+          disabled: true # Questionable (in some cases bare return improves 
readability).
+        - name: blank-imports
+        - name: bool-literal-in-expr
+        - name: call-to-gc
+        - name: cognitive-complexity
+          disabled: true # Duplicates gocognit linter.
+        - name: comment-spacings
+          arguments:
+            - nolint # Allow //nolint without a space.
+        - name: comments-density
+          disabled: true # Questionable.
+        - name: confusing-naming
+          disabled: true # Questionable (valid use case: Method() as a thin 
wrapper for method()).
+        - name: confusing-results
+        - name: constant-logical-expr
+        - name: context-as-argument
+        - name: context-keys-type
+        - name: cyclomatic
+          disabled: true # Duplicates cyclop and gocyclo linters.
+        - name: datarace
+        - name: deep-exit
+        - name: defer
+        - name: dot-imports
+        - name: duplicated-imports
+        - name: early-return
+        - name: empty-block
+          disabled: true # https://github.com/mgechev/revive/issues/386
+        - name: empty-lines
+        - name: enforce-map-style
+          arguments:
+            - make # Use `make(map[A]B)` instead of literal `map[A]B{}`.
+        - name: enforce-repeated-arg-type-style
+          disabled: true # Questionable (short form for similar args and full 
otherwise may improve readability).
+        - name: enforce-slice-style
+          disabled: true # Questionable (sometimes we need a nil slice, 
sometimes not nil).
+        - name: enforce-switch-style
+          arguments:
+            - allowNoDefault
+        - name: error-naming
+        - name: error-return
+        - name: error-strings
+        - name: errorf
+        - name: exported
+        - name: file-header
+        - name: file-length-limit
+        - name: filename-format
+        - name: flag-parameter
+        - name: function-length
+          disabled: true # Duplicates funlen linter.
+        - name: function-result-limit
+          disabled: true # Questionable.
+        - name: get-return
+        - name: identical-branches
+        - name: if-return
+        - name: import-alias-naming
+        - name: import-shadowing
+        - name: imports-blocklist
+        - name: increment-decrement
+        - name: indent-error-flow
+        - name: line-length-limit
+          disabled: true # Duplicates lll linter.
+        - name: max-control-nesting
+        - name: max-public-structs
+          disabled: true # Questionable.
+        - name: modifies-parameter
+        - name: modifies-value-receiver
+        - name: nested-structs
+          disabled: true # Questionable (useful in tests, may worth enabling 
for non-tests).
+        - name: optimize-operands-order
+        - name: package-comments
+        - name: range
+        - name: range-val-address
+        - name: range-val-in-closure
+        - name: receiver-naming
+        - name: redefines-builtin-id
+        - name: redundant-build-tag
+        - name: redundant-import-alias
+        - name: redundant-test-main-exit
+        - name: string-format
+          arguments:
+            - - fmt.Errorf[0]
+              - /(^|[^\.!?])$/
+              - must not end in punctuation
+            - - panic
+              - /^[^\n]*$/
+              - must not contain line breaks
+        - name: string-of-int
+        - name: struct-tag
+        - name: superfluous-else
+        - name: time-date
+        - name: time-equal
+        - name: time-naming
+        - name: unchecked-type-assertion
+          disabled: true # Duplicates errcheck and forcetypeassert linters.
+        - name: unconditional-recursion
+        - name: unexported-naming
+        - name: unexported-return
+        - name: unhandled-error
+          disabled: true # Duplicates errcheck linter.
+        - name: unnecessary-format
+        - name: unnecessary-stmt
+        - name: unreachable-code
+        - name: unused-parameter
+        - name: unused-receiver
+        - name: use-any
+        - name: use-errors-new
+        - name: use-fmt-print
+        - name: useless-break
+        - name: var-declaration
+        - name: var-naming
+        - name: waitgroup-by-value
+    rowserrcheck:
+      packages:
+        - github.com/jmoiron/sqlx
+        - github.com/powerman/sqlxx
+    sloglint:
+      context: scope
+      static-msg: true
+      msg-style: capitalized
+      key-naming-case: snake
+      forbidden-keys:
+        - time # Used by standard slog.JSONHandler or slog.TextHandler.
+        - level # Used by standard slog.JSONHandler or slog.TextHandler.
+        - msg # Used by standard slog.JSONHandler or slog.TextHandler.
+        - source # Used by standard slog.JSONHandler or slog.TextHandler.
+    tagalign:
+      order:
+        - json
+        - yaml
+        - yml
+        - toml
+        - env
+        - mod
+        - mapstructure
+        - binding
+        - validate
+      strict: true
+    tagliatelle:
+      case:
+        rules:
+          json: snake
+          yaml: kebab
+          xml: camel
+          toml: camel
+          bson: camel
+          avro: snake
+          mapstructure: kebab
+          envconfig: upperSnake
+          whatever: snake
+    testifylint:
+      enable-all: true
+    testpackage:
+      skip-regexp: .*_internal_test\.go
+    thelper:
+      test:
+        name: false # Allow *testing.T param to have any name, not only `t`.
+    usestdlibvars:
+      time-date-month: true
+      time-month: true
+      time-layout: true
+      crypto-hash: true
+      default-rpc-path: true
+      sql-isolation-level: true
+      tls-signature-scheme: true
+    wrapcheck:
+      report-internal-errors: true
+  exclusions:
+    rules:
+      - path: (.+)\.go$
+        text: declaration of "(log|err|ctx)" shadows
+      - path: (.+)\.go$
+        text: 'missing cases in switch of type \S+: \S+_UNSPECIFIED$'
+      - path: _test\.go|testing(_.*)?\.go
+        linters:
+          - bodyclose
+          - dupl
+          - errcheck
+          - forcetypeassert
+          - funlen
+          - gochecknoglobals
+          - gochecknoinits
+          - gocognit
+          - goconst
+          - gosec
+          - maintidx
+          - reassign
+      - source: '[Cc]onst' # Define global const-vars like: var SomeGlobal = 
[]int{42} // Const.
+        linters:
+          - gochecknoglobals
+      - path: _test\.go|testing(_.*)?\.go
+        text: (unnamedResult|exitAfterDefer|rangeValCopy|unnecessaryBlock)
+        linters:
+          - gocritic
+      - path: _test\.go
+        text: '"t" shadows'
+        linters:
+          - govet
+      - path: ^(.*/)?embed.go$
+        linters:
+          - gochecknoglobals
+      - linters:
+          - lll
+        source: '^//go:generate '
+    paths:
+      - \.[\w-]+\.go$ # Use this pattern to name auto-generated files.
+formatters:
+  enable:
+    - gci
+    - gofmt
+    - gofumpt
+    - goimports
+    - golines
+  settings:
+    gci:
+      sections:
+        - standard # Standard section: captures all standard packages.
+        - default # Default section: contains all imports that could not be 
matched to another section type.
+        - localmodule # Local module section: contains all local packages. 
This section is not present unless explicitly enabled.
+      no-inline-comments: true
+      no-prefix-comments: true
+    gofmt:
+      rewrite-rules:
+        - pattern: interface{}
+          replacement: any
+        - pattern: a[b:len(a)]
+          replacement: a[b:]
+    golines:
+      max-len: 200
+      tab-len: 8
+  exclusions:
+    generated: strict
+    paths:
+      - \.[\w-]+\.go$ # Use this pattern to name auto-generated files.
+issues:
+  max-issues-per-linter: 0
+  max-same-issues: 0
+output:
+  sort-order:
+    - linter
+    - severity
+    - file # filepath, line, and column.
+  show-stats: false
+run:
+  timeout: 1m
+  modules-download-mode: readonly
+severity:
+  default: error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/CHANGELOG.md 
new/vendor/github.com/powerman/fileuri/CHANGELOG.md
--- old/vendor/github.com/powerman/fileuri/CHANGELOG.md 1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/CHANGELOG.md 2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,22 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a 
Changelog](https://keepachangelog.com/en/1.1.0/),
+and this project adheres to [Semantic 
Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [0.2.0] - 2025-08-24
+
+### 🚀 Added
+
+- Add extended-length path prefix support by @powerman in [af72ba9]
+
+### 🐛 Fixed
+
+- Require UNC share name by @powerman in [bb632aa]
+
+[0.2.0]: https://github.com/powerman/fileuri/compare/%40%7B10year%7D..v0.2.0
+[bb632aa]: 
https://github.com/powerman/fileuri/commit/bb632aa608bef21cf43d70108b6b225d55140453
+[af72ba9]: 
https://github.com/powerman/fileuri/commit/af72ba9ea2c93f670d0cda14b974bb6bdc327039
+
+<!-- generated by git-cliff -->
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/LICENSE 
new/vendor/github.com/powerman/fileuri/LICENSE
--- old/vendor/github.com/powerman/fileuri/LICENSE      1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/LICENSE      2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Alex Efros
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+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.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/LICENSE-go 
new/vendor/github.com/powerman/fileuri/LICENSE-go
--- old/vendor/github.com/powerman/fileuri/LICENSE-go   1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/LICENSE-go   2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,27 @@
+Copyright 2009 The Go Authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google LLC nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/README.md 
new/vendor/github.com/powerman/fileuri/README.md
--- old/vendor/github.com/powerman/fileuri/README.md    1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/README.md    2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,19 @@
+# fileuri is a Go package to work with file:// URI
+
+[![License 
MIT](https://img.shields.io/badge/license-MIT-royalblue.svg)](LICENSE)
+[![Go 
version](https://img.shields.io/github/go-mod/go-version/powerman/fileuri?color=blue)](https://go.dev/)
+[![Test](https://img.shields.io/github/actions/workflow/status/powerman/fileuri/test.yml?label=test)](https://github.com/powerman/fileuri/actions/workflows/test.yml)
+[![Coverage 
Status](https://raw.githubusercontent.com/powerman/fileuri/gh-badges/coverage.svg)](https://github.com/powerman/fileuri/actions/workflows/test.yml)
+[![Go Report 
Card](https://goreportcard.com/badge/github.com/powerman/fileuri)](https://goreportcard.com/report/github.com/powerman/fileuri)
+[![Release](https://img.shields.io/github/v/release/powerman/fileuri?color=blue)](https://github.com/powerman/fileuri/releases/latest)
+[![Go 
Reference](https://pkg.go.dev/badge/github.com/powerman/fileuri.svg)](https://pkg.go.dev/github.com/powerman/fileuri)
+
+![Linux | amd64 arm64 armv7 ppc64le s390x 
riscv64](https://img.shields.io/badge/Linux-amd64%20arm64%20armv7%20ppc64le%20s390x%20riscv64-royalblue)
+![macOS | amd64 
arm64](https://img.shields.io/badge/macOS-amd64%20arm64-royalblue)
+![Windows | amd64 
arm64](https://img.shields.io/badge/Windows-amd64%20arm64-royalblue)
+
+Implements [RFC 8089 The "file" URI 
Scheme](https://datatracker.ietf.org/doc/html/rfc8089).
+
+The implementation is based on `cmd/go/internal/web` package from Go 1.25.0.
+
+See also [Go issue 32456](https://github.com/golang/go/issues/32456).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/fileuri.go 
new/vendor/github.com/powerman/fileuri/fileuri.go
--- old/vendor/github.com/powerman/fileuri/fileuri.go   1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/fileuri.go   2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,129 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE-go file.
+
+// Copyright 2025 Alex Efros <[email protected]>. All rights reserved.
+// Use of this source code is governed by a MIT license that can be found in 
the LICENSE file.
+
+// Package fileuri provides functions to work with file:// URLs.
+// It implements RFC 8089 The "file" URI Scheme.
+package fileuri
+
+import (
+       "errors"
+       "net/url"
+       "path/filepath"
+       "strings"
+)
+
+// TODO(golang.org/issue/32456): If accepted, move these functions into the
+// net/url package.
+
+var (
+       errNotAbsolute = errors.New("path is not absolute")
+       errNonFile     = errors.New("non-file URL")
+       errMissingPath = errors.New("file URL missing path")
+)
+
+// ToFilePath converts a file URL to a filesystem path.
+// It returns an error if the URL is not a file URL or if the path is not 
absolute.
+// The returned path is in the format of the current operating system.
+//
+// ToFilePath handles file URLs as specified in RFC 8089.
+// In particular, it supports both hostless file URLs (file:///path/to/file)
+// and UNC file URLs (file://host/share/path/to/file).
+//
+// ToFilePath does not access the filesystem and does not verify that the path 
exists.
+func ToFilePath(u *url.URL) (string, error) {
+       if u.Scheme != "file" {
+               return "", errNonFile
+       }
+
+       checkAbs := func(path string) (string, error) {
+               if !filepath.IsAbs(path) {
+                       return "", errNotAbsolute
+               }
+               return path, nil
+       }
+
+       if u.Path == "" {
+               if u.Host != "" || u.Opaque == "" {
+                       return "", errMissingPath
+               }
+               return checkAbs(filepath.FromSlash(u.Opaque))
+       }
+
+       path, err := convertFileURLPath(u.Host, u.Path)
+       if err != nil {
+               return path, err
+       }
+       return checkAbs(path)
+}
+
+// FromFilePath converts an absolute filesystem path to a file URL.
+// It returns an error if the path is not absolute.
+//
+// FromFilePath handles paths on Windows and Unix as specified in RFC 8089.
+// In particular, it converts Windows UNC paths (\\host\share\path\to\file)
+// to UNC file URLs (file://host/share/path/to/file).
+//
+// FromFilePath does not access the filesystem and does not verify that the 
path exists.
+func FromFilePath(path string) (*url.URL, error) {
+       // Convert extended-length UNC path to regular UNC path.
+       // See 
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#unc-paths.
+       if strings.HasPrefix(path, `\\?\UNC`) {
+               path = `\` + path[7:]
+       } else if strings.HasPrefix(path, `\\?\`) {
+               path = path[4:]
+       }
+
+       if !filepath.IsAbs(path) {
+               return nil, errNotAbsolute
+       }
+
+       // If path has a Windows volume name, convert the volume to a host and 
prefix
+       // per 
https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/.
+       if vol := filepath.VolumeName(path); vol != "" {
+               if strings.HasPrefix(vol, `\\`) {
+                       path = filepath.ToSlash(path[2:])
+                       i := strings.IndexByte(path, '/')
+
+                       if i < 0 {
+                               // A degenerate case.
+                               // \\host.example.com (without a share name)
+                               // becomes
+                               // file://host.example.com/
+                               return &url.URL{
+                                       Scheme: "file",
+                                       Host:   path,
+                                       Path:   "/",
+                               }, nil
+                       }
+
+                       // \\host.example.com\Share\path\to\file
+                       // becomes
+                       // file://host.example.com/Share/path/to/file
+                       return &url.URL{
+                               Scheme: "file",
+                               Host:   path[:i],
+                               Path:   filepath.ToSlash(path[i:]),
+                       }, nil
+               }
+
+               // C:\path\to\file
+               // becomes
+               // file:///C:/path/to/file
+               return &url.URL{
+                       Scheme: "file",
+                       Path:   "/" + filepath.ToSlash(path),
+               }, nil
+       }
+
+       // /path/to/file
+       // becomes
+       // file:///path/to/file
+       return &url.URL{
+               Scheme: "file",
+               Path:   filepath.ToSlash(path),
+       }, nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/fileuri_other.go 
new/vendor/github.com/powerman/fileuri/fileuri_other.go
--- old/vendor/github.com/powerman/fileuri/fileuri_other.go     1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/fileuri_other.go     2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,26 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE-go file.
+
+// Copyright 2025 Alex Efros <[email protected]>. All rights reserved.
+// Use of this source code is governed by a MIT license that can be found in 
the LICENSE file.
+
+//go:build !windows
+
+package fileuri
+
+import (
+       "errors"
+       "path/filepath"
+)
+
+var errNonLocalHost = errors.New("file URL specifies non-local host")
+
+func convertFileURLPath(host, path string) (string, error) {
+       switch host {
+       case "", "localhost":
+       default:
+               return "", errNonLocalHost
+       }
+       return filepath.FromSlash(path), nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vendor/github.com/powerman/fileuri/fileuri_windows.go 
new/vendor/github.com/powerman/fileuri/fileuri_windows.go
--- old/vendor/github.com/powerman/fileuri/fileuri_windows.go   1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/fileuri_windows.go   2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,67 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE-go file.
+
+// Copyright 2025 Alex Efros <[email protected]>. All rights reserved.
+// Use of this source code is governed by a MIT license that can be found in 
the LICENSE file.
+
+package fileuri
+
+import (
+       "errors"
+       "path/filepath"
+       "strings"
+)
+
+const maxPath = 260 // Windows MAX_PATH limitation.
+
+var (
+       errVolumeInHost  = errors.New("file URL encodes volume in host field: 
too few slashes?")
+       errMissingVolume = errors.New("file URL missing drive letter")
+       errMissingShare  = errors.New("file URL missing UNC share name")
+)
+
+func convertFileURLPath(host, path string) (string, error) {
+       if path == "" || path[0] != '/' {
+               return "", errNotAbsolute
+       }
+
+       path = filepath.FromSlash(path)
+
+       // We interpret Windows file URLs per the description in
+       // https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/.
+
+       // The host part of a file URL (if any) is the UNC volume name,
+       // but RFC 8089 reserves the authority "localhost" for the local 
machine.
+       if host != "" && host != "localhost" {
+               // A common "legacy" format omits the leading slash before a 
drive letter,
+               // encoding the drive letter as the host instead of part of the 
path.
+               // (See 
https://blogs.msdn.microsoft.com/freeassociations/2005/05/19/the-bizarre-and-unhappy-story-of-file-urls/.)
+               // We do not support that format, but we should at least emit a 
more
+               // helpful error message for it.
+               if filepath.VolumeName(host) != "" {
+                       return "", errVolumeInHost
+               }
+               if path == `\` {
+                       return "", errMissingShare
+               }
+               path = `\\` + host + path
+               if len(path) >= maxPath { // Too strict because check bytes 
instead of UTF-16 chars.
+                       // Use the extended-length path prefix to avoid 
MAX_PATH limitations.
+                       // See 
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation.
+                       path = `\\?\UNC` + filepath.Clean(path[1:])
+               }
+               return path, nil
+       }
+
+       // If host is empty, path must contain an initial slash followed by a
+       // drive letter and path. Remove the slash and verify that the path is 
valid.
+       if vol := filepath.VolumeName(path[1:]); vol == "" || 
strings.HasPrefix(vol, `\\`) {
+               return "", errMissingVolume
+       }
+       path = path[1:]
+       if len(path) >= maxPath { // Too strict because check bytes instead of 
UTF-16 chars.
+               path = `\\?\` + filepath.Clean(path)
+       }
+       return path, nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/github.com/powerman/fileuri/mise.toml 
new/vendor/github.com/powerman/fileuri/mise.toml
--- old/vendor/github.com/powerman/fileuri/mise.toml    1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/github.com/powerman/fileuri/mise.toml    2026-03-26 
09:17:46.000000000 +0100
@@ -0,0 +1,115 @@
+[settings]
+experimental = true # Required to use lockfile.
+lockfile = true     # DO NOT FORGET TO `touch mise.lock` if mise.lock does not 
exist!
+
+
+[tools]
+go = 'latest'
+
+#--- Generate
+# MockGen generates mock implementations of Go interfaces.
+'go:go.uber.org/mock/mockgen' = 'latest'
+
+#--- Lint
+# Static checker for GitHub Actions workflow files.
+actionlint = 'latest'
+# Fast linters runner for Go.
+golangci-lint = 'latest'
+
+#--- Test
+# 'go test' runner with output optimized for humans.
+gotestsum = 'latest'
+
+#--- Release
+# A highly customizable Changelog Generator that follows Conventional Commit 
specifications.
+git-cliff = 'latest'
+# GitHub's official command line tool.
+gh = 'latest'
+
+
+[vars]
+cover = '.cache/cover.out'
+
+
+[tasks.'changelog:skip-commit']
+description = 'Add commit hash to .cliffignore to exclude from CHANGELOG'
+usage = 'arg "<commit>" help="Git revision (e.g. HEAD or a1b2c4d)"'
+run = 'git rev-parse --verify "${usage_commit}" >> .cliffignore'
+
+[tasks.generate]
+description = 'Generate everything'
+depends = ['generate:*']
+
+[tasks.fmt]
+description = 'Format all files'
+depends = ['fmt:*']
+
+[tasks.lint]
+description = 'Run all linters'
+depends = ['lint:*']
+
+[tasks.test]
+description = 'Run all tests'
+depends = ['test:*']
+
+[tasks.default]
+description = 'Run all linters and tests'
+depends = ['lint', 'test']
+
+[tasks.ci]
+description = 'Run all CI tasks'
+depends = ['generate', 'fmt', 'lint', 'test']
+# Is working tree clean after fmt?
+run = '! git status --porcelain | tee /dev/stderr | grep -q .'
+run_windows = 'powershell -c "$status = git status --porcelain; if ($status) { 
$status; exit 1 }"'
+
+[tasks.'generate:go']
+description = 'Generate Go code'
+run = 'go generate ./...'
+
+[tasks.'fmt:go']
+description = 'Format Go code'
+run = 'golangci-lint fmt'
+
+[tasks.'lint:workflows']
+description = 'Lint GitHub Action workflows'
+run = 'actionlint'
+
+[tasks.'lint:go']
+description = 'Lint Go files'
+run = 'golangci-lint run'
+
+[tasks.'lint:go-compile-windows']
+description = 'Check Go test compiles on Windows'
+run = 'GOOS=windows go test -c -o /dev/null ./...'
+
+[tasks.'test:go']
+description = 'Run Go tests for a whole project'
+wait_for = ['generate:*', 'lint:*']              # Avoid interleaved output 
with linters.
+run = 'gotestsum -- -race -timeout=60s ./...'
+
+[tasks.'cover:go:total']
+description = 'Show Go test coverage total'
+depends = 'cover:go:generate'
+run = 'go tool cover -func={{vars.cover}} | tail -n 1 | xargs echo'
+
+[tasks.'cover:go:browse']
+description = 'Show Go test coverage in a browser'
+depends = 'cover:go:generate'
+run = 'go tool cover -html={{vars.cover}}'
+
+[tasks.'cover:go:generate']
+hide = true
+depends = 'cachedir'
+sources = ['**/*.go']
+outputs = ['{{vars.cover}}']
+run = '''
+gotestsum -- \
+    -coverpkg="$(go list ./... | paste -s -d,)" \
+    -coverprofile {{vars.cover}} \
+    ./...
+'''
+
+[tasks.cachedir]
+hide = true
+run = 'mkdir -p .cache'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt
--- old/vendor/modules.txt      2026-03-17 11:44:22.000000000 +0100
+++ new/vendor/modules.txt      2026-03-26 09:17:46.000000000 +0100
@@ -378,6 +378,9 @@
 # github.com/pmezard/go-difflib v1.0.0
 ## explicit
 github.com/pmezard/go-difflib/difflib
+# github.com/powerman/fileuri v0.2.0
+## explicit; go 1.24.6
+github.com/powerman/fileuri
 # github.com/rhysd/actionlint v1.7.10
 ## explicit; go 1.24.0
 github.com/rhysd/actionlint
@@ -510,8 +513,8 @@
 golang.org/x/sys/plan9
 golang.org/x/sys/unix
 golang.org/x/sys/windows
-# golang.org/x/term v0.40.0
-## explicit; go 1.24.0
+# golang.org/x/term v0.41.0
+## explicit; go 1.25.0
 golang.org/x/term
 # golang.org/x/time v0.15.0
 ## explicit; go 1.25.0

Reply via email to