release-v1
This commit is contained in:
commit
a5d76d8d5a
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@ -0,0 +1,11 @@
|
||||
# Debian GNU/Linux 10 (1.13.10-buster)
|
||||
FROM golang:1.13.10-buster
|
||||
|
||||
# copy entrypoint file
|
||||
COPY entrypoint.go /usr/bin/entrypoint.go
|
||||
|
||||
# change mode of the entrypoint file
|
||||
RUN chmod +x /usr/bin/entrypoint.go
|
||||
|
||||
# set entrypoint command
|
||||
ENTRYPOINT [ "go", "run", "/usr/bin/entrypoint.go" ]
|
49
README.md
Normal file
49
README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# GitHub Action: go-build-action
|
||||
This actions generates cross-platform executable files from a Go module.
|
||||
|
||||
![release](/assets/release.png)
|
||||
|
||||
# Workflow setup
|
||||
|
||||
```yaml
|
||||
# workflow name
|
||||
name: Generate release-artifacts
|
||||
|
||||
# on events
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
# workflow tasks
|
||||
jobs:
|
||||
generate:
|
||||
name: Generate cross-platform builds
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Generate build files
|
||||
uses: thatisuday/go-cross-build@v1
|
||||
with:
|
||||
platforms: 'linux/amd64, darwin/amd64, windows/amd64'
|
||||
package: 'demo'
|
||||
name: 'program'
|
||||
compress: 'true'
|
||||
dest: 'dist'
|
||||
```
|
||||
|
||||
### option: **platforms**
|
||||
The `platforms` option specifies comma-separated platform names to create binary-executable files for. To see the list of supported platforms, use `go tool dist list` command.
|
||||
|
||||
### option: **package**
|
||||
If the module (_repository_) itself is a Go package, then `package` option value should be an empty string (''). If the repository contains a package directory, then `package` value should be the directory name.
|
||||
|
||||
### option: **compress**
|
||||
The `compress` option if set to `'true'` will generate **compressed-tar** archive files for the each platform-build file. The resulting archive file also contains `README.md` and `LICENSE` file if they exist inside the root of the repository. In this mode, the binary executable file name is taken from the `name` option value.
|
||||
|
||||
### option: **name**
|
||||
The `name` option sets a prefix for the build filenames. In compression mode, this prefix is applied to archive files and binary executable filename is set to this value.
|
||||
|
||||
### option: **dest**
|
||||
The `dest` option sets the output directory for the build files. This should be a relative directory without leading `./`.
|
43
action.yml
Normal file
43
action.yml
Normal file
@ -0,0 +1,43 @@
|
||||
# action name
|
||||
name: 'go-cross-build'
|
||||
|
||||
# action author
|
||||
author: 'Uday Hiwarale <thatisuday@gmail.com>'
|
||||
|
||||
# action description
|
||||
description: 'Generates cross-platform executable files from a Go module.'
|
||||
|
||||
# action input values
|
||||
inputs:
|
||||
platforms:
|
||||
description: 'Comma-separated list of "<kernel>/<arch>" combinations.'
|
||||
default: 'linux/386,linux/amd64'
|
||||
required: false
|
||||
package:
|
||||
description: 'Package (directory) in the module to build. By default, builds the module directory.'
|
||||
default: ''
|
||||
required: false
|
||||
compress:
|
||||
description: 'Compress each build file inside a ".tar.gz" archive.'
|
||||
default: 'false'
|
||||
required: false
|
||||
name:
|
||||
description: 'Binary executable filename and filenames prefix for the build files.'
|
||||
default: 'program'
|
||||
required: false
|
||||
dest:
|
||||
description: 'Destination directory inside workspace to output build-artifacts.'
|
||||
default: 'build'
|
||||
required: false
|
||||
|
||||
# action runner (golang:latest image)
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
env:
|
||||
GO111MODULE: 'on'
|
||||
|
||||
# branding
|
||||
branding:
|
||||
icon: terminal
|
||||
color: green
|
BIN
assets/release.png
Normal file
BIN
assets/release.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
215
entrypoint.go
Normal file
215
entrypoint.go
Normal file
@ -0,0 +1,215 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/*************************************/
|
||||
|
||||
// check if file exists (relative to the current directory)
|
||||
func fileExists(path string) bool {
|
||||
|
||||
// get current directory
|
||||
cwd, _ := os.Getwd()
|
||||
|
||||
// get an absolute path of the file
|
||||
absPath := filepath.Join(cwd, path)
|
||||
|
||||
// access file information
|
||||
if _, err := os.Stat(absPath); err != nil {
|
||||
return !os.IsNotExist(err) // return `false` if doesn't exist
|
||||
}
|
||||
|
||||
// file exists
|
||||
return true
|
||||
}
|
||||
|
||||
// copy file using `cp` command
|
||||
func copyFile(src, dest string) {
|
||||
if err := exec.Command("cp", src, dest).Run(); err != nil {
|
||||
fmt.Println("An error occurred during copy operation:", src, "=>", dest)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
|
||||
// build the package for a platform
|
||||
func build(packageName, destDir string, platform map[string]string, compress bool) {
|
||||
|
||||
// platform config
|
||||
platformKernel := platform["kernel"]
|
||||
platformArch := platform["arch"]
|
||||
|
||||
// binary executable file path
|
||||
inputName := os.Getenv("INPUT_NAME")
|
||||
|
||||
// build file name (same as the `inputName` if compression is enabled)
|
||||
buildFileName := fmt.Sprintf("%s-%s-%s", inputName, platformKernel, platformArch)
|
||||
if compress {
|
||||
buildFileName = inputName
|
||||
}
|
||||
|
||||
// append `.exe` file-extension for windows
|
||||
if platformKernel == "windows" {
|
||||
buildFileName += ".exe"
|
||||
}
|
||||
|
||||
// workspace directory
|
||||
workspaceDir := os.Getenv("GITHUB_WORKSPACE")
|
||||
|
||||
// destination directory path
|
||||
destDirPath := filepath.Join(workspaceDir, destDir)
|
||||
|
||||
// join destination path
|
||||
buildFilePath := filepath.Join(destDirPath, buildFileName)
|
||||
|
||||
// package directory local path
|
||||
var packagePath string
|
||||
if packageName == "" {
|
||||
packagePath = "."
|
||||
} else {
|
||||
packagePath = "./" + packageName
|
||||
}
|
||||
|
||||
/*------------*/
|
||||
|
||||
// command-line options for the `go build` command
|
||||
buildOptions := []string{"build", "-buildmode", "exe", "-o", buildFilePath, packagePath}
|
||||
|
||||
// generate `go build` command
|
||||
buildCmd := exec.Command("go", buildOptions...)
|
||||
|
||||
// set environment variables
|
||||
buildCmd.Env = append(os.Environ(), []string{
|
||||
fmt.Sprintf("GOOS=%s", platformKernel),
|
||||
fmt.Sprintf("GOARCH=%s", platformArch),
|
||||
}...)
|
||||
|
||||
// execute `go build` command
|
||||
fmt.Println("Creating a build using :", buildCmd.String())
|
||||
if output, err := buildCmd.Output(); err != nil {
|
||||
fmt.Println("An error occurred during build:", err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
fmt.Printf("%s\n", output)
|
||||
}
|
||||
|
||||
/*------------------------------*/
|
||||
|
||||
// create a compressed `.tar.gz` file
|
||||
if compress {
|
||||
|
||||
// compressed gzip file name
|
||||
gzFileName := fmt.Sprintf("%s-%s-%s.tar.gz", inputName, platformKernel, platformArch)
|
||||
|
||||
/*------------*/
|
||||
|
||||
// file to compress (default: build file)
|
||||
includeFiles := []string{buildFileName}
|
||||
|
||||
// copy "README.md" file inside destination directory
|
||||
if fileExists("README.md") {
|
||||
copyFile("README.md", filepath.Join(destDirPath, "README.md"))
|
||||
includeFiles = append(includeFiles, "README.md")
|
||||
}
|
||||
|
||||
// copy "LICENSE" file inside destination directory
|
||||
if fileExists("LICENSE") {
|
||||
copyFile("LICENSE", filepath.Join(destDirPath, "LICENSE"))
|
||||
includeFiles = append(includeFiles, "LICENSE")
|
||||
}
|
||||
|
||||
/*------------*/
|
||||
|
||||
// command-line options for the `tar` command
|
||||
tarOptions := append([]string{"-cvzf", gzFileName}, includeFiles...)
|
||||
|
||||
// generate `tar` command
|
||||
tarCmd := exec.Command("tar", tarOptions...)
|
||||
|
||||
// set working directory for the command
|
||||
tarCmd.Dir = destDirPath
|
||||
|
||||
// execute `tar` command
|
||||
fmt.Println("Compressing build file using:", tarCmd.String())
|
||||
if err := tarCmd.Run(); err != nil {
|
||||
fmt.Println("An error occurred during compression:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
/*------------*/
|
||||
|
||||
// generate cleanup command
|
||||
cleanCmd := exec.Command("rm", append([]string{"-f"}, includeFiles...)...)
|
||||
|
||||
// set working directory for the command
|
||||
cleanCmd.Dir = destDirPath
|
||||
|
||||
// start cleanup process
|
||||
fmt.Println("Performing cleanup operation using:", cleanCmd.String())
|
||||
if err := cleanCmd.Run(); err != nil {
|
||||
fmt.Println("An error occurred during cleaup:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
|
||||
func main() {
|
||||
|
||||
// get input variables from action
|
||||
inputPlatforms := os.Getenv("INPUT_PLATFORMS")
|
||||
inputPackage := os.Getenv("INPUT_PACKAGE")
|
||||
inputCompress := os.Getenv("INPUT_COMPRESS")
|
||||
inputDest := os.Getenv("INPUT_DEST")
|
||||
|
||||
// package name to build
|
||||
packageName := strings.ReplaceAll(inputPackage, " ", "")
|
||||
|
||||
// destination directory
|
||||
destDir := strings.ReplaceAll(inputDest, " ", "")
|
||||
|
||||
// split platform names by comma (`,`)
|
||||
platforms := strings.Split(inputPlatforms, ",")
|
||||
|
||||
// should compress build file
|
||||
compress := false
|
||||
if strings.ToLower(inputCompress) == "true" {
|
||||
compress = true
|
||||
}
|
||||
|
||||
// for each platform, execute `build` function
|
||||
for _, platform := range platforms {
|
||||
|
||||
// split platform by `/` (and clean all whitespaces)
|
||||
platformSpec := strings.Split(strings.ReplaceAll(platform, " ", ""), "/")
|
||||
|
||||
// create a `map` of `kernel` and `arch`
|
||||
platformMap := map[string]string{
|
||||
"kernel": platformSpec[0],
|
||||
"arch": platformSpec[1],
|
||||
}
|
||||
|
||||
// execute `build` function
|
||||
build(packageName, destDir, platformMap, compress)
|
||||
}
|
||||
|
||||
/*------------*/
|
||||
|
||||
// list files inside destination directory
|
||||
if output, err := exec.Command("ls", "-alh", destDir).Output(); err != nil {
|
||||
fmt.Println("An error occurred during ls operation:", err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
fmt.Println("--- BUILD FILES ---")
|
||||
fmt.Printf("%s\n", output)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user