2022-01-20 14:59:39 -03:00
|
|
|
package aur
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"bytes"
|
2024-03-19 23:53:08 -03:00
|
|
|
"crypto/sha256"
|
2022-01-20 14:59:39 -03:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2023-12-17 14:52:09 -03:00
|
|
|
"path"
|
2022-01-20 14:59:39 -03:00
|
|
|
"path/filepath"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"text/template"
|
|
|
|
|
2022-06-21 21:11:15 -03:00
|
|
|
"github.com/caarlos0/log"
|
2024-05-26 15:02:57 -03:00
|
|
|
"github.com/goreleaser/goreleaser/v2/internal/artifact"
|
|
|
|
"github.com/goreleaser/goreleaser/v2/internal/client"
|
|
|
|
"github.com/goreleaser/goreleaser/v2/internal/commitauthor"
|
|
|
|
"github.com/goreleaser/goreleaser/v2/internal/pipe"
|
|
|
|
"github.com/goreleaser/goreleaser/v2/internal/skips"
|
|
|
|
"github.com/goreleaser/goreleaser/v2/internal/tmpl"
|
|
|
|
"github.com/goreleaser/goreleaser/v2/pkg/config"
|
|
|
|
"github.com/goreleaser/goreleaser/v2/pkg/context"
|
2022-01-20 14:59:39 -03:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2023-04-30 10:18:13 -03:00
|
|
|
aurExtra = "AURConfig"
|
|
|
|
defaultCommitMsg = "Update to {{ .Tag }}"
|
2022-01-20 14:59:39 -03:00
|
|
|
)
|
|
|
|
|
|
|
|
var ErrNoArchivesFound = errors.New("no linux archives found")
|
|
|
|
|
|
|
|
// Pipe for arch linux's AUR pkgbuild.
|
|
|
|
type Pipe struct{}
|
|
|
|
|
2023-11-03 23:30:48 +00:00
|
|
|
func (Pipe) String() string { return "arch user repositories" }
|
|
|
|
func (Pipe) ContinueOnError() bool { return true }
|
|
|
|
func (Pipe) Skip(ctx *context.Context) bool {
|
|
|
|
return skips.Any(ctx, skips.AUR) || len(ctx.Config.AURs) == 0
|
|
|
|
}
|
2022-01-20 14:59:39 -03:00
|
|
|
|
|
|
|
func (Pipe) Default(ctx *context.Context) error {
|
|
|
|
for i := range ctx.Config.AURs {
|
|
|
|
pkg := &ctx.Config.AURs[i]
|
|
|
|
|
|
|
|
pkg.CommitAuthor = commitauthor.Default(pkg.CommitAuthor)
|
|
|
|
if pkg.CommitMessageTemplate == "" {
|
|
|
|
pkg.CommitMessageTemplate = defaultCommitMsg
|
|
|
|
}
|
|
|
|
if pkg.Name == "" {
|
|
|
|
pkg.Name = ctx.Config.ProjectName
|
|
|
|
}
|
|
|
|
if !strings.HasSuffix(pkg.Name, "-bin") {
|
|
|
|
pkg.Name += "-bin"
|
|
|
|
}
|
|
|
|
if len(pkg.Conflicts) == 0 {
|
|
|
|
pkg.Conflicts = []string{ctx.Config.ProjectName}
|
|
|
|
}
|
|
|
|
if len(pkg.Provides) == 0 {
|
|
|
|
pkg.Provides = []string{ctx.Config.ProjectName}
|
|
|
|
}
|
|
|
|
if pkg.Rel == "" {
|
|
|
|
pkg.Rel = "1"
|
|
|
|
}
|
2022-04-11 22:43:22 -03:00
|
|
|
if pkg.Goamd64 == "" {
|
2022-04-13 21:29:39 -03:00
|
|
|
pkg.Goamd64 = "v1"
|
2022-04-11 22:43:22 -03:00
|
|
|
}
|
2022-01-20 14:59:39 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (Pipe) Run(ctx *context.Context) error {
|
feat: allow goreleaser to run in gerrit, soft-serve and others (#4271)
Currently, GoReleaser will assume you're running against github, gitea
or gitlab.
You could set `release.disable: true`, but it would still set and try to
use some defaults that could break things up.
Now, if you disable the release, goreleaser will not set these defaults.
It'll also hard error in some cases in which it would happily produce
invalid resources before, namely, if `release.disable` is set, and, for
example, `brews.url_template` is empty (in which case it would try to
use the one from the release, usually github).
closes #4208
2023-09-04 11:23:38 -03:00
|
|
|
cli, err := client.NewReleaseClient(ctx)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return runAll(ctx, cli)
|
|
|
|
}
|
|
|
|
|
feat: allow goreleaser to run in gerrit, soft-serve and others (#4271)
Currently, GoReleaser will assume you're running against github, gitea
or gitlab.
You could set `release.disable: true`, but it would still set and try to
use some defaults that could break things up.
Now, if you disable the release, goreleaser will not set these defaults.
It'll also hard error in some cases in which it would happily produce
invalid resources before, namely, if `release.disable` is set, and, for
example, `brews.url_template` is empty (in which case it would try to
use the one from the release, usually github).
closes #4208
2023-09-04 11:23:38 -03:00
|
|
|
func runAll(ctx *context.Context, cli client.ReleaseURLTemplater) error {
|
2022-02-04 14:45:02 -03:00
|
|
|
for _, aur := range ctx.Config.AURs {
|
|
|
|
err := doRun(ctx, aur, cli)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
feat: allow goreleaser to run in gerrit, soft-serve and others (#4271)
Currently, GoReleaser will assume you're running against github, gitea
or gitlab.
You could set `release.disable: true`, but it would still set and try to
use some defaults that could break things up.
Now, if you disable the release, goreleaser will not set these defaults.
It'll also hard error in some cases in which it would happily produce
invalid resources before, namely, if `release.disable` is set, and, for
example, `brews.url_template` is empty (in which case it would try to
use the one from the release, usually github).
closes #4208
2023-09-04 11:23:38 -03:00
|
|
|
func doRun(ctx *context.Context, aur config.AUR, cl client.ReleaseURLTemplater) error {
|
2023-12-17 14:52:09 -03:00
|
|
|
if err := tmpl.New(ctx).ApplyAll(
|
|
|
|
&aur.Name,
|
|
|
|
&aur.Directory,
|
|
|
|
); err != nil {
|
2022-01-20 14:59:39 -03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
filters := []artifact.Filter{
|
|
|
|
artifact.ByGoos("linux"),
|
|
|
|
artifact.Or(
|
2022-04-11 22:43:22 -03:00
|
|
|
artifact.And(
|
|
|
|
artifact.ByGoarch("amd64"),
|
|
|
|
artifact.ByGoamd64(aur.Goamd64),
|
|
|
|
),
|
2022-01-20 14:59:39 -03:00
|
|
|
artifact.ByGoarch("arm64"),
|
|
|
|
artifact.ByGoarch("386"),
|
|
|
|
artifact.And(
|
|
|
|
artifact.ByGoarch("arm"),
|
|
|
|
artifact.Or(
|
|
|
|
artifact.ByGoarm("7"),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
artifact.Or(
|
|
|
|
artifact.ByType(artifact.UploadableArchive),
|
|
|
|
artifact.ByType(artifact.UploadableBinary),
|
|
|
|
),
|
|
|
|
}
|
2022-02-04 14:45:02 -03:00
|
|
|
if len(aur.IDs) > 0 {
|
|
|
|
filters = append(filters, artifact.ByIDs(aur.IDs...))
|
2022-01-20 14:59:39 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
archives := ctx.Artifacts.Filter(artifact.And(filters...)).List()
|
|
|
|
if len(archives) == 0 {
|
|
|
|
return ErrNoArchivesFound
|
|
|
|
}
|
|
|
|
|
2022-02-04 14:45:02 -03:00
|
|
|
pkg, err := tmpl.New(ctx).Apply(aur.Package)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if strings.TrimSpace(pkg) == "" {
|
|
|
|
art := archives[0]
|
|
|
|
switch art.Type {
|
|
|
|
case artifact.UploadableBinary:
|
|
|
|
name := art.Name
|
2022-06-23 23:36:19 -03:00
|
|
|
bin := artifact.ExtraOr(*art, artifact.ExtraBinary, art.Name)
|
2022-01-20 14:59:39 -03:00
|
|
|
pkg = fmt.Sprintf(`install -Dm755 "./%s "${pkgdir}/usr/bin/%s"`, name, bin)
|
|
|
|
case artifact.UploadableArchive:
|
2023-12-26 08:37:28 -03:00
|
|
|
folder := artifact.ExtraOr(*art, artifact.ExtraWrappedIn, ".")
|
2022-06-23 23:36:19 -03:00
|
|
|
for _, bin := range artifact.ExtraOr(*art, artifact.ExtraBinaries, []string{}) {
|
2023-12-26 08:37:28 -03:00
|
|
|
path := filepath.ToSlash(filepath.Clean(filepath.Join(folder, bin)))
|
|
|
|
pkg = fmt.Sprintf(`install -Dm755 "./%s" "${pkgdir}/usr/bin/%s"`, path, bin)
|
2022-01-20 14:59:39 -03:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Warnf("guessing package to be %q", pkg)
|
|
|
|
}
|
2022-02-04 14:45:02 -03:00
|
|
|
aur.Package = pkg
|
2022-01-20 14:59:39 -03:00
|
|
|
|
|
|
|
for _, info := range []struct {
|
|
|
|
name, tpl, ext string
|
|
|
|
kind artifact.Type
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "PKGBUILD",
|
2022-02-04 14:45:02 -03:00
|
|
|
tpl: aurTemplateData,
|
2022-01-20 14:59:39 -03:00
|
|
|
ext: ".pkgbuild",
|
|
|
|
kind: artifact.PkgBuild,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: ".SRCINFO",
|
|
|
|
tpl: srcInfoTemplate,
|
|
|
|
ext: ".srcinfo",
|
|
|
|
kind: artifact.SrcInfo,
|
|
|
|
},
|
|
|
|
} {
|
2022-02-04 14:45:02 -03:00
|
|
|
pkgContent, err := buildPkgFile(ctx, aur, cl, archives, info.tpl)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-02-04 14:45:02 -03:00
|
|
|
path := filepath.Join(ctx.Config.Dist, "aur", aur.Name+info.ext)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
|
|
return fmt.Errorf("failed to write %s: %w", info.kind, err)
|
|
|
|
}
|
|
|
|
log.WithField("file", path).Info("writing")
|
|
|
|
if err := os.WriteFile(path, []byte(pkgContent), 0o644); err != nil { //nolint: gosec
|
|
|
|
return fmt.Errorf("failed to write %s: %w", info.kind, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.Artifacts.Add(&artifact.Artifact{
|
|
|
|
Name: info.name,
|
|
|
|
Path: path,
|
|
|
|
Type: info.kind,
|
|
|
|
Extra: map[string]interface{}{
|
2022-02-04 14:45:02 -03:00
|
|
|
aurExtra: aur,
|
|
|
|
artifact.ExtraID: aur.Name,
|
2022-01-20 14:59:39 -03:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
feat: allow goreleaser to run in gerrit, soft-serve and others (#4271)
Currently, GoReleaser will assume you're running against github, gitea
or gitlab.
You could set `release.disable: true`, but it would still set and try to
use some defaults that could break things up.
Now, if you disable the release, goreleaser will not set these defaults.
It'll also hard error in some cases in which it would happily produce
invalid resources before, namely, if `release.disable` is set, and, for
example, `brews.url_template` is empty (in which case it would try to
use the one from the release, usually github).
closes #4208
2023-09-04 11:23:38 -03:00
|
|
|
func buildPkgFile(ctx *context.Context, pkg config.AUR, client client.ReleaseURLTemplater, artifacts []*artifact.Artifact, tpl string) (string, error) {
|
2022-01-20 14:59:39 -03:00
|
|
|
data, err := dataFor(ctx, pkg, client, artifacts)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return applyTemplate(ctx, tpl, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fixLines(s string) string {
|
|
|
|
lines := strings.Split(s, "\n")
|
|
|
|
var result []string
|
|
|
|
for _, line := range lines {
|
|
|
|
l := strings.TrimSpace(line)
|
|
|
|
if l == "" {
|
|
|
|
result = append(result, "")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
result = append(result, " "+l)
|
|
|
|
}
|
|
|
|
return strings.Join(result, "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func applyTemplate(ctx *context.Context, tpl string, data templateData) (string, error) {
|
|
|
|
t := template.Must(
|
|
|
|
template.New(data.Name).
|
|
|
|
Funcs(template.FuncMap{
|
|
|
|
"fixLines": fixLines,
|
|
|
|
"pkgArray": toPkgBuildArray,
|
|
|
|
}).
|
|
|
|
Parse(tpl),
|
|
|
|
)
|
|
|
|
|
|
|
|
var out bytes.Buffer
|
|
|
|
if err := t.Execute(&out, data); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
content, err := tmpl.New(ctx).Apply(out.String())
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
out.Reset()
|
|
|
|
|
|
|
|
// Sanitize the template output and get rid of trailing whitespace.
|
|
|
|
var (
|
|
|
|
r = strings.NewReader(content)
|
|
|
|
s = bufio.NewScanner(r)
|
|
|
|
)
|
|
|
|
for s.Scan() {
|
|
|
|
l := strings.TrimRight(s.Text(), " ")
|
|
|
|
_, _ = out.WriteString(l)
|
|
|
|
_ = out.WriteByte('\n')
|
|
|
|
}
|
|
|
|
if err := s.Err(); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return out.String(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func toPkgBuildArray(ss []string) string {
|
|
|
|
result := make([]string, 0, len(ss))
|
|
|
|
for _, s := range ss {
|
|
|
|
result = append(result, fmt.Sprintf("'%s'", s))
|
|
|
|
}
|
|
|
|
return strings.Join(result, " ")
|
|
|
|
}
|
|
|
|
|
|
|
|
func toPkgBuildArch(arch string) string {
|
|
|
|
switch arch {
|
|
|
|
case "amd64":
|
|
|
|
return "x86_64"
|
|
|
|
case "386":
|
|
|
|
return "i686"
|
|
|
|
case "arm64":
|
|
|
|
return "aarch64"
|
|
|
|
case "arm6":
|
|
|
|
return "armv6h"
|
|
|
|
case "arm7":
|
|
|
|
return "armv7h"
|
|
|
|
default:
|
|
|
|
return "invalid" // should never get here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
feat: allow goreleaser to run in gerrit, soft-serve and others (#4271)
Currently, GoReleaser will assume you're running against github, gitea
or gitlab.
You could set `release.disable: true`, but it would still set and try to
use some defaults that could break things up.
Now, if you disable the release, goreleaser will not set these defaults.
It'll also hard error in some cases in which it would happily produce
invalid resources before, namely, if `release.disable` is set, and, for
example, `brews.url_template` is empty (in which case it would try to
use the one from the release, usually github).
closes #4208
2023-09-04 11:23:38 -03:00
|
|
|
func dataFor(ctx *context.Context, cfg config.AUR, cl client.ReleaseURLTemplater, artifacts []*artifact.Artifact) (templateData, error) {
|
2022-01-20 14:59:39 -03:00
|
|
|
result := templateData{
|
|
|
|
Name: cfg.Name,
|
|
|
|
Desc: cfg.Description,
|
|
|
|
Homepage: cfg.Homepage,
|
2022-01-27 00:23:37 -03:00
|
|
|
Version: fmt.Sprintf("%d.%d.%d", ctx.Semver.Major, ctx.Semver.Minor, ctx.Semver.Patch),
|
2022-01-20 14:59:39 -03:00
|
|
|
License: cfg.License,
|
|
|
|
Rel: cfg.Rel,
|
|
|
|
Maintainers: cfg.Maintainers,
|
|
|
|
Contributors: cfg.Contributors,
|
|
|
|
Provides: cfg.Provides,
|
|
|
|
Conflicts: cfg.Conflicts,
|
2022-10-05 09:42:17 -03:00
|
|
|
Backup: cfg.Backup,
|
2022-01-20 14:59:39 -03:00
|
|
|
Depends: cfg.Depends,
|
|
|
|
OptDepends: cfg.OptDepends,
|
|
|
|
Package: cfg.Package,
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, art := range artifacts {
|
|
|
|
sum, err := art.Checksum("sha256")
|
|
|
|
if err != nil {
|
|
|
|
return result, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg.URLTemplate == "" {
|
|
|
|
url, err := cl.ReleaseURLTemplate(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return result, err
|
|
|
|
}
|
|
|
|
cfg.URLTemplate = url
|
|
|
|
}
|
2022-11-25 15:26:14 -03:00
|
|
|
url, err := tmpl.New(ctx).WithArtifact(art).Apply(cfg.URLTemplate)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err != nil {
|
|
|
|
return result, err
|
|
|
|
}
|
|
|
|
|
|
|
|
releasePackage := releasePackage{
|
|
|
|
DownloadURL: url,
|
|
|
|
SHA256: sum,
|
|
|
|
Arch: toPkgBuildArch(art.Goarch + art.Goarm),
|
2022-06-23 23:36:19 -03:00
|
|
|
Format: artifact.ExtraOr(*art, artifact.ExtraFormat, ""),
|
2022-01-20 14:59:39 -03:00
|
|
|
}
|
|
|
|
result.ReleasePackages = append(result.ReleasePackages, releasePackage)
|
|
|
|
result.Arches = append(result.Arches, releasePackage.Arch)
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(result.Arches)
|
|
|
|
sort.Slice(result.ReleasePackages, func(i, j int) bool {
|
|
|
|
return result.ReleasePackages[i].Arch < result.ReleasePackages[j].Arch
|
|
|
|
})
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Publish the PKGBUILD and .SRCINFO files to the AUR repository.
|
|
|
|
func (Pipe) Publish(ctx *context.Context) error {
|
|
|
|
skips := pipe.SkipMemento{}
|
|
|
|
for _, pkgs := range ctx.Artifacts.Filter(
|
|
|
|
artifact.Or(
|
|
|
|
artifact.ByType(artifact.PkgBuild),
|
|
|
|
artifact.ByType(artifact.SrcInfo),
|
|
|
|
),
|
|
|
|
).GroupByID() {
|
|
|
|
err := doPublish(ctx, pkgs)
|
|
|
|
if err != nil && pipe.IsSkip(err) {
|
|
|
|
skips.Remember(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return skips.Evaluate()
|
|
|
|
}
|
|
|
|
|
|
|
|
func doPublish(ctx *context.Context, pkgs []*artifact.Artifact) error {
|
2022-06-23 23:36:19 -03:00
|
|
|
cfg, err := artifact.Extra[config.AUR](*pkgs[0], aurExtra)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-01-20 14:59:39 -03:00
|
|
|
|
|
|
|
if strings.TrimSpace(cfg.SkipUpload) == "true" {
|
2022-02-04 14:45:02 -03:00
|
|
|
return pipe.Skip("aur.skip_upload is set")
|
2022-01-20 14:59:39 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if strings.TrimSpace(cfg.SkipUpload) == "auto" && ctx.Semver.Prerelease != "" {
|
|
|
|
return pipe.Skip("prerelease detected with 'auto' upload, skipping aur publish")
|
|
|
|
}
|
|
|
|
|
2023-04-30 10:18:13 -03:00
|
|
|
author, err := commitauthor.Get(ctx, cfg.CommitAuthor)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
msg, err := tmpl.New(ctx).Apply(cfg.CommitMessageTemplate)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-04-30 10:18:13 -03:00
|
|
|
cli := client.NewGitUploadClient("master")
|
|
|
|
repo := client.RepoFromRef(config.RepoRef{
|
|
|
|
Git: config.GitRepoRef{
|
|
|
|
PrivateKey: cfg.PrivateKey,
|
|
|
|
URL: cfg.GitURL,
|
|
|
|
SSHCommand: cfg.GitSSHCommand,
|
|
|
|
},
|
2024-03-19 23:53:08 -03:00
|
|
|
Name: fmt.Sprintf("%x", sha256.Sum256([]byte(cfg.GitURL))),
|
2023-04-30 10:18:13 -03:00
|
|
|
})
|
2022-01-20 14:59:39 -03:00
|
|
|
|
2023-06-19 14:03:22 -03:00
|
|
|
files := make([]client.RepoFile, 0, len(pkgs))
|
2022-01-20 14:59:39 -03:00
|
|
|
for _, pkg := range pkgs {
|
2023-04-30 10:18:13 -03:00
|
|
|
content, err := os.ReadFile(pkg.Path)
|
2022-01-20 14:59:39 -03:00
|
|
|
if err != nil {
|
2023-04-30 10:18:13 -03:00
|
|
|
return err
|
2022-01-20 14:59:39 -03:00
|
|
|
}
|
2023-06-19 14:03:22 -03:00
|
|
|
files = append(files, client.RepoFile{
|
2023-12-17 14:52:09 -03:00
|
|
|
Path: path.Join(cfg.Directory, pkg.Name),
|
2023-06-19 14:03:22 -03:00
|
|
|
Content: content,
|
|
|
|
})
|
2022-01-20 14:59:39 -03:00
|
|
|
}
|
2023-06-19 14:03:22 -03:00
|
|
|
return cli.CreateFiles(ctx, author, repo, msg, files)
|
2022-01-20 14:59:39 -03:00
|
|
|
}
|