0
0
mirror of https://github.com/thegeeklab/wp-git-clone.git synced 2024-06-02 18:29:42 +02:00

Compare commits

...

56 Commits
v0.1.1 ... main

Author SHA1 Message Date
renovate[bot]
802a17e461
chore(deps): update docker.io/library/alpine docker tag to v3.20 (#53)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-01 13:22:05 +02:00
renovate[bot]
6a6632ddc6 chore(deps): update dependency golangci/golangci-lint to v1.59.0 2024-05-27 03:21:22 +00:00
renovate[bot]
d19fce329b
fix(deps): update module github.com/rs/zerolog to v1.33.0 (#54)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-24 09:25:58 +02:00
renovate[bot]
8f35a567cb chore(docker): update docker.io/library/golang:1.22 docker digest to f43c6f0 2024-05-18 05:45:18 +00:00
6e5ad068d0
chore: migrate to wp-plugin-go v3 (#50) 2024-05-17 21:50:05 +02:00
renovate[bot]
ccfad42ff3
chore(docker): update docker.io/library/golang:1.22 docker digest to 91ad6f9 (#49)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-16 13:41:19 +02:00
renovate[bot]
9ab5ebab66 chore(deps): update dependency golangci/golangci-lint to v1.58.1 2024-05-13 03:21:49 +00:00
5b78cb5330
ci: fix golangci-lint deprecations 2024-05-12 11:08:31 +02:00
renovate[bot]
b17cd244a8 chore(docker): update docker.io/library/golang:1.22 docker digest to b1e05e2 2024-05-08 05:07:39 +00:00
772c94948d
fix: check is cmd is nil before execution (#45) 2024-05-07 11:57:29 +02:00
d3410de2f1
fix: disable command output while setting ssh key 2024-05-06 22:45:33 +02:00
6ac87de468
cleanup import 2024-05-06 21:28:07 +02:00
2204435c15
use assert instead of require 2024-05-06 21:14:04 +02:00
7fd0de6cc4
refactor: switch to plugin Cmd and add tests (#44) 2024-05-06 20:30:18 +02:00
renovate[bot]
bcf5f1ca1a chore(deps): update dependency golangci/golangci-lint to v1.58.0 2024-05-06 03:30:18 +00:00
renovate[bot]
97b685b01c chore(docker): update docker.io/library/golang:1.22 docker digest to d5302d4 2024-04-25 04:00:57 +00:00
2f1564fa07
fix: ensure branch has a default value set (#37) 2024-04-22 20:46:46 +02:00
renovate[bot]
9b68258a67
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.7.1 (#36)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-22 13:24:30 +02:00
renovate[bot]
c377b1946b chore(docker): update docker.io/library/golang:1.22 docker digest to 450e382 2024-04-11 04:58:47 +00:00
renovate[bot]
fb68f845fe chore(docker): update docker.io/library/golang:1.22 docker digest to 3cb9b4d 2024-04-10 06:44:18 +00:00
renovate[bot]
74d829d591
fix(deps): update module golang.org/x/sys to v0.19.0 (#33)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-05 08:55:09 +02:00
renovate[bot]
27c6332215 chore(docker): update docker.io/library/golang:1.22 docker digest to c4fb952 2024-04-04 03:02:26 +00:00
renovate[bot]
816d6ac145 chore(deps): update dependency golangci/golangci-lint to v1.57.2 2024-04-01 05:02:06 +00:00
renovate[bot]
bd9d0fcc8c
chore(deps): update quay.io/thegeeklab/wp-docker-buildx docker tag to v4 (#30)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-27 08:56:31 +01:00
renovate[bot]
15082b446e
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.7.0 (#26)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 08:31:38 +01:00
renovate[bot]
90774820e0
fix(deps): update module github.com/cenkalti/backoff/v4 to v4.3.0 (#29)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 08:31:31 +01:00
renovate[bot]
007fa77671 chore(deps): update dependency golangci/golangci-lint to v1.57.1 2024-03-25 05:19:05 +00:00
renovate[bot]
1ef29aa1cd chore(docker): update docker.io/library/golang:1.22 docker digest to 0b55ab8 2024-03-13 06:46:23 +00:00
renovate[bot]
6c878f71ca
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.6.1 (#25)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-07 21:26:41 +01:00
renovate[bot]
e53082d420
fix(deps): update module golang.org/x/sys to v0.18.0 (#23)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 14:42:05 +01:00
renovate[bot]
118694a789 chore(docker): update docker.io/library/golang:1.22 docker digest to 34ce21a 2024-03-06 03:10:22 +00:00
renovate[bot]
9f3148d9d1 chore(deps): update dependency golangci/golangci-lint to v1.56.2 2024-02-19 04:18:45 +00:00
renovate[bot]
999524e514 chore(docker): update docker.io/library/golang:1.22 docker digest to 7b297d9 2024-02-16 03:32:35 +00:00
6ed4dc2ea1
[skip ci] revert renovate automerge config 2024-02-15 12:19:32 +01:00
renovate[bot]
f8cd99676f
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.6.0 (#20)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 21:55:40 +01:00
renovate[bot]
32c1da7df0
fix(deps): update module golang.org/x/sys to v0.17.0 (#19)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-08 08:33:08 +01:00
renovate[bot]
c6089df662
chore(deps): update docker.io/library/golang docker tag to v1.22 (#17)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
2024-02-07 22:31:58 +01:00
5c87a86020
harmonize container image refs and use fqin 2024-02-07 09:40:53 +01:00
a1367d825f
run ci on renovate auto branches 2024-02-07 09:10:14 +01:00
c54bd212ae
ci: enable ci run on renovate branches 2024-02-05 08:58:32 +01:00
renovate[bot]
c3f24caac4
fix(deps): update module github.com/rs/zerolog to v1.32.0 (#16)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 08:45:28 +01:00
renovate[bot]
5d691ec4d2 chore(docker): update golang:1.21 docker digest to 7b575fe 2024-02-03 06:15:19 +00:00
renovate[bot]
594950682e chore(deps): update dependency mvdan/gofumpt to v0.6.0 2024-01-30 06:58:08 +00:00
renovate[bot]
d7a55b250a chore(docker): update alpine:3.19 docker digest to c5b1261 2024-01-28 03:40:09 +00:00
renovate[bot]
bbc657e6f2 chore(docker): update golang:1.21 docker digest to 76aadd9 2024-01-25 07:42:13 +00:00
renovate[bot]
20dec75586
chore(deps): update quay.io/thegeeklab/wp-docker-buildx docker tag to v3 (#11)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-22 11:27:51 +01:00
renovate[bot]
468e2398ff chore(docker): update golang:1.21 docker digest to 5f5d61d 2024-01-17 11:37:28 +00:00
renovate[bot]
81f30f75f6 chore(docker): update golang:1.21 docker digest to 6fbd2d3 2024-01-12 03:44:29 +00:00
renovate[bot]
979b7c30fd chore(docker): update golang:1.21 docker digest to 21260a4 2024-01-11 17:09:59 +00:00
renovate[bot]
4abd84fbfa chore(docker): update golang:1.21 docker digest to ffbb0b8 2024-01-11 04:06:06 +00:00
renovate[bot]
b2d1403da4 chore(docker): update golang:1.21 docker digest to 7026fb7 2024-01-10 04:08:45 +00:00
renovate[bot]
033c273124
fix(deps): update module golang.org/x/sys to v0.16.0 (#5)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-04 20:33:39 +01:00
c539d62bbf
docs: fix default value property in data file 2024-01-03 23:26:18 +01:00
5776b9b829
docs: always set required data attr (#4) 2024-01-03 21:22:10 +01:00
6b506e6a31
chore: cleanup docs and use cmd trace from plugin lib (#3) 2024-01-02 22:58:05 +01:00
renovate[bot]
40636a12c5
fix(deps): update module github.com/thegeeklab/wp-plugin-go to v1.4.0 (#2)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-02 21:04:55 +01:00
31 changed files with 999 additions and 684 deletions

View File

@ -23,7 +23,6 @@ linters:
- errchkjson
- errname
- errorlint
- execinquery
- exhaustive
- exportloopref
- forcetypeassert
@ -37,12 +36,12 @@ linters:
- gocyclo
- godot
- godox
- goerr113
- err113
- gofmt
- gofumpt
- goheader
- goimports
- gomnd
- mnd
- gomoddirectives
- gomodguard
- goprintffuncname

View File

@ -7,7 +7,7 @@ when:
steps:
- name: dryrun
image: quay.io/thegeeklab/wp-docker-buildx:2
image: quay.io/thegeeklab/wp-docker-buildx:4
settings:
containerfile: Containerfile.multiarch
dry_run: true
@ -20,7 +20,7 @@ steps:
- event: [pull_request]
- name: publish-dockerhub
image: quay.io/thegeeklab/wp-docker-buildx:2
image: quay.io/thegeeklab/wp-docker-buildx:4
group: container
settings:
auto_tag: true
@ -41,7 +41,7 @@ steps:
- ${CI_REPO_DEFAULT_BRANCH}
- name: publish-quay
image: quay.io/thegeeklab/wp-docker-buildx:2
image: quay.io/thegeeklab/wp-docker-buildx:4
group: container
settings:
auto_tag: true

View File

@ -7,7 +7,7 @@ when:
steps:
- name: build
image: docker.io/techknowlogick/xgo:go-1.21.x
image: docker.io/techknowlogick/xgo:go-1.22.x
commands:
- ln -s $(pwd) /source
- make release

View File

@ -7,12 +7,12 @@ when:
steps:
- name: lint
image: docker.io/library/golang:1.21
image: docker.io/library/golang:1.22
commands:
- make lint
- name: test
image: docker.io/library/golang:1.21
image: docker.io/library/golang:1.22
commands:
- apt-get update
- apt-get install -y --no-install-recommends git git-lfs

View File

@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.21@sha256:672a2286da3ee7a854c3e0a56e0838918d0dbb1c18652992930293312de898a6 as build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.22@sha256:f43c6f049f04cbbaeb28f0aad3eea15274a7d0a7899a617d0037aec48d7ab010 as build
ARG TARGETOS
ARG TARGETARCH
@ -8,7 +8,7 @@ WORKDIR /src
RUN make build
FROM alpine:3.19@sha256:51b67269f354137895d43f3b3d810bfacd3945438e94dc5ac55fdac340352f48
FROM docker.io/library/alpine:3.20@sha256:77726ef6b57ddf65bb551896826ec38bc3e53f75cdde31354fbffb4f25238ebd
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"

View File

@ -1,7 +1,7 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.5.0
GOFUMPT_PACKAGE_VERSION := v0.6.0
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.55.2
GOLANGCI_LINT_PACKAGE_VERSION := v1.59.0
EXECUTABLE := wp-git-clone
@ -19,8 +19,7 @@ GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(G
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GOTESTSUM_PACKAGE ?= gotest.tools/gotestsum@latest
GENERATE ?=
XGO_VERSION := go-1.21.x
XGO_VERSION := go-1.22.x
XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64
TARGETOS ?= linux
@ -65,11 +64,7 @@ lint: golangci-lint
.PHONY: generate
generate:
$(GO) generate $(GENERATE)
.PHONY: generate-docs
generate-docs:
$(GO) generate ./cmd/$(EXECUTABLE)/flags.go
$(GO) generate $(PACKAGES)
.PHONY: test
test:

View File

@ -1,57 +0,0 @@
//go:build generate
// +build generate
package main
import (
"bytes"
"embed"
"fmt"
"os"
"text/template"
"github.com/thegeeklab/wp-git-clone/plugin"
"github.com/thegeeklab/wp-plugin-go/docs"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
"github.com/urfave/cli/v2"
)
//go:embed templates/docs-data.yaml.tmpl
var yamlTemplate embed.FS
func main() {
settings := &plugin.Settings{}
app := &cli.App{
Flags: settingsFlags(settings, wp.FlagsPluginCategory),
}
out, err := toYAML(app)
if err != nil {
panic(err)
}
fi, err := os.Create("../../docs/data/data-raw.yaml")
if err != nil {
panic(err)
}
defer fi.Close()
if _, err := fi.WriteString(out); err != nil {
panic(err)
}
}
func toYAML(app *cli.App) (string, error) {
var w bytes.Buffer
yamlTmpl, err := template.New("docs").ParseFS(yamlTemplate, "templates/docs-data.yaml.tmpl")
if err != nil {
fmt.Println(yamlTmpl)
return "", err
}
if err := yamlTmpl.ExecuteTemplate(&w, "docs-data.yaml.tmpl", docs.GetTemplateData(app)); err != nil {
return "", err
}
return w.String(), nil
}

View File

@ -1,174 +0,0 @@
// Copyright (c) 2020, the Drone Plugins project authors.
// Copyright (c) 2021, Robert Kaussow <mail@thegeeklab.de>
// Use of this source code is governed by an Apache 2.0 license that can be
// found in the LICENSE file.
package main
import (
"github.com/thegeeklab/wp-git-clone/plugin"
"github.com/thegeeklab/wp-plugin-go/types"
"github.com/urfave/cli/v2"
)
// settingsFlags has the cli.Flags for the plugin.Settings.
//
//go:generate go run docs.go flags.go
func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "remote",
Usage: "git remote url",
EnvVars: []string{"PLUGIN_REMOTE", "CI_REPO_CLONE_URL"},
Destination: &settings.Repo.RemoteURL,
Category: category,
},
&cli.StringFlag{
Name: "remote-ssh",
Usage: "git clone ssh url",
EnvVars: []string{"PLUGIN_REMOTE_SSH", "CI_REPO_CLONE_SSH_URL"},
Destination: &settings.Repo.RemoteSSH,
Category: category,
},
&cli.StringFlag{
Name: "workdir",
Usage: "path to clone git repository",
EnvVars: []string{"PLUGIN_WORKDIR", "CI_WORKSPACE"},
Destination: &settings.WorkDir,
Category: category,
},
&cli.StringFlag{
Name: "sha",
Usage: "git commit sha",
EnvVars: []string{"PLUGIN_COMMIT_SHA", "CI_COMMIT_SHA"},
Destination: &settings.Repo.CommitSha,
Category: category,
},
&cli.StringFlag{
Name: "ref",
Value: "refs/heads/main",
Usage: "git commit ref",
EnvVars: []string{"PLUGIN_COMMIT_REF", "CI_COMMIT_REF"},
Destination: &settings.Repo.CommitRef,
Category: category,
},
&cli.StringFlag{
Name: "netrc.machine",
Usage: "netrc machine",
EnvVars: []string{"CI_NETRC_MACHINE"},
Destination: &settings.Netrc.Machine,
Category: category,
},
&cli.StringFlag{
Name: "netrc.username",
Usage: "netrc username",
EnvVars: []string{"CI_NETRC_USERNAME"},
Destination: &settings.Netrc.Password,
Category: category,
},
&cli.StringFlag{
Name: "netrc.password",
Usage: "netrc password",
EnvVars: []string{"CI_NETRC_PASSWORD"},
Destination: &settings.Netrc.Password,
Category: category,
},
&cli.IntFlag{
Name: "depth",
Usage: "clone depth",
EnvVars: []string{"PLUGIN_DEPTH"},
Destination: &settings.Depth,
Category: category,
},
&cli.BoolFlag{
Name: "recursive",
Usage: "clone submodules",
EnvVars: []string{"PLUGIN_RECURSIVE"},
Value: true,
Destination: &settings.Recursive,
Category: category,
},
&cli.BoolFlag{
Name: "tags",
Usage: "fetch git tags during clone",
EnvVars: []string{"PLUGIN_TAGS"},
Value: true,
Destination: &settings.Tags,
Category: category,
},
&cli.BoolFlag{
Name: "insecure-skip-ssl-verify",
Usage: "skip ssl verification of the remote machine",
EnvVars: []string{"PLUGIN_INSECURE_SKIP_SSL_VERIFY"},
Destination: &settings.Repo.InsecureSkipSSLVerify,
Category: category,
},
&cli.BoolFlag{
Name: "submodule-update-remote",
Usage: "update remote submodules",
EnvVars: []string{"PLUGIN_SUBMODULES_UPDATE_REMOTE", "PLUGIN_SUBMODULE_UPDATE_REMOTE"},
Destination: &settings.Repo.SubmoduleRemote,
Category: category,
},
&cli.GenericFlag{
Name: "submodule-override",
Usage: "json map of submodule overrides",
EnvVars: []string{"PLUGIN_SUBMODULE_OVERRIDE"},
Value: &types.MapFlag{},
Category: category,
},
&cli.BoolFlag{
Name: "submodule-partial",
Usage: "update submodules via partial clone",
EnvVars: []string{"PLUGIN_SUBMODULES_PARTIAL", "PLUGIN_SUBMODULE_PARTIAL"},
Value: true,
Destination: &settings.Repo.SubmodulePartial,
Category: category,
},
&cli.BoolFlag{
Name: "lfs",
Usage: "whether to retrieve LFS content if available",
EnvVars: []string{"PLUGIN_LFS"},
Value: true,
Destination: &settings.Lfs,
Category: category,
},
&cli.StringFlag{
Name: "branch",
Usage: "change branch name",
EnvVars: []string{"PLUGIN_BRANCH", "CI_COMMIT_BRANCH", "CI_REPO_DEFAULT_BRANCH"},
Destination: &settings.Repo.Branch,
Value: "main",
Category: category,
},
&cli.BoolFlag{
Name: "partial",
Usage: "enable/disable partial clone",
EnvVars: []string{"PLUGIN_PARTIAL"},
Destination: &settings.Partial,
Category: category,
},
&cli.StringFlag{
Name: "safe-directory",
Usage: "define/replace safe directories",
EnvVars: []string{"PLUGIN_SAFE_DIRECTORY", "CI_WORKSPACE"},
Destination: &settings.Repo.SafeDirectory,
Category: category,
},
&cli.BoolFlag{
Name: "use-ssh",
Usage: "using ssh for git clone",
EnvVars: []string{"PLUGIN_USE_SSH"},
Destination: &settings.UseSSH,
Category: category,
},
&cli.StringFlag{
Name: "ssh-key",
Usage: "ssh key for ssh clone",
EnvVars: []string{"PLUGIN_SSH_KEY"},
Destination: &settings.SSHKey,
Category: category,
},
}
}

View File

@ -1,17 +1,7 @@
// Copyright (c) 2020, the Drone Plugins project authors.
// Copyright (c) 2021, Robert Kaussow <mail@thegeeklab.de>
// Use of this source code is governed by an Apache 2.0 license that can be
// found in the LICENSE file.
package main
import (
"fmt"
"github.com/thegeeklab/wp-git-clone/plugin"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
)
//nolint:gochecknoglobals
@ -21,14 +11,5 @@ var (
)
func main() {
settings := &plugin.Settings{}
options := wp.Options{
Name: "wp-git-clone",
Description: "Clone git repository",
Version: BuildVersion,
VersionMetadata: fmt.Sprintf("date=%s", BuildDate),
Flags: settingsFlags(settings, wp.FlagsPluginCategory),
}
plugin.New(options, settings).Run()
plugin.New(nil, BuildVersion, BuildDate).Run()
}

View File

@ -1,14 +0,0 @@
---
{{- if .GlobalArgs }}
properties:
{{- range $v := .GlobalArgs }}
- name: {{ $v.Name }}
{{- with $v.Description }}
description: |
{{ . }}
{{- end }}
{{- with $v.Default }}
defaultvalue: {{ . }}
{{- end }}
{{ end -}}
{{ end -}}

View File

@ -3,84 +3,125 @@ properties:
- name: branch
description: |
Change branch name.
defaultvalue: "main"
type: string
defaultValue: "main"
required: false
- name: commit_ref
description: |
Git commit ref.
defaultvalue: "refs/heads/main"
type: string
defaultValue: "refs/heads/main"
required: false
- name: commit_sha
description: |
Git commit sha.
type: string
defaultValue: $CI_COMMIT_SHA
required: false
- name: depth
description: |
Clone depth.
defaultvalue: 0
type: integer
defaultValue: 0
required: false
- name: insecure_skip_ssl_verify
- name: insecure_skip_verify
description: |
Skip SSL verification of the remote machine. Activating this option is insecure
and should be avoided in most cases.
defaultvalue: true
Skip SSL verification.
Activating this option is insecure and should be avoided in most cases.
type: bool
defaultValue: false
required: false
- name: lfs
description: |
Whether to retrieve LFS content if available.
defaultvalue: true
type: bool
defaultValue: true
required: false
- name: log_level
description: |
Plugin log level.
type: string
defaultValue: "info"
required: false
- name: partial
description: |
Enable/disable partial clone.
defaultvalue: false
type: bool
defaultValue: false
required: false
- name: recursive
description: |
Clone submodules.
defaultvalue: true
type: bool
defaultValue: true
required: false
- name: remote
description: |
Git remote HTTP clone url.
type: string
defaultValue: $CI_REPO_CLONE_URL
required: false
- name: remote_ssh
description: |
Git remote SSH clone url.
type: string
defaultValue: $CI_REPO_CLONE_SSH_URL
required: false
- name: safe_directory
description: |
Define/replace safe directories.
type: string
defaultValue: $CI_WORKSPACE
required: false
- name: ssh_key
description: |
SSH key for ssh clone.
Private key for SSH clone.
type: string
required: false
- name: submodule_override
description: |
JSON map of submodule overrides.
type: generic
required: false
- name: submodules_partial
description: |
Update submodules via partial clone (`depth=1`).
defaultvalue: true
type: bool
defaultValue: true
required: false
- name: submodules_update_remote
description: |
Update remote submodules.
defaultvalue: false
type: bool
defaultValue: false
required: false
- name: tags
description: |
Fetch git tags during clone.
defaultvalue: true
- name: use_ssh
description: |
Using ssh for git clone.
defaultvalue: false
type: bool
defaultValue: true
required: false
- name: workdir
description: |
Path to clone git repository.
type: string
defaultValue: $CI_WORKSPACE
required: false

View File

@ -2,35 +2,37 @@ package git
import (
"fmt"
"os"
"golang.org/x/sys/execabs"
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
)
// FetchSource fetches the source from remote.
func FetchSource(ref string, depth int, filter string) *execabs.Cmd {
func (r *Repository) FetchSource(ref string) *plugin_exec.Cmd {
args := []string{
"fetch",
}
if depth != 0 {
args = append(args, fmt.Sprintf("--depth=%d", depth))
if r.Depth != 0 {
args = append(args, fmt.Sprintf("--depth=%d", r.Depth))
}
if filter != "" {
args = append(args, "--filter="+filter)
if r.Filter != "" {
args = append(args, "--filter", r.Filter)
}
args = append(args, "origin")
args = append(args, fmt.Sprintf("+%s:", ref))
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}
// FetchTags fetches the source from remote.
func FetchTags() *execabs.Cmd {
func (r *Repository) FetchTags() *plugin_exec.Cmd {
args := []string{
"fetch",
"--tags",
@ -38,27 +40,29 @@ func FetchTags() *execabs.Cmd {
"origin",
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}
// FetchLFS fetches lfs.
func FetchLFS() *execabs.Cmd {
func (r *Repository) FetchLFS() *plugin_exec.Cmd {
args := []string{
"lfs",
"fetch",
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}
// CheckoutHead handles head checkout.
func CheckoutHead() *execabs.Cmd {
func (r *Repository) CheckoutHead() *plugin_exec.Cmd {
args := []string{
"checkout",
"--force",
@ -66,36 +70,39 @@ func CheckoutHead() *execabs.Cmd {
"FETCH_HEAD",
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}
// CheckoutSha handles commit checkout.
func CheckoutSha(repo Repository) *execabs.Cmd {
func (r *Repository) CheckoutSha() *plugin_exec.Cmd {
args := []string{
"reset",
"--hard",
"--quiet",
repo.CommitSha,
r.CommitSha,
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}
// CheckoutLFS handles commit checkout.
func CheckoutLFS() *execabs.Cmd {
func (r *Repository) CheckoutLFS() *plugin_exec.Cmd {
args := []string{
"lfs",
"checkout",
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}

View File

@ -2,62 +2,206 @@ package git
import (
"testing"
"github.com/stretchr/testify/assert"
)
// TestFetch tests if the arguments to `git fetch` are constructed properly.
func TestFetch(t *testing.T) {
func TestFetchSource(t *testing.T) {
testdata := []struct {
ref string
name string
repo *Repository
tags bool
depth int
exp []string
want []string
}{
{
"refs/heads/master",
false,
0,
[]string{
"/usr/bin/git",
name: "fetch main without tags",
repo: &Repository{
CommitRef: "refs/heads/main",
},
tags: false,
depth: 0,
want: []string{
gitBin,
"fetch",
"origin",
"+refs/heads/master:",
"+refs/heads/main:",
},
},
{
"refs/heads/master",
false,
50,
[]string{
"/usr/bin/git",
name: "fetch main without tags with depth",
repo: &Repository{
CommitRef: "refs/heads/main",
Depth: 50,
},
tags: false,
depth: 50,
want: []string{
gitBin,
"fetch",
"--depth=50",
"origin",
"+refs/heads/master:",
"+refs/heads/main:",
},
},
{
"refs/heads/master",
true,
100,
[]string{
"/usr/bin/git",
name: "fetch main with tags and depth",
repo: &Repository{
CommitRef: "refs/heads/main",
Depth: 100,
},
tags: true,
depth: 100,
want: []string{
gitBin,
"fetch",
"--depth=100",
"origin",
"+refs/heads/master:",
"+refs/heads/main:",
},
},
}
for _, td := range testdata {
c := FetchSource(td.ref, td.depth, "")
if len(c.Args) != len(td.exp) {
t.Errorf("Expected: %s, got %s", td.exp, c.Args)
}
for i := range c.Args {
if c.Args[i] != td.exp[i] {
t.Errorf("Expected: %s, got %s", td.exp, c.Args)
}
}
for _, tt := range testdata {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.FetchSource(tt.repo.CommitRef)
assert.Equal(t, tt.want, cmd.Args)
})
}
}
func TestFetchTags(t *testing.T) {
testdata := []struct {
name string
repo *Repository
tags bool
depth int
want []string
}{
{
name: "fetch tags",
repo: &Repository{},
tags: true,
want: []string{
gitBin,
"fetch",
"--tags",
"--quiet",
"origin",
},
},
}
for _, tt := range testdata {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.FetchTags()
assert.Equal(t, tt.want, cmd.Args)
})
}
}
func TestFetchLFS(t *testing.T) {
testdata := []struct {
name string
repo *Repository
want []string
}{
{
name: "fetch LFS",
repo: &Repository{},
want: []string{
gitBin,
"lfs",
"fetch",
},
},
}
for _, tt := range testdata {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.FetchLFS()
assert.Equal(t, tt.want, cmd.Args)
})
}
}
func TestCheckoutHead(t *testing.T) {
testdata := []struct {
name string
repo *Repository
want []string
}{
{
name: "checkout head",
repo: &Repository{},
want: []string{
gitBin,
"checkout",
"--force",
"--quiet",
"FETCH_HEAD",
},
},
}
for _, tt := range testdata {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.CheckoutHead()
assert.Equal(t, tt.want, cmd.Args)
})
}
}
func TestCheckoutSha(t *testing.T) {
testdata := []struct {
name string
repo *Repository
want []string
}{
{
name: "checkout sha",
repo: &Repository{
CommitSha: "abcd1234",
},
want: []string{
gitBin,
"reset",
"--hard",
"--quiet",
"abcd1234",
},
},
}
for _, tt := range testdata {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.CheckoutSha()
assert.Equal(t, tt.want, cmd.Args)
})
}
}
func TestCheckoutLFS(t *testing.T) {
testdata := []struct {
name string
repo *Repository
want []string
}{
{
name: "checkout LFS with no arguments",
repo: &Repository{},
want: []string{
gitBin,
"lfs",
"checkout",
},
},
}
for _, tt := range testdata {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.CheckoutLFS()
assert.Equal(t, tt.want, cmd.Args)
})
}
}

View File

@ -4,43 +4,43 @@ import (
"fmt"
"strconv"
"golang.org/x/sys/execabs"
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
)
// ConfigSSLVerify disables globally the git ssl verification.
func ConfigSSLVerify(repo Repository) *execabs.Cmd {
func (r *Repository) ConfigSSLVerify(skipVerify bool) *plugin_exec.Cmd {
args := []string{
"config",
"--global",
"http.sslVerify",
strconv.FormatBool(!repo.InsecureSkipSSLVerify),
strconv.FormatBool(!skipVerify),
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Trace = false
return cmd
}
// ConfigSafeDirectory disables globally the git ssl verification.
func ConfigSafeDirectory(repo Repository) *execabs.Cmd {
func (r *Repository) ConfigSafeDirectory() *plugin_exec.Cmd {
args := []string{
"config",
"--global",
"--replace-all",
"safe.directory",
repo.SafeDirectory,
r.SafeDirectory,
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Trace = false
return cmd
}
// ConfigRemapSubmodule returns a git command that, when executed configures git to
// remap submodule urls.
func ConfigRemapSubmodule(name, url string) *execabs.Cmd {
func (r *Repository) ConfigRemapSubmodule(name, url string) *plugin_exec.Cmd {
args := []string{
"config",
"--global",
@ -48,14 +48,14 @@ func ConfigRemapSubmodule(name, url string) *execabs.Cmd {
url,
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Trace = false
return cmd
}
// ConfigSSHCommand sets custom SSH key.
func ConfigSSHCommand(sshKey string) *execabs.Cmd {
func (r *Repository) ConfigSSHCommand(sshKey string) *plugin_exec.Cmd {
args := []string{
"config",
"--global",
@ -63,8 +63,8 @@ func ConfigSSHCommand(sshKey string) *execabs.Cmd {
"ssh -i " + sshKey,
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Trace = false
return cmd
}

121
git/config_test.go Normal file
View File

@ -0,0 +1,121 @@
package git
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestConfigSSLVerify(t *testing.T) {
tests := []struct {
name string
repo Repository
skipVerify bool
want []string
}{
{
name: "enable SSL verification",
repo: Repository{},
skipVerify: false,
want: []string{gitBin, "config", "--global", "http.sslVerify", "true"},
},
{
name: "disable SSL verification",
repo: Repository{},
skipVerify: true,
want: []string{gitBin, "config", "--global", "http.sslVerify", "false"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.ConfigSSLVerify(tt.skipVerify)
assert.Equal(t, tt.want, cmd.Cmd.Args)
})
}
}
func TestConfigSafeDirectory(t *testing.T) {
tests := []struct {
name string
repo Repository
safeDir string
want []string
}{
{
name: "set safe directory",
repo: Repository{
SafeDirectory: "/path/to/safe/dir",
},
want: []string{gitBin, "config", "--global", "--replace-all", "safe.directory", "/path/to/safe/dir"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.ConfigSafeDirectory()
assert.Equal(t, tt.want, cmd.Cmd.Args)
})
}
}
func TestConfigRemapSubmodule(t *testing.T) {
tests := []struct {
name string
repo Repository
subName string
subURL string
want []string
}{
{
name: "remap submodule URL",
repo: Repository{},
subName: "mysubmodule",
subURL: "https://example.com/mysubmodule.git",
want: []string{
gitBin, "config", "--global", "submodule.mysubmodule.url",
"https://example.com/mysubmodule.git",
},
},
{
name: "remap submodule URL with spaces",
repo: Repository{},
subName: "my submodule",
subURL: "https://example.com/my submodule.git",
want: []string{
gitBin, "config", "--global", "submodule.my submodule.url",
"https://example.com/my submodule.git",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.ConfigRemapSubmodule(tt.subName, tt.subURL)
assert.Equal(t, tt.want, cmd.Cmd.Args)
})
}
}
func TestConfigSSHCommand(t *testing.T) {
tests := []struct {
name string
repo Repository
sshKey string
want []string
}{
{
name: "set SSH command with key",
repo: Repository{},
sshKey: "/path/to/ssh/key",
want: []string{gitBin, "config", "--global", "core.sshCommand", "ssh -i /path/to/ssh/key"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.ConfigSSHCommand(tt.sshKey)
assert.Equal(t, tt.want, cmd.Cmd.Args)
})
}
}

View File

@ -1,7 +1,5 @@
package git
const gitBin = "/usr/bin/git"
type Repository struct {
RemoteURL string
RemoteSSH string
@ -12,7 +10,11 @@ type Repository struct {
SubmoduleRemote bool
SubmodulePartial bool
InsecureSkipSSLVerify bool
SafeDirectory string
InitExists bool
SafeDirectory string
WorkDir string
IsEmpty bool
Filter string
Depth int
}
const gitBin = "/usr/bin/git"

View File

@ -1,19 +1,22 @@
package git
import (
"golang.org/x/sys/execabs"
"os"
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
)
// RemoteRemove drops the defined remote from a git repo.
func Init(repo Repository) *execabs.Cmd {
func (r *Repository) Init() *plugin_exec.Cmd {
args := []string{
"init",
"-b",
repo.Branch,
r.Branch,
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}

30
git/init_test.go Normal file
View File

@ -0,0 +1,30 @@
package git
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestInit(t *testing.T) {
tests := []struct {
name string
repo Repository
expected []string
}{
{
name: "init repo",
repo: Repository{
Branch: "main",
},
expected: []string{gitBin, "init", "-b", "main"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.Init()
assert.Equal(t, tt.expected, cmd.Cmd.Args)
})
}
}

View File

@ -1,20 +1,23 @@
package git
import (
"golang.org/x/sys/execabs"
"os"
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
)
// RemoteAdd adds an additional remote to a git repo.
func RemoteAdd(url string) *execabs.Cmd {
func (r *Repository) RemoteAdd() *plugin_exec.Cmd {
args := []string{
"remote",
"add",
"origin",
url,
r.RemoteURL,
}
return execabs.Command(
gitBin,
args...,
)
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}

31
git/remote_test.go Normal file
View File

@ -0,0 +1,31 @@
package git
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestRemoteAdd(t *testing.T) {
tests := []struct {
name string
repo Repository
want []string
}{
{
name: "add remote with valid inputs",
repo: Repository{
RemoteURL: "https://example.com/repo.git",
},
want: []string{gitBin, "remote", "add", "origin", "https://example.com/repo.git"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.RemoteAdd()
assert.Equal(t, tt.want, cmd.Cmd.Args)
assert.Equal(t, tt.repo.WorkDir, cmd.Cmd.Dir)
})
}
}

View File

@ -1,11 +1,13 @@
package git
import (
"golang.org/x/sys/execabs"
"os"
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
)
// SubmoduleUpdate recursively initializes and updates submodules.
func SubmoduleUpdate(repo Repository) *execabs.Cmd {
func (r *Repository) SubmoduleUpdate() *plugin_exec.Cmd {
args := []string{
"submodule",
"update",
@ -13,18 +15,17 @@ func SubmoduleUpdate(repo Repository) *execabs.Cmd {
"--recursive",
}
if repo.SubmodulePartial {
if r.SubmodulePartial {
args = append(args, "--depth=1", "--recommend-shallow")
}
cmd := execabs.Command(
gitBin,
args...,
)
if repo.SubmoduleRemote {
cmd.Args = append(cmd.Args, "--remote")
if r.SubmoduleRemote {
args = append(args, "--remote")
}
cmd := plugin_exec.Command(gitBin, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}

View File

@ -2,19 +2,25 @@ package git
import (
"testing"
"github.com/stretchr/testify/assert"
)
// TestUpdateSubmodules tests if the arguments to `git submodule update`
// are constructed properly.
func TestUpdateSubmodules(t *testing.T) {
tests := []struct {
partial bool
exp []string
name string
repo *Repository
want []string
}{
{
false,
[]string{
"/usr/bin/git",
name: "full submodule update",
repo: &Repository{
SubmodulePartial: false,
},
want: []string{
gitBin,
"submodule",
"update",
"--init",
@ -22,9 +28,12 @@ func TestUpdateSubmodules(t *testing.T) {
},
},
{
true,
[]string{
"/usr/bin/git",
name: "partial submodule update",
repo: &Repository{
SubmodulePartial: true,
},
want: []string{
gitBin,
"submodule",
"update",
"--init",
@ -33,35 +42,13 @@ func TestUpdateSubmodules(t *testing.T) {
"--recommend-shallow",
},
},
}
for _, tt := range tests {
repo := Repository{
SubmoduleRemote: false,
SubmodulePartial: tt.partial,
}
c := SubmoduleUpdate(repo)
if len(c.Args) != len(tt.exp) {
t.Errorf("Expected: %s, got %s", tt.exp, c.Args)
}
for i := range c.Args {
if c.Args[i] != tt.exp[i] {
t.Errorf("Expected: %s, got %s", tt.exp, c.Args)
}
}
}
}
// TestUpdateSubmodules tests if the arguments to `git submodule update`
// are constructed properly.
func TestUpdateSubmodulesRemote(t *testing.T) {
tests := []struct {
exp []string
}{
{
[]string{
"/usr/bin/git",
name: "submodule update with remote",
repo: &Repository{
SubmoduleRemote: true,
},
want: []string{
gitBin,
"submodule",
"update",
"--init",
@ -70,31 +57,28 @@ func TestUpdateSubmodulesRemote(t *testing.T) {
},
},
{
[]string{
"/usr/bin/git",
name: "submodule update with remote and partial",
repo: &Repository{
SubmoduleRemote: true,
SubmodulePartial: true,
},
want: []string{
gitBin,
"submodule",
"update",
"--init",
"--recursive",
"--depth=1",
"--recommend-shallow",
"--remote",
},
},
}
for _, tt := range tests {
repo := Repository{
SubmoduleRemote: true,
SubmodulePartial: false,
}
c := SubmoduleUpdate(repo)
if len(c.Args) != len(tt.exp) {
t.Errorf("Expected: %s, got %s", tt.exp, c.Args)
}
for i := range c.Args {
if c.Args[i] != tt.exp[i] {
t.Errorf("Expected: %s, got %s", tt.exp, c.Args)
}
}
t.Run(tt.name, func(t *testing.T) {
cmd := tt.repo.SubmoduleUpdate()
assert.Equal(t, tt.want, cmd.Args)
})
}
}

View File

@ -1,47 +0,0 @@
package git
import (
"fmt"
"os"
"os/user"
"path/filepath"
)
const (
netrcFile = `
machine %s
login %s
password %s
`
)
const (
strictFilePerm = 0o600
)
// WriteNetrc writes the netrc file.
func WriteNetrc(machine, login, password string) error {
netrcContent := fmt.Sprintf(
netrcFile,
machine,
login,
password,
)
home := "/root"
if currentUser, err := user.Current(); err == nil {
home = currentUser.HomeDir
}
netpath := filepath.Join(
home,
".netrc",
)
return os.WriteFile(
netpath,
[]byte(netrcContent),
strictFilePerm,
)
}

24
go.mod
View File

@ -1,20 +1,21 @@
module github.com/thegeeklab/wp-git-clone
go 1.21
go 1.22
require (
github.com/cenkalti/backoff/v4 v4.2.1
github.com/rs/zerolog v1.31.0
github.com/thegeeklab/wp-plugin-go v1.3.0
github.com/urfave/cli/v2 v2.26.0
golang.org/x/sys v0.15.0
github.com/cenkalti/backoff/v4 v4.3.0
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.9.0
github.com/thegeeklab/wp-plugin-go/v3 v3.0.2
github.com/urfave/cli/v2 v2.27.2
)
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.1.1 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.11 // indirect
@ -23,10 +24,13 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.19.0 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

41
go.sum
View File

@ -5,11 +5,11 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -35,8 +35,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
@ -46,27 +46,27 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/thegeeklab/wp-plugin-go v1.3.0 h1:Yhz0dTDwXcbeaoyoPOXNDf2RzSoUixHuE+ML27cYy2E=
github.com/thegeeklab/wp-plugin-go v1.3.0/go.mod h1:EUOH6XJ8G/bcd6gmM6a6vLeta+keyX9ul1Es0F0r2Lc=
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/thegeeklab/wp-plugin-go/v3 v3.0.2 h1:Mv5i8S1WY+BUNjTjX6lOnB3p8S9mvM+XwfY4R98gx0g=
github.com/thegeeklab/wp-plugin-go/v3 v3.0.2/go.mod h1:ij1iJcAVgzerBTqXnmq0bu1VA+hhVVwzXKqiqfoGjjg=
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -78,8 +78,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@ -91,6 +91,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=

42
internal/doc/main.go Normal file
View File

@ -0,0 +1,42 @@
//go:build generate
// +build generate
package main
import (
"context"
"flag"
"net/http"
"os"
"time"
"github.com/thegeeklab/wp-git-clone/plugin"
plugin_docs "github.com/thegeeklab/wp-plugin-go/v3/docs"
plugin_template "github.com/thegeeklab/wp-plugin-go/v3/template"
)
func main() {
tmpl := "https://raw.githubusercontent.com/thegeeklab/woodpecker-plugins/main/templates/docs-data.yaml.tmpl"
client := http.Client{
Timeout: 30 * time.Second,
}
p := plugin.New(nil)
out, err := plugin_template.Render(context.Background(), client, tmpl, plugin_docs.GetTemplateData(p.App))
if err != nil {
panic(err)
}
outputFile := flag.String("output", "", "Output file path")
flag.Parse()
if *outputFile == "" {
panic("no output file specified")
}
err = os.WriteFile(*outputFile, []byte(out), 0o644)
if err != nil {
panic(err)
}
}

View File

@ -1,8 +1,3 @@
// Copyright (c) 2023, Robert Kaussow <mail@thegeeklab.de>
// Use of this source code is governed by an Apache 2.0 license that can be
// found in the LICENSE file.
package plugin
import (
@ -13,13 +8,13 @@ import (
"io"
"os"
"path/filepath"
"strings"
"time"
"github.com/rs/zerolog/log"
"github.com/thegeeklab/wp-git-clone/git"
"github.com/thegeeklab/wp-plugin-go/types"
"golang.org/x/sys/execabs"
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
plugin_file "github.com/thegeeklab/wp-plugin-go/v3/file"
plugin_types "github.com/thegeeklab/wp-plugin-go/v3/types"
plugin_util "github.com/thegeeklab/wp-plugin-go/v3/util"
)
const (
@ -52,16 +47,24 @@ func (p *Plugin) run(ctx context.Context) error {
// Validate handles the settings validation of the plugin.
func (p *Plugin) Validate() error {
if p.Settings.WorkDir == "" {
var err error
if p.Settings.WorkDir, err = os.Getwd(); err != nil {
return err
var err error
// This default cannot be set in the cli flag, as the CI_* environment variables
// can be set empty, resulting in an empty default value.
if p.Settings.Repo.Branch == "" {
p.Settings.Repo.Branch = "main"
}
if p.Settings.Repo.WorkDir == "" {
p.Settings.Repo.WorkDir, err = os.Getwd()
if err != nil {
return fmt.Errorf("failed to get working directory: %w", err)
}
}
if p.Settings.Partial {
p.Settings.Depth = 1
p.Settings.Filter = "tree:0"
p.Settings.Repo.Depth = 1
p.Settings.Repo.Filter = "tree:0"
}
return nil
@ -69,76 +72,97 @@ func (p *Plugin) Validate() error {
// Execute provides the implementation of the plugin.
func (p *Plugin) Execute() error {
cmds := make([]*execabs.Cmd, 0)
var err error
// Handle init
initPath := filepath.Join(p.Settings.WorkDir, ".git")
homeDir := plugin_util.GetUserHomeDir()
batchCmd := make([]*plugin_exec.Cmd, 0)
if err := os.MkdirAll(p.Settings.WorkDir, os.ModePerm); err != nil {
return err
fmt.Println(p.Settings.Repo.WorkDir)
// Handle repo initialization.
if err := os.MkdirAll(p.Settings.Repo.WorkDir, os.ModePerm); err != nil {
return fmt.Errorf("failed to create working directory: %w", err)
}
//nolint:nestif
if _, err := os.Stat(initPath); os.IsNotExist(err) {
cmds = append(cmds, git.ConfigSafeDirectory(p.Settings.Repo))
p.Settings.Repo.IsEmpty, err = plugin_file.IsDirEmpty(p.Settings.Repo.WorkDir)
if err != nil {
return fmt.Errorf("failed to check working directory: %w", err)
}
if err := p.execCmd(git.Init(p.Settings.Repo), new(bytes.Buffer)); err != nil {
return err
}
isDir, err := plugin_file.IsDir(filepath.Join(p.Settings.Repo.WorkDir, ".git"))
if err != nil {
return fmt.Errorf("failed to check working directory: %w", err)
}
if p.Settings.UseSSH {
cmds = append(cmds, git.RemoteAdd(p.Settings.Repo.RemoteSSH))
if p.Settings.SSHKey != "" {
cmds = append(cmds, git.ConfigSSHCommand(p.Settings.SSHKey))
}
} else {
cmds = append(cmds, git.RemoteAdd(p.Settings.Repo.RemoteURL))
if !isDir {
batchCmd = append(batchCmd, p.Settings.Repo.Init())
batchCmd = append(batchCmd, p.Settings.Repo.RemoteAdd())
if p.Settings.SSHKey != "" {
batchCmd = append(batchCmd, p.Settings.Repo.ConfigSSHCommand(p.Settings.SSHKey))
}
}
if p.Settings.Repo.InsecureSkipSSLVerify {
cmds = append(cmds, git.ConfigSSLVerify(p.Settings.Repo))
}
batchCmd = append(batchCmd, p.Settings.Repo.ConfigSSLVerify(p.Network.InsecureSkipVerify))
if err := git.WriteNetrc(p.Settings.Netrc.Machine, p.Settings.Netrc.Login, p.Settings.Netrc.Password); err != nil {
netrc := p.Settings.Netrc
if err := WriteNetrc(homeDir, netrc.Machine, netrc.Login, netrc.Password); err != nil {
return err
}
// Handle clone
if p.Settings.Repo.CommitSha == "" {
// fetch and checkout by ref
log.Info().Msg("no commit information: using head checkout")
cmds = append(cmds, git.FetchSource(p.Settings.Repo.CommitRef, p.Settings.Depth, p.Settings.Filter))
cmds = append(cmds, git.CheckoutHead())
batchCmd = append(batchCmd, p.Settings.Repo.FetchSource(p.Settings.Repo.CommitRef))
batchCmd = append(batchCmd, p.Settings.Repo.CheckoutHead())
} else {
cmds = append(cmds, git.FetchSource(p.Settings.Repo.CommitSha, p.Settings.Depth, p.Settings.Filter))
cmds = append(cmds, git.CheckoutSha(p.Settings.Repo))
batchCmd = append(batchCmd, p.Settings.Repo.FetchSource(p.Settings.Repo.CommitSha))
batchCmd = append(batchCmd, p.Settings.Repo.CheckoutSha())
}
if p.Settings.Tags {
cmds = append(cmds, git.FetchTags())
batchCmd = append(batchCmd, p.Settings.Repo.FetchTags())
}
for name, submoduleURL := range p.Settings.Repo.Submodules {
cmds = append(cmds, git.ConfigRemapSubmodule(name, submoduleURL))
batchCmd = append(batchCmd, p.Settings.Repo.ConfigRemapSubmodule(name, submoduleURL))
}
if p.Settings.Recursive {
cmds = append(cmds, git.SubmoduleUpdate(p.Settings.Repo))
batchCmd = append(batchCmd, p.Settings.Repo.SubmoduleUpdate())
}
if p.Settings.Lfs {
cmds = append(cmds, git.FetchLFS())
cmds = append(cmds, git.CheckoutLFS())
batchCmd = append(batchCmd, p.Settings.Repo.FetchLFS())
batchCmd = append(batchCmd, p.Settings.Repo.CheckoutLFS())
}
for _, cmd := range cmds {
log.Debug().Msgf("+ %s", strings.Join(cmd.Args, " "))
for _, cmd := range batchCmd {
if cmd == nil {
continue
}
buf := new(bytes.Buffer)
err := p.execCmd(cmd, buf)
// Don' set GIT_TERMINAL_PROMPT=0 as it prevents git from loading .netrc
defaultEnvVars := []string{
"GIT_LFS_SKIP_SMUDGE=1", // prevents git-lfs from retrieving any LFS files
}
if p.Settings.Home != "" {
if _, err := os.Stat(p.Settings.Home); !os.IsNotExist(err) {
defaultEnvVars = append(defaultEnvVars, fmt.Sprintf("HOME=%s", p.Settings.Home))
}
}
cmd.Env = append(os.Environ(), defaultEnvVars...)
cmd.Stdout = io.MultiWriter(os.Stdout, buf)
cmd.Stderr = io.MultiWriter(os.Stderr, buf)
cmd.Dir = p.Settings.Repo.WorkDir
err := cmd.Run()
switch {
case err != nil && shouldRetry(buf.String()):
@ -152,7 +176,7 @@ func (p *Plugin) Execute() error {
}
func (p *Plugin) FlagsFromContext() error {
submodules, ok := p.Context.Generic("submodule-override").(*types.MapFlag)
submodules, ok := p.Context.Generic("submodule-override").(*plugin_types.MapFlag)
if !ok {
return fmt.Errorf("%w: failed to read submodule-override input", ErrTypeAssertionFailed)
}
@ -161,25 +185,3 @@ func (p *Plugin) FlagsFromContext() error {
return nil
}
func (p *Plugin) execCmd(cmd *execabs.Cmd, buf *bytes.Buffer) error {
// Don' set GIT_TERMINAL_PROMPT=0 as it prevents git from loading .netrc
defaultEnvVars := []string{
"GIT_LFS_SKIP_SMUDGE=1", // prevents git-lfs from retrieving any LFS files
}
if p.Settings.Home != "" {
if _, err := os.Stat(p.Settings.Home); !os.IsNotExist(err) {
defaultEnvVars = append(defaultEnvVars, fmt.Sprintf("HOME=%s", p.Settings.Home))
}
}
cmd.Env = append(os.Environ(), defaultEnvVars...)
cmd.Stdout = io.MultiWriter(os.Stdout, buf)
cmd.Stderr = io.MultiWriter(os.Stderr, buf)
cmd.Dir = p.Settings.WorkDir
trace(cmd)
return cmd.Run()
}

View File

@ -1,6 +1,7 @@
package plugin
import (
"context"
"os"
"path/filepath"
"testing"
@ -28,19 +29,18 @@ func TestClone(t *testing.T) {
dir := setup()
defer teardown(dir)
plugin := Plugin{
Settings: &Settings{
Repo: git.Repository{
RemoteURL: tt.clone,
CommitRef: tt.ref,
CommitSha: tt.commit,
Branch: "main",
},
Home: "/tmp",
plugin := New(func(_ context.Context) error { return nil })
plugin.Settings = &Settings{
Repo: git.Repository{
RemoteURL: tt.clone,
CommitRef: tt.ref,
CommitSha: tt.commit,
Branch: "main",
WorkDir: filepath.Join(dir, tt.path),
Recursive: tt.recursive,
Lfs: tt.lfs,
},
Home: "/tmp",
Recursive: tt.recursive,
Lfs: tt.lfs,
}
if err := plugin.Execute(); err != nil {
@ -48,14 +48,14 @@ func TestClone(t *testing.T) {
}
if tt.data != "" {
data := readFile(plugin.Settings.WorkDir, tt.file)
data := readFile(plugin.Settings.Repo.WorkDir, tt.file)
if data != tt.data {
t.Errorf("Expected %s to contain [%s]. Got [%s].", tt.file, tt.data, data)
}
}
if tt.dataSize != 0 {
size := getFileSize(plugin.Settings.WorkDir, tt.file)
size := getFileSize(plugin.Settings.Repo.WorkDir, tt.file)
if size != tt.dataSize {
t.Errorf("Expected %s size to be [%d]. Got [%d].", tt.file, tt.dataSize, size)
}
@ -71,19 +71,18 @@ func TestCloneNonEmpty(t *testing.T) {
defer teardown(dir)
for _, tt := range getCommits() {
plugin := Plugin{
Settings: &Settings{
Repo: git.Repository{
RemoteURL: tt.clone,
CommitRef: tt.ref,
CommitSha: tt.commit,
Branch: "main",
},
Home: "/tmp",
plugin := New(func(_ context.Context) error { return nil })
plugin.Settings = &Settings{
Repo: git.Repository{
RemoteURL: tt.clone,
CommitRef: tt.ref,
CommitSha: tt.commit,
Branch: "main",
WorkDir: filepath.Join(dir, tt.path),
Recursive: tt.recursive,
Lfs: tt.lfs,
},
Home: "/tmp",
Recursive: tt.recursive,
Lfs: tt.lfs,
}
if err := plugin.Execute(); err != nil {
@ -91,7 +90,7 @@ func TestCloneNonEmpty(t *testing.T) {
}
if tt.data != "" {
data := readFile(plugin.Settings.WorkDir, tt.file)
data := readFile(plugin.Settings.Repo.WorkDir, tt.file)
if data != tt.data {
t.Errorf("Expected %s to contain [%q]. Got [%q].", tt.file, tt.data, data)
@ -100,7 +99,7 @@ func TestCloneNonEmpty(t *testing.T) {
}
if tt.dataSize != 0 {
size := getFileSize(plugin.Settings.WorkDir, tt.file)
size := getFileSize(plugin.Settings.Repo.WorkDir, tt.file)
if size != tt.dataSize {
t.Errorf("Expected %s size to be [%d]. Got [%d].", tt.file, tt.dataSize, size)
}

View File

@ -1,18 +1,19 @@
// Copyright (c) 2023, Robert Kaussow <mail@thegeeklab.de>
// Use of this source code is governed by an Apache 2.0 license that can be
// found in the LICENSE file.
package plugin
import (
"fmt"
"github.com/thegeeklab/wp-git-clone/git"
wp "github.com/thegeeklab/wp-plugin-go/plugin"
plugin_base "github.com/thegeeklab/wp-plugin-go/v3/plugin"
plugin_types "github.com/thegeeklab/wp-plugin-go/v3/types"
"github.com/urfave/cli/v2"
)
//go:generate go run ../internal/doc/main.go -output=../docs/data/data-raw.yaml
// Plugin implements provide the plugin.
type Plugin struct {
*wp.Plugin
*plugin_base.Plugin
Settings *Settings
}
@ -24,28 +25,192 @@ type Netrc struct {
// Settings for the plugin.
type Settings struct {
Depth int
Recursive bool
Tags bool
Lfs bool
Partial bool
Filter string
UseSSH bool
SSHKey string
Home string
WorkDir string
SSHKey string
Netrc Netrc
Repo git.Repository
}
func New(options wp.Options, settings *Settings) *Plugin {
p := &Plugin{}
func New(e plugin_base.ExecuteFunc, build ...string) *Plugin {
p := &Plugin{
Settings: &Settings{},
}
options.Execute = p.run
options := plugin_base.Options{
Name: "wp-git-clone",
Description: "Clone git repository",
Flags: Flags(p.Settings, plugin_base.FlagsPluginCategory),
Execute: p.run,
HideWoodpeckerFlags: true,
}
p.Plugin = wp.New(options)
p.Settings = settings
if len(build) > 0 {
options.Version = build[0]
}
if len(build) > 1 {
options.VersionMetadata = fmt.Sprintf("date=%s", build[1])
}
if e != nil {
options.Execute = e
}
p.Plugin = plugin_base.New(options)
return p
}
// Flags returns a slice of CLI flags for the plugin.
func Flags(settings *Settings, category string) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "remote",
Usage: "git remote HTTP clone url",
EnvVars: []string{"PLUGIN_REMOTE", "CI_REPO_CLONE_URL"},
Destination: &settings.Repo.RemoteURL,
DefaultText: "$CI_REPO_CLONE_URL",
Category: category,
},
&cli.StringFlag{
Name: "remote-ssh",
Usage: "git remote SSH clone url",
EnvVars: []string{"PLUGIN_REMOTE_SSH", "CI_REPO_CLONE_SSH_URL"},
Destination: &settings.Repo.RemoteSSH,
DefaultText: "$CI_REPO_CLONE_SSH_URL",
Category: category,
},
&cli.StringFlag{
Name: "workdir",
Usage: "path to clone git repository",
EnvVars: []string{"PLUGIN_WORKDIR", "CI_WORKSPACE"},
Destination: &settings.Repo.WorkDir,
DefaultText: "$CI_WORKSPACE",
Category: category,
},
&cli.StringFlag{
Name: "sha",
Usage: "git commit sha",
EnvVars: []string{"PLUGIN_COMMIT_SHA", "CI_COMMIT_SHA"},
Destination: &settings.Repo.CommitSha,
DefaultText: "$CI_COMMIT_SHA",
Category: category,
},
&cli.StringFlag{
Name: "ref",
Usage: "git commit ref",
EnvVars: []string{"PLUGIN_COMMIT_REF", "CI_COMMIT_REF"},
Value: "refs/heads/main",
Destination: &settings.Repo.CommitRef,
Category: category,
},
&cli.StringFlag{
Name: "netrc.machine",
Usage: "netrc machine",
EnvVars: []string{"CI_NETRC_MACHINE"},
Destination: &settings.Netrc.Machine,
Category: category,
},
&cli.StringFlag{
Name: "netrc.username",
Usage: "netrc username",
EnvVars: []string{"CI_NETRC_USERNAME"},
Destination: &settings.Netrc.Password,
Category: category,
},
&cli.StringFlag{
Name: "netrc.password",
Usage: "netrc password",
EnvVars: []string{"CI_NETRC_PASSWORD"},
Destination: &settings.Netrc.Password,
Category: category,
},
&cli.IntFlag{
Name: "depth",
Usage: "clone depth",
EnvVars: []string{"PLUGIN_DEPTH"},
Destination: &settings.Repo.Depth,
Category: category,
},
&cli.BoolFlag{
Name: "recursive",
Usage: "clone submodules",
EnvVars: []string{"PLUGIN_RECURSIVE"},
Value: true,
Destination: &settings.Recursive,
Category: category,
},
&cli.BoolFlag{
Name: "tags",
Usage: "fetch git tags during clone",
EnvVars: []string{"PLUGIN_TAGS"},
Value: true,
Destination: &settings.Tags,
Category: category,
},
&cli.BoolFlag{
Name: "submodule-update-remote",
Usage: "update remote submodules",
EnvVars: []string{"PLUGIN_SUBMODULES_UPDATE_REMOTE", "PLUGIN_SUBMODULE_UPDATE_REMOTE"},
Destination: &settings.Repo.SubmoduleRemote,
Category: category,
},
&cli.GenericFlag{
Name: "submodule-override",
Usage: "JSON map of submodule overrides",
EnvVars: []string{"PLUGIN_SUBMODULE_OVERRIDE"},
Value: &plugin_types.MapFlag{},
Category: category,
},
&cli.BoolFlag{
Name: "submodule-partial",
Usage: "update submodules via partial clone (`depth=1`)",
EnvVars: []string{"PLUGIN_SUBMODULES_PARTIAL", "PLUGIN_SUBMODULE_PARTIAL"},
Value: true,
Destination: &settings.Repo.SubmodulePartial,
Category: category,
},
&cli.BoolFlag{
Name: "lfs",
Usage: "whether to retrieve LFS content if available",
EnvVars: []string{"PLUGIN_LFS"},
Value: true,
Destination: &settings.Lfs,
Category: category,
},
&cli.StringFlag{
Name: "branch",
Usage: "change branch name",
EnvVars: []string{"PLUGIN_BRANCH", "CI_COMMIT_BRANCH", "CI_REPO_DEFAULT_BRANCH"},
Destination: &settings.Repo.Branch,
Category: category,
},
&cli.BoolFlag{
Name: "partial",
Usage: "enable/disable partial clone",
EnvVars: []string{"PLUGIN_PARTIAL"},
Destination: &settings.Partial,
Category: category,
},
&cli.StringFlag{
Name: "safe-directory",
Usage: "define/replace safe directories",
EnvVars: []string{"PLUGIN_SAFE_DIRECTORY", "CI_WORKSPACE"},
Destination: &settings.Repo.SafeDirectory,
DefaultText: "$CI_WORKSPACE",
Category: category,
},
&cli.StringFlag{
Name: "ssh-key",
Usage: "private key for SSH clone",
EnvVars: []string{"PLUGIN_SSH_KEY"},
Destination: &settings.SSHKey,
Category: category,
},
}
}

38
plugin/plugin_test.go Normal file
View File

@ -0,0 +1,38 @@
package plugin
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_pluginOptions(t *testing.T) {
tests := []struct {
name string
envs map[string]string
want string
}{
{
name: "ensure default branch is set",
envs: map[string]string{
"CI_COMMIT_BRANCH": "",
},
want: "main",
},
}
for _, tt := range tests {
for key, value := range tt.envs {
t.Setenv(key, value)
}
got := New(func(_ context.Context) error { return nil })
_ = got.App.Run([]string{"wp-git-clone"})
_ = got.Validate()
_ = got.FlagsFromContext()
assert.EqualValues(t, tt.want, got.Settings.Repo.Branch)
}
}

View File

@ -3,12 +3,21 @@ package plugin
import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/rs/zerolog/log"
"golang.org/x/sys/execabs"
plugin_exec "github.com/thegeeklab/wp-plugin-go/v3/exec"
)
const (
netrcFile = `machine %s
login %s
password %s
`
strictFilePerm = 0o600
)
// shouldRetry returns true if the command should be re-executed. Currently
@ -25,23 +34,16 @@ func newBackoff(maxRetries uint64) backoff.BackOff {
return backoff.WithMaxRetries(b, maxRetries)
}
func trace(cmd *execabs.Cmd) {
fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " "))
}
func retryCmd(cmd *execabs.Cmd) error {
func retryCmd(cmd *plugin_exec.Cmd) error {
backoffOps := func() error {
// copy the original command
//nolint:gosec
retry := execabs.Command(cmd.Args[0], cmd.Args[1:]...)
retry.Dir = cmd.Dir
retry := plugin_exec.Command(cmd.Cmd.Path, cmd.Cmd.Args...)
retry.Env = cmd.Env
retry.Stdout = os.Stdout
retry.Stderr = os.Stderr
retry.Stdout = cmd.Stdout
retry.Stderr = cmd.Stderr
retry.Dir = cmd.Dir
trace(cmd)
return cmd.Run()
return retry.Run()
}
backoffLog := func(err error, delay time.Duration) {
log.Error().Msgf("failed to find remote ref: %v: retry in %s", err, delay.Truncate(time.Second))
@ -49,3 +51,15 @@ func retryCmd(cmd *execabs.Cmd) error {
return backoff.RetryNotify(backoffOps, newBackoff(daemonBackoffMaxRetries), backoffLog)
}
// WriteNetrc writes the netrc file.
func WriteNetrc(path, machine, login, password string) error {
netrcPath := filepath.Join(path, ".netrc")
netrcContent := fmt.Sprintf(netrcFile, machine, login, password)
if err := os.WriteFile(netrcPath, []byte(netrcContent), strictFilePerm); err != nil {
return fmt.Errorf("failed to create .netrc file: %w", err)
}
return nil
}