mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-05-14 20:03:24 +02:00
Fixes: https://gitea.com/gitea/runner/issues/859 Migration approach mirrors [actions-oss/act-cli#154](https://github.com/actions-oss/act-cli/pull/154). ### Dependency changes - `github.com/docker/docker` v25.0.15 → **removed** (v29 doesn't exist as docker/docker; the project moved to moby/moby) - `github.com/docker/cli` v25.0.7 → v29.4.3 - `github.com/docker/go-connections` v0.6.0 → v0.7.0 - `github.com/docker/docker-credential-helpers` v0.9.5 → v0.9.6 - `github.com/moby/go-archive` added at v0.2.0 - `github.com/moby/moby/api` added at v1.54.2 - `github.com/moby/moby/client` added at v0.4.1 - `github.com/moby/buildkit` removed (only used `dockerignore.ReadAll`, swapped for `moby/patternmatcher/ignorefile.ReadAll` directly) - `github.com/containerd/errdefs` v0.3.0 → v1.0.0 ### Migration - v28: type aliases moved to their subpackages (`types.{Container,Image,Network,Exec}*` → `container/image/network/...`); deprecated APIs replaced (`ImageInspectWithRaw`, `client.IsErrNotFound`, `archive.CanonicalTarNameForPath`, `opts.ValidateMACAddress`, `ListOpts.GetAll`) - v29: structural client redesign — every `cli.X(ctx, ...)` call switched to options-everywhere/Result-typed signatures, `ContainerExec*` → `Exec*`, `ContainerWait` returns a struct with `Result`/`Error` channels, `Tty`→`TTY`, `Copy*Container` takes options struct, `client.NewClientWithOpts` → `client.New`. `pkg/stdcopy` moved to `moby/moby/api/pkg/stdcopy`. The vendored copy of `cli/command/container/opts.go` was refreshed from cli v29 (now uses `netip.Addr` for IPs, port-set conversion helpers). A small local `parsePlatform` helper centralises the `os/arch[/variant]` parsing previously inlined into multiple call sites. ### Behaviour preservation The migration introduced several behavioural shifts vs the v25 client; all were caught in review and reverted/fixed in follow-up commits: - `GetDockerClient`: cli v29's `Ping(NegotiateAPIVersion: true)` returns errors that the old `NegotiateAPIVersion` silently swallowed. Restored best-effort behaviour (warn-log + continue) so daemons with blocked `_ping` or API < 1.40 keep working. The SSH-helper `client.New` call no longer inherits `client.FromEnv`, matching the old `NewClientWithOpts(WithHost, WithDialContext)` so `DOCKER_API_VERSION`/`DOCKER_TLS_VERIFY` don't leak into the SSH-tunneled client - `parsePlatform`: malformed input now returns an explicit error instead of silently dropping to "no platform constraint" and pulling the host-default architecture. Single-segment (`"linux"`), 4+-segment (`"linux/arm/v7/extra"`), and trailing-slash (`"linux/arm/"`) inputs are all rejected - `LoadDockerAuthConfig`/`LoadDockerAuthConfigs`: `config.LoadDefaultConfigFile(nil)` panics on a malformed config file (it does `fmt.Fprintln` on the nil `io.Writer`). Switched to `config.Load(config.Dir())` so load errors reach the logger and the panic path is gone. Restored the old behaviour of returning `config.Load` and `GetAuthConfig` errors to the caller (the v29 refactor had silently downgraded them to warn-only). A `reference.ParseNormalizedNamed` failure on the image string falls through to the `docker.io` default rather than aborting, since the old string-based hostname extraction was infallible Test assertions also updated for two upstream error-message string shifts (`go-connections` port-range parser; `cli/opts` envfile BOM check). Added unit-test coverage for the new `parsePlatform` helper, locking in the intentional limits (single-segment, 4+-segment, and trailing-slash platforms rejected). --- This PR was written with the help of Claude Opus 4.7 Reviewed-on: https://gitea.com/gitea/runner/pulls/943 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-committed-by: silverwind <me@silverwind.io>
81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// Copyright 2021 The nektos/act Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
|
|
|
|
package container
|
|
|
|
import (
|
|
"context"
|
|
|
|
"gitea.com/gitea/runner/act/common"
|
|
|
|
"github.com/distribution/reference"
|
|
"github.com/docker/cli/cli/config"
|
|
"github.com/docker/cli/cli/config/credentials"
|
|
"github.com/moby/moby/api/types/registry"
|
|
)
|
|
|
|
func LoadDockerAuthConfig(ctx context.Context, image string) (registry.AuthConfig, error) {
|
|
logger := common.Logger(ctx)
|
|
// config.LoadDefaultConfigFile panics on nil io.Writer when the config
|
|
// file is malformed; use config.Load to route errors through the logger.
|
|
cfg, err := config.Load(config.Dir())
|
|
if err != nil {
|
|
logger.Warnf("Could not load docker config: %v", err)
|
|
return registry.AuthConfig{}, err
|
|
}
|
|
if !cfg.ContainsAuth() {
|
|
cfg.CredentialsStore = credentials.DetectDefaultStore(cfg.CredentialsStore)
|
|
}
|
|
|
|
registryKey := registryAuthConfigKey("docker.io")
|
|
if image != "" {
|
|
if registryRef, refErr := reference.ParseNormalizedNamed(image); refErr != nil {
|
|
logger.Warnf("Could not normalize image reference: %v", refErr)
|
|
} else {
|
|
registryKey = registryAuthConfigKey(reference.Domain(registryRef))
|
|
}
|
|
}
|
|
|
|
authConfig, err := cfg.GetAuthConfig(registryKey)
|
|
if err != nil {
|
|
logger.Warnf("Could not get auth config from docker config: %v", err)
|
|
return registry.AuthConfig{}, err
|
|
}
|
|
|
|
return registry.AuthConfig(authConfig), nil
|
|
}
|
|
|
|
func LoadDockerAuthConfigs(ctx context.Context) map[string]registry.AuthConfig {
|
|
logger := common.Logger(ctx)
|
|
cfg, err := config.Load(config.Dir())
|
|
if err != nil {
|
|
logger.Warnf("Could not load docker config: %v", err)
|
|
return nil
|
|
}
|
|
if !cfg.ContainsAuth() {
|
|
cfg.CredentialsStore = credentials.DetectDefaultStore(cfg.CredentialsStore)
|
|
}
|
|
|
|
creds, err := cfg.GetAllCredentials()
|
|
if err != nil {
|
|
logger.Warnf("Could not get docker auth configs: %v", err)
|
|
return nil
|
|
}
|
|
authConfigs := make(map[string]registry.AuthConfig, len(creds))
|
|
for k, v := range creds {
|
|
authConfigs[k] = registry.AuthConfig(v)
|
|
}
|
|
|
|
return authConfigs
|
|
}
|
|
|
|
func registryAuthConfigKey(domainName string) string {
|
|
if domainName == "docker.io" || domainName == "index.docker.io" {
|
|
return "https://index.docker.io/v1/"
|
|
}
|
|
return domainName
|
|
}
|