Switch remote deploy to vendored source builds

Move remote deployment to a vendored source bundle built on the target host via Docker so redeploys no longer require local cross-compilation or host Go installation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
GitHub Actions
2026-05-08 12:19:18 +08:00
parent bb27566e38
commit c1a0fe2949
1320 changed files with 497125 additions and 11 deletions

17
vendor/github.com/leaanthony/gosod/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,17 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
generated
examples/ignore/ignore
examples/basic/basic
examples/filters/filters

21
vendor/github.com/leaanthony/gosod/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Lea Anthony
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.

105
vendor/github.com/leaanthony/gosod/README.md generated vendored Normal file
View File

@@ -0,0 +1,105 @@
<p align="center" style="text-align: center">
<img src="logo.png" width="50%"><br/>
</p>
<p align="center">
Scaffolding simplified<br/><br/>
<a href="https://github.com/leaanthony/gosod/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg"></a>
<a href="https://goreportcard.com/report/github.com/leaanthony/gosod"><img src="https://goreportcard.com/badge/github.com/leaanthony/gosod"/></a>
<a href="https://godoc.org/github.com/leaanthony/gosod"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
<a href="https://github.com/leaanthony/gosod/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fleaanthony%2Fgosod?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fleaanthony%2Fgosod.svg?type=shield"/></a>
</p>
Features:
- Scaffold out project directories from templates
- Uses Go's native templating engine
- Uses `fs.FS` for input, so it works well with `go:embed` and [debme](https://github.com/leaanthony/debme)
- Go alternative to [cookiecutter](https://github.com/cookiecutter/cookiecutter)
## Installation
`go get github.com/leaanthony/gosod`
## Usage
1. Define a template directory
2. Define some data
3. Extract to a target directory
```go
package main
import (
"log"
"github.com/leaanthony/gosod"
)
type config struct {
Name string
}
// mytemplate/
// ├── custom.filtername.txt
// ├── ignored.txt
// ├── subdir
// │ ├── included.txt
// │ └── sub.tmpl.go
// └── test.tmpl.go
//go:embed mytemplate/*
var mytemplate embed.FS
func main() {
// Define a new Template directory
basic, err := gosod.New(mytemplate)
if err != nil {
log.Fatal(err)
}
// Make some config data
myConfig := &config{
Name: "Mat",
}
// Ignore files
basic.IgnoreFile("ignored.txt")
// Custom template filters
basic.SetTemplateFilters([]string{ ".filtername", ".tmpl" })
// Create a new directory using the template and config
err = basic.Extract("./generated", myConfig)
if err != nil {
log.Fatal(err)
}
// Ouput FS:
// generated/
// ├── custom.txt
// ├── subdir
// │ ├── included.txt
// │ └── sub.go
// └── test.go
}
```
## Template Directories
A template directory is simply a directory structure contianing files you wish to copy. The algorithm for copying is:
* Categorise all files into one of: directory, standard file and template files
* Create the directory structure
* Copy standard files
* Copy template files, assembled using the given data
Template files, by default, are any file with ".tmpl" in their filename. To change this, use `SetTemplateFilters([]string)`. This allows you to set any number of filters.
Files may also be ignored by using the `IgnoreFilename(string)` method.
## What's with the name?
Google is your [friend](https://translate.google.com/?sl=cy&tl=en&text=gosod&op=translate)

11
vendor/github.com/leaanthony/gosod/gosod.go generated vendored Normal file
View File

@@ -0,0 +1,11 @@
package gosod
import (
"github.com/leaanthony/gosod/internal/templatedir"
"io/fs"
)
// New creates a new TemplateDir structure for the given filesystem
func New(fs fs.FS) *templatedir.TemplateDir {
return templatedir.New(fs)
}

View File

@@ -0,0 +1,287 @@
package templatedir
import (
"bytes"
"io"
"io/fs"
"log"
"os"
"path/filepath"
"strings"
"syscall"
"text/template"
)
// TemplateDir defines a directory containing directories and files, including template files
type TemplateDir struct {
fs fs.FS
templateFilters []string
dirs []string
standardFiles []string
templateFiles []string
ignoredFiles map[string]struct{}
renameFiles map[string]string
}
// New attempts to create a new TemplateDir from the given FS
func New(fs fs.FS) *TemplateDir {
return &TemplateDir{
fs: fs,
templateFilters: []string{".tmpl"},
ignoredFiles: make(map[string]struct{}),
renameFiles: make(map[string]string),
}
}
// IgnoreFile will add the given filename to the list of files to ignore
// during extraction
func (t *TemplateDir) IgnoreFile(filename string) {
t.ignoredFiles[filename] = struct{}{}
}
// SetTemplateFilters sets the template filter. Each filename is checked to see if
// it contains this string and if so, it is deemed to be a template file
func (t *TemplateDir) SetTemplateFilters(filters []string) {
t.templateFilters = filters
}
func (t *TemplateDir) RenameFiles(renameFiles map[string]string) {
t.renameFiles = renameFiles
}
// Extract the templates to the given directory, using data as input
func (t *TemplateDir) Extract(targetDirectory string, data interface{}) error {
// Get the absolute path
targetDirectory, err := filepath.Abs(targetDirectory)
if err != nil {
return err
}
// If the targetDirectory doesn't exist, then create it
if _, err := os.Stat(targetDirectory); os.IsNotExist(err) == true {
// Create the targetDirectory
err = os.MkdirAll(targetDirectory, 0755)
if err != nil {
return err
}
}
// Process the template files
err = t.processTemplateDirFiles(targetDirectory, data)
if err != nil {
return err
}
return nil
}
func (t *TemplateDir) processTemplateDirFiles(targetDirectory string, data interface{}) error {
// Categorise all files
err := t.categoriseFiles()
if err != nil {
return err
}
// Create all directories
err = t.createDirectories(targetDirectory, data)
if err != nil {
return err
}
// Process TemplateDirs
err = t.processTemplateDirs(targetDirectory, data)
if err != nil {
return err
}
// Copy files
err = t.copyFiles(targetDirectory, data)
if err != nil {
return err
}
return nil
}
func (t *TemplateDir) categoriseFiles() error {
return fs.WalkDir(t.fs, ".", t.categoriseFile)
}
func (t *TemplateDir) categoriseFile(path string, info fs.DirEntry, err error) error {
// Process error
if err != nil {
return err
}
// Is it a directory?
if info.IsDir() {
// Ignore base dir
if path != "." {
t.dirs = append(t.dirs, path)
}
return nil
}
// Get the filename
filename := filepath.Base(path)
// Is it a file we are ignoring?
_, ignored := t.ignoredFiles[filename]
if ignored {
return nil
}
// Is it a template?
for _, filter := range t.templateFilters {
if strings.Index(filename, filter) > -1 {
t.templateFiles = append(t.templateFiles, path)
return nil
}
}
// Treat as standard file
t.standardFiles = append(t.standardFiles, path)
return nil
}
func (t *TemplateDir) convertPathTarget(path string, targetDirectory string, data any) string {
result := filepath.Join(targetDirectory, path)
if data == nil {
return result
}
// Load the filename as a template
tmpl, err := template.New("filename").Parse(result)
if err != nil {
return result
}
// Execute the template
var buf bytes.Buffer
err = tmpl.Execute(&buf, data)
if err != nil {
return result
}
// Return the result
return buf.String()
}
func (t *TemplateDir) createDirectories(targetDirectory string, data any) error {
// Iterate all directories and attempt to create them
for _, dirPath := range t.dirs {
targetDir := t.convertPathTarget(dirPath, targetDirectory, data)
// Create the directory
err := os.MkdirAll(targetDir, 0755)
// Ignore directory exists errors
if err != nil && err != syscall.EEXIST {
return err
}
}
return nil
}
func (t *TemplateDir) processTemplateDirs(targetDirectory string, data interface{}) error {
// Iterate template files
for _, templateFile := range t.templateFiles {
// Parse template
tmpl, err := template.ParseFS(t.fs, templateFile)
if err != nil {
return err
}
// Convert path to target path
targetFile := t.convertPathTarget(templateFile, targetDirectory, data)
// update filename
baseDir := filepath.Dir(targetFile)
filename := filepath.Base(targetFile)
for _, filter := range t.templateFilters {
filename = strings.ReplaceAll(filename, filter, "")
}
renamedFile := t.renameFiles[filename]
if renamedFile != "" {
filename = renamedFile
}
targetFile = filepath.Join(baseDir, filename)
// Create target file
writer, err := os.Create(targetFile)
if err != nil {
return err
}
err = tmpl.Execute(writer, data)
if err != nil {
err2 := writer.Close()
if err2 != nil {
return err2
}
return err
}
err = writer.Close()
if err != nil {
return err
}
}
return nil
}
func (t *TemplateDir) copyFiles(targetDirectory string, data any) error {
// Iterate over files
for _, filename := range t.standardFiles {
targetFile := filename
renamedFile := t.renameFiles[filename]
if renamedFile != "" {
targetFile = renamedFile
}
targetFilename := t.convertPathTarget(targetFile, targetDirectory, data)
err := t.copyFile(filename, targetFilename)
if err != nil {
return err
}
}
return nil
}
func (t *TemplateDir) copyFile(source, target string) error {
s, err := t.fs.Open(source)
if err != nil {
return err
}
defer func(s fs.File) {
err := s.Close()
if err != nil {
log.Fatal(err)
}
}(s)
d, err := os.Create(target)
if err != nil {
return err
}
if _, err := io.Copy(d, s); err != nil {
err := d.Close()
if err != nil {
return err
}
return err
}
return d.Close()
}

BIN
vendor/github.com/leaanthony/gosod/logo.png generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB