Compare commits
12 Commits
Author | SHA1 | Date |
---|---|---|
DataHearth | dd6eeb3041 | |
DataHearth | 68f263e245 | |
DataHearth | fe4ff05d5d | |
DataHearth | 8efdca8fe4 | |
DataHearth | f85fc9d39c | |
DataHearth | 8051912b35 | |
DataHearth | 224754870d | |
DataHearth | 0f1019774d | |
DataHearth | 42d2152f8e | |
DataHearth | 66f0fe3042 | |
DataHearth | 21c031d8fc | |
DataHearth | 6e5ede992a |
|
@ -2,7 +2,7 @@ style: github
|
|||
template: CHANGELOG.tpl.md
|
||||
info:
|
||||
title: CHANGELOG
|
||||
repository_url: https://github.com/DataHearth/config-mapper
|
||||
repository_url: https://gitea.antoine-langlois.net/DataHearth/config-mapper
|
||||
options:
|
||||
commits:
|
||||
filters:
|
||||
|
|
|
@ -29,8 +29,10 @@ folders:
|
|||
linux: "$LOCATION/macos/.config:~/.config"
|
||||
|
||||
package-managers:
|
||||
installation-order: ["homebrew"] # available: brew, pip (pip check also for pip3), cargo, apt, npm, go
|
||||
homebrew:
|
||||
# available: brew, pip (pip check also for pip3), cargo, apt, npm, go
|
||||
installation-order:
|
||||
- brew
|
||||
brew:
|
||||
- bat
|
||||
- hexyl
|
||||
- fd
|
||||
|
|
44
CHANGELOG.md
44
CHANGELOG.md
|
@ -3,8 +3,20 @@
|
|||
## [Unreleased]
|
||||
|
||||
|
||||
<a name="v0.6.0"></a>
|
||||
## [v0.6.0] - 2022-08-20
|
||||
### Bug Fixes
|
||||
- **configuration:** remove installation-order default value
|
||||
- **items:** fix stdout when no path is available
|
||||
- **pkgs:** update command building
|
||||
- **pkgs:** add pkg manager validation check and parsing cli arguments
|
||||
|
||||
### Features
|
||||
- **packages:** add nala package manager
|
||||
|
||||
|
||||
<a name="v0.5.0"></a>
|
||||
## [v0.5.0] - 2022-07-10
|
||||
## [v0.5.0] - 2022-08-01
|
||||
### Bug Fixes
|
||||
- **git:** use go-git for adding removed file (workaround)
|
||||
|
||||
|
@ -13,7 +25,7 @@
|
|||
|
||||
|
||||
<a name="v0.4.0"></a>
|
||||
## [v0.4.0] - 2022-06-16
|
||||
## [v0.4.0] - 2022-08-01
|
||||
### Bug Fixes
|
||||
- **config:** don't throw error when file not available on OS
|
||||
- **save:** remove folder before copy (avoid unwanted files)
|
||||
|
@ -24,17 +36,15 @@
|
|||
|
||||
|
||||
<a name="v0.3.0"></a>
|
||||
## [v0.3.0] - 2022-06-01
|
||||
## [v0.3.0] - 2022-08-01
|
||||
### Features
|
||||
- **cli:** packages are disabled by default
|
||||
- **sync:** add .ignore file to filter folder's content
|
||||
|
||||
|
||||
<a name="v0.2.0"></a>
|
||||
## [v0.2.0] - 2022-05-23
|
||||
## [v0.2.0] - 2022-08-01
|
||||
### Bug Fixes
|
||||
- **config:** fix config path check
|
||||
- **copy:** use io.Copy instead of custom copy
|
||||
- **git:** use git binary for "git add"
|
||||
- **git:** deleted files are not pushed
|
||||
- **git:** add error handling and repo URL from config
|
||||
|
@ -44,24 +54,15 @@
|
|||
### Code Refactoring
|
||||
- **archi:** reduce base code to one struct
|
||||
- **cli:** separate functions from CLI for lisibility
|
||||
- **config:** unmarshal configuration instead of raw read
|
||||
- **logging:** drop pterm
|
||||
|
||||
### Features
|
||||
- **cli:** add configuration-file persistant flag
|
||||
- **cli:** add git push option with message
|
||||
- **cli:** add save and load features
|
||||
- **cli:** add init sub-command
|
||||
- **cli:** add copy folder
|
||||
- **cli:** add save command
|
||||
- **cli:** implement pkgs installation
|
||||
- **config:** update git configuration
|
||||
- **config:** add yaml tags for yaml.v3
|
||||
- **index:** add indexing system
|
||||
|
||||
|
||||
<a name="v0.1.0"></a>
|
||||
## v0.1.0 - 2022-02-27
|
||||
## v0.1.0 - 2022-07-31
|
||||
### Bug Fixes
|
||||
- **config:** fix config path check
|
||||
- **copy:** use io.Copy instead of custom copy
|
||||
|
@ -80,8 +81,9 @@
|
|||
- **config:** add yaml tags for yaml.v3
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/DataHearth/config-mapper/compare/v0.5.0...HEAD
|
||||
[v0.5.0]: https://github.com/DataHearth/config-mapper/compare/v0.4.0...v0.5.0
|
||||
[v0.4.0]: https://github.com/DataHearth/config-mapper/compare/v0.3.0...v0.4.0
|
||||
[v0.3.0]: https://github.com/DataHearth/config-mapper/compare/v0.2.0...v0.3.0
|
||||
[v0.2.0]: https://github.com/DataHearth/config-mapper/compare/v0.1.0...v0.2.0
|
||||
[Unreleased]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.6.0...HEAD
|
||||
[v0.6.0]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.5.0...v0.6.0
|
||||
[v0.5.0]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.4.0...v0.5.0
|
||||
[v0.4.0]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.3.0...v0.4.0
|
||||
[v0.3.0]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.2.0...v0.3.0
|
||||
[v0.2.0]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.1.0...v0.2.0
|
||||
|
|
|
@ -24,7 +24,7 @@ var rootCmd = &cobra.Command{
|
|||
Short: "Manage your systems configuration",
|
||||
Long: `config-mapper aims to help you manage your configurations between systems
|
||||
with a single configuration file.`,
|
||||
Version: "v0.5.0",
|
||||
Version: "v0.6.0",
|
||||
}
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
|
@ -69,9 +69,11 @@ func init() {
|
|||
loadCmd.Flags().Bool("disable-files", false, "files will be ignored")
|
||||
loadCmd.Flags().Bool("disable-folders", false, "folders will be ignored")
|
||||
loadCmd.Flags().Bool("pkgs", false, "packages will be installed")
|
||||
loadCmd.Flags().StringSlice("exclude-pkg-managers", []string{}, "package managers to exclude (comma separated)")
|
||||
viper.BindPFlag("load-disable-files", loadCmd.Flags().Lookup("disable-files"))
|
||||
viper.BindPFlag("load-disable-folders", loadCmd.Flags().Lookup("disable-folders"))
|
||||
viper.BindPFlag("load-enable-pkgs", loadCmd.Flags().Lookup("pkgs"))
|
||||
viper.BindPFlag("exclude-pkg-managers", loadCmd.Flags().Lookup("exclude-pkg-managers"))
|
||||
|
||||
saveCmd.Flags().Bool("disable-files", false, "files will be ignored")
|
||||
saveCmd.Flags().Bool("disable-folders", false, "folders will be ignored")
|
||||
|
|
1
go.mod
1
go.mod
|
@ -9,7 +9,6 @@ require (
|
|||
github.com/spf13/cobra v1.3.0
|
||||
github.com/spf13/viper v1.10.1
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
@ -51,7 +51,6 @@ func InitConfig() {
|
|||
viper.SetConfigName(".config-mapper")
|
||||
|
||||
viper.SetDefault("storage.location", fmt.Sprintf("%s/config-mapper", os.TempDir()))
|
||||
viper.SetDefault("package-managers.installation-order", []string{"apt", "homebrew"})
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
|
|
|
@ -43,4 +43,5 @@ type PkgManagers struct {
|
|||
Pip []string `mapstructure:"pip" yaml:"pip"`
|
||||
Npm []string `mapstructure:"npm" yaml:"npm"`
|
||||
Go []string `mapstructure:"go" yaml:"go"`
|
||||
Nala []string `mapstructure:"nala" yaml:"nala"`
|
||||
}
|
||||
|
|
|
@ -46,18 +46,18 @@ func NewItemsActions(items []configuration.OSLocation, storage string, repositor
|
|||
//
|
||||
// If the performed action is "save", it'll also write the `.index` file with all new items.
|
||||
func (e *Items) Action(action string) {
|
||||
color.Blue("# %s files and folders\n", action)
|
||||
fmt.Printf("# %s files and folders\n", action)
|
||||
newLines := []string{}
|
||||
|
||||
for i, l := range e.locations {
|
||||
var src string
|
||||
storagePath, systemPath, err := misc.ConfigPaths(l, e.storage)
|
||||
if err != nil {
|
||||
PrintError("[%d] failed to resolve item paths \"%v\": %v", i, l, err)
|
||||
PrintError("❌ failed to resolve item paths \"%v\": %v", i, l, err)
|
||||
continue
|
||||
}
|
||||
if storagePath == "" && systemPath == "" {
|
||||
color.Blue("[%d] file doesn't have configuration path for current OS. Skipping...")
|
||||
fmt.Printf("⛔ Skipping %s\n", src)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ func (e *Items) Action(action string) {
|
|||
e.loadItem(storagePath, systemPath, i)
|
||||
}
|
||||
|
||||
color.Green("[%d] %s copied", i, src)
|
||||
fmt.Printf("✔️ %s\n", src)
|
||||
}
|
||||
|
||||
if action == "save" && !viper.GetBool("disable-index-update") {
|
||||
|
@ -94,13 +94,13 @@ func (e *Items) Action(action string) {
|
|||
// (E.g: /home/user/.config => .config)
|
||||
func (e *Items) saveItem(src, dst string, index int) string {
|
||||
if err := os.MkdirAll(path.Dir(dst), 0755); err != nil {
|
||||
PrintError("[%d] failed to create directory architecture for destination path \"%s\": %v", index, path.Dir(dst), err)
|
||||
PrintError("❌ failed to create directory architecture for destination path \"%s\": %v", index, path.Dir(dst), err)
|
||||
return ""
|
||||
}
|
||||
|
||||
s, err := os.Stat(src)
|
||||
if err != nil {
|
||||
PrintError("[%d] failed to check if source path is a folder \"%s\": %v", index, src, err)
|
||||
PrintError("❌ failed to check if source path is a folder \"%s\": %v", index, src, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ func (e *Items) saveItem(src, dst string, index int) string {
|
|||
s, err := os.Stat(dst)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
PrintError("[%d] failed to check if destination folder \"%s\" exists: %v", index, dst, err)
|
||||
PrintError("❌ failed to check if destination folder \"%s\" exists: %v", index, dst, err)
|
||||
return ""
|
||||
}
|
||||
} else {
|
||||
|
@ -118,29 +118,29 @@ func (e *Items) saveItem(src, dst string, index int) string {
|
|||
|
||||
// remove the destination if it exists. It cleans up the saved location from unused files
|
||||
if err := os.RemoveAll(dst); err != nil {
|
||||
PrintError("[%d] failed to truncate destination folder \"%s\": %v", index, dst, err)
|
||||
PrintError("❌ failed to truncate destination folder \"%s\": %v", index, dst, err)
|
||||
}
|
||||
|
||||
if err := os.Mkdir(dst, dstPerms); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
PrintError("[%d] failed to create destination folder \"%s\": %v", index, dst, err)
|
||||
PrintError("❌ failed to create destination folder \"%s\": %v", index, dst, err)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
if err := misc.CopyFolder(src, dst, true); err != nil {
|
||||
PrintError("[%d] failed to save folder from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
PrintError("❌ failed to save folder from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
return ""
|
||||
}
|
||||
} else {
|
||||
if err := misc.CopyFile(src, dst); err != nil {
|
||||
PrintError("[%d] failed to save file from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
PrintError("❌ failed to save file from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
p, err := misc.AbsolutePath(e.storage)
|
||||
if err != nil {
|
||||
PrintError("[%d] failed resolve absolute path from configuration storage: %v", index, err)
|
||||
PrintError("❌ failed resolve absolute path from configuration storage: %v", index, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -153,13 +153,13 @@ func (e *Items) saveItem(src, dst string, index int) string {
|
|||
// (meaning the item hasn't been saved) and prints the error in STDERR.
|
||||
func (e *Items) loadItem(src, dst string, index int) {
|
||||
if err := os.MkdirAll(path.Dir(dst), 0755); err != nil {
|
||||
PrintError("[%d] failed to create directory architecture for destination path \"%s\": %v", index, path.Dir(dst), err)
|
||||
PrintError("❌ failed to create directory architecture for destination path \"%s\": %v", index, path.Dir(dst), err)
|
||||
return
|
||||
}
|
||||
|
||||
s, err := os.Stat(src)
|
||||
if err != nil {
|
||||
PrintError("[%d] failed to check if source path is a folder \"%s\": %v", index, src, err)
|
||||
PrintError("❌ failed to check if source path is a folder \"%s\": %v", index, src, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ func (e *Items) loadItem(src, dst string, index int) {
|
|||
s, err := os.Stat(dst)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
PrintError("[%d] failed to check if destination folder \"%s\" exists: %v", index, dst, err)
|
||||
PrintError("❌ failed to check if destination folder \"%s\" exists: %v", index, dst, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
@ -177,17 +177,17 @@ func (e *Items) loadItem(src, dst string, index int) {
|
|||
|
||||
if err := os.Mkdir(dst, dstPerms); err != nil {
|
||||
if !os.IsExist(err) {
|
||||
PrintError("[%d] failed to create destination folder \"%s\": %v", index, dst, err)
|
||||
PrintError("❌ failed to create destination folder \"%s\": %v", index, dst, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := misc.CopyFolder(src, dst, false); err != nil {
|
||||
PrintError("[%d] failed to load folder from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
PrintError("❌ failed to load folder from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := misc.CopyFile(src, dst); err != nil {
|
||||
PrintError("[%d] failed to load file from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
PrintError("❌ failed to load file from \"%s\" to \"%s\": %v", index, src, dst, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
127
internal/pkgs.go
127
internal/pkgs.go
|
@ -4,9 +4,10 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/datahearth/config-mapper/internal/configuration"
|
||||
"github.com/fatih/color"
|
||||
"github.com/gernest/wow"
|
||||
"github.com/gernest/wow/spin"
|
||||
"github.com/spf13/viper"
|
||||
|
@ -14,9 +15,20 @@ import (
|
|||
|
||||
// InstallPackages install all packages from the configuration file by installation order
|
||||
func InstallPackages(c configuration.PkgManagers) error {
|
||||
color.Blue("\n# Installing packages")
|
||||
pkgManagers := map[string]bool{}
|
||||
for _, pkgManager := range viper.GetStringSlice("exclude-pkg-managers") {
|
||||
pkgManagers[pkgManager] = true
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
for _, pkgManager := range c.InstallationOrder {
|
||||
fmt.Printf("# Installing %s packages\n", pkgManager)
|
||||
if _, ok := pkgManagers[pkgManager]; ok {
|
||||
fmt.Printf("⛔ Skipping %s packages\n", pkgManager)
|
||||
fmt.Println()
|
||||
continue
|
||||
}
|
||||
|
||||
var pkgs []string
|
||||
switch pkgManager {
|
||||
case "brew":
|
||||
|
@ -31,53 +43,116 @@ func InstallPackages(c configuration.PkgManagers) error {
|
|||
pkgs = c.Pip
|
||||
case "go":
|
||||
pkgs = c.Go
|
||||
case "nala":
|
||||
pkgs = c.Nala
|
||||
default:
|
||||
PrintError("package manager not supported: %s", pkgManager)
|
||||
PrintError("package manager not supported: %s\n", pkgManager)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := exec.LookPath(pkgManager); err != nil {
|
||||
// * pip might not be available on the system but pip3 is
|
||||
if pkgManager == "pip" {
|
||||
if _, err := exec.LookPath("pip3"); err != nil {
|
||||
return fmt.Errorf("%s and pip3 are not available on your system", pkgManager)
|
||||
PrintError("%s and pip3 are not available on your system\n", pkgManager)
|
||||
continue
|
||||
}
|
||||
pkgManager = "pip3"
|
||||
} else {
|
||||
return fmt.Errorf("%s is not available on your system", pkgManager)
|
||||
PrintError("%s is not available on your system\n", pkgManager)
|
||||
continue
|
||||
}
|
||||
}
|
||||
// * for some reason, apt binary is available on darwin. Exclude it to avoid errors
|
||||
if pkgManager == "apt" && runtime.GOOS == "darwin" {
|
||||
PrintError("%s is not available on your system\n", pkgManager)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Printf("%s: nothing to do\n", pkgManager)
|
||||
return nil
|
||||
fmt.Printf("✔️ nothing to do\n\n")
|
||||
continue
|
||||
}
|
||||
|
||||
cmd := exec.Command(pkgManager, "install")
|
||||
cmd.Args = append(cmd.Args, pkgs...)
|
||||
color.Blue("\n## Installing %s packages", pkgManager)
|
||||
|
||||
spinner := wow.New(os.Stdout, spin.Get(spin.Dots3), " Running...")
|
||||
|
||||
v := viper.GetBool("verbose")
|
||||
if v {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
commands := []*exec.Cmd{}
|
||||
// * package managers requiring sudo permission
|
||||
if pkgManager == "apt" || pkgManager == "nala" {
|
||||
commands = append(commands, buildDefaultCommand([]string{"sudo", pkgManager, "install", "-y"}, pkgs, v))
|
||||
} else if pkgManager == "cargo" {
|
||||
commands = buildCargoCommand(pkgs, v)
|
||||
} else {
|
||||
spinner.Start()
|
||||
commands = append(commands, buildDefaultCommand([]string{pkgManager, "install"}, pkgs, v))
|
||||
}
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
spinner.Stop()
|
||||
PrintError("\n%s command failed: %v", pkgManager, err)
|
||||
return err
|
||||
}
|
||||
for i, cmd := range commands {
|
||||
spinner := wow.New(os.Stdout, spin.Get(spin.Dots3), " Installing...")
|
||||
if !v {
|
||||
spinner.Start()
|
||||
}
|
||||
if err := cmd.Run(); err != nil {
|
||||
if v {
|
||||
PrintError(err.Error())
|
||||
} else {
|
||||
msg := fmt.Sprintf(" %s", cmd.Args)
|
||||
if i == len(commands)-1 {
|
||||
msg = fmt.Sprintf("%s\n", msg)
|
||||
}
|
||||
spinner.PersistWith(spin.Spinner{Frames: []string{"❌"}}, msg)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if v {
|
||||
// todo: find a way to clear spinner when done
|
||||
spinner.Stop()
|
||||
if !v {
|
||||
// msg := fmt.Sprintf(" %s %s", color.GreenString("Success\t"), cmd.Args)
|
||||
msg := fmt.Sprintf(" %s", cmd.Args)
|
||||
if i == len(commands)-1 {
|
||||
msg = fmt.Sprintf("%s\n", msg)
|
||||
}
|
||||
spinner.PersistWith(spin.Spinner{Frames: []string{"✔️"}}, msg)
|
||||
}
|
||||
}
|
||||
color.Green("\n%s Packages intalled succesfully !", pkgManager)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildCargoCommand(packages []string, verbose bool) []*exec.Cmd {
|
||||
commands := []*exec.Cmd{}
|
||||
|
||||
cmd := exec.Command("cargo", "install")
|
||||
for _, pkg := range packages {
|
||||
if strings.Contains(pkg, " ") {
|
||||
customCmd := exec.Command("cargo", "install")
|
||||
customCmd.Args = append(cmd.Args, strings.Split(pkg, " ")...)
|
||||
if verbose {
|
||||
customCmd.Stderr = os.Stderr
|
||||
customCmd.Stdout = os.Stdout
|
||||
}
|
||||
commands = append(commands, customCmd)
|
||||
} else {
|
||||
cmd.Args = append(cmd.Args, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
if verbose {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
}
|
||||
if len(cmd.Args) > 2 {
|
||||
commands = append(commands, cmd)
|
||||
}
|
||||
|
||||
return commands
|
||||
}
|
||||
|
||||
func buildDefaultCommand(command, packages []string, verbose bool) *exec.Cmd {
|
||||
cmd := exec.Command(command[0], command[1:]...)
|
||||
cmd.Args = append(cmd.Args, packages...)
|
||||
if verbose {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
import enum
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import subprocess
|
||||
from typing import Any, Dict
|
||||
import requests
|
||||
|
||||
GITEA_API = "https://gitea.antoine-langlois.net/api/v1/repos/DataHearth/config-mapper"
|
||||
NTR = "\033[0m" # * Neutral
|
||||
INF = "\033[0;34m" # * Blue (info)
|
||||
WRN = "\033[1;33m" # * Yellow (warning)
|
||||
ERR = "\033[1;31m" # * Red (error)
|
||||
version_regex = re.compile(r"Version: \"v\d*.\d*.\d*\"")
|
||||
|
||||
|
||||
class LogLevel(enum.Enum):
|
||||
INFO = "INFO"
|
||||
WARNING = "WARNING"
|
||||
ERROR = "ERROR"
|
||||
|
||||
|
||||
def log(msg: str, level: LogLevel = LogLevel.INFO):
|
||||
color_lvl = (
|
||||
INF
|
||||
if level == LogLevel.INFO
|
||||
else WRN
|
||||
if level == LogLevel.WARNING
|
||||
else ERR
|
||||
if level == LogLevel.ERROR
|
||||
else INF
|
||||
)
|
||||
print(f"{color_lvl}{level.value}{NTR} {msg}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
release = input("Enter a release version (vX.Y.Z): ")
|
||||
|
||||
log("updating release version in files")
|
||||
with open("cmd/cli.go") as f:
|
||||
data = version_regex.sub(f'Version: "{release}"', f.read())
|
||||
|
||||
with open("cmd/cli.go", "w") as f:
|
||||
f.write(data)
|
||||
|
||||
res = subprocess.run(
|
||||
["git-chglog", "--next-tag", release, "--output", "CHANGELOG.md"],
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.DEVNULL,
|
||||
)
|
||||
if res.returncode != 0:
|
||||
log(
|
||||
f'failed to generate changelog: {res.stderr.decode("UTF-8")}',
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
log("commit & push changes")
|
||||
res = subprocess.run(
|
||||
args=f"git add . && git commit -m {release}",
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.DEVNULL,
|
||||
shell=True,
|
||||
)
|
||||
if res.returncode != 0:
|
||||
log(
|
||||
f'failed to commit changes: {res.stderr.decode("UTF-8")}',
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
res = subprocess.run(
|
||||
args=f"git tag -a {release} -m {release} && git push --follow-tags",
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.DEVNULL,
|
||||
shell=True,
|
||||
)
|
||||
if res.returncode != 0:
|
||||
log(
|
||||
f'failed to tag and push changes: {res.stderr.decode("UTF-8")}',
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
log("building Linux binary")
|
||||
res = subprocess.run(
|
||||
args=["go", "build", "-o", "build/x86-x64_linux_config-mapper"],
|
||||
env=os.environ | {"GOOS": "linux"},
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.DEVNULL,
|
||||
)
|
||||
if res.returncode != 0:
|
||||
log(
|
||||
f'failed to build linux binary: {res.stderr.decode("UTF-8")}',
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
log("building Darwin binary")
|
||||
res = subprocess.run(
|
||||
args=["go", "build", "-o", "build/x86-x64_darwin_config-mapper"],
|
||||
env=os.environ | {"GOOS": "darwin"},
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.DEVNULL,
|
||||
)
|
||||
if res.returncode != 0:
|
||||
log(
|
||||
f'failed to build darwin binary: {res.stderr.decode("UTF-8")}',
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
log("creating gitea release")
|
||||
api_token: str
|
||||
if len(sys.argv) > 1:
|
||||
api_token = sys.argv.pop()
|
||||
elif os.getenv("GIT_CFG_MAPPER_TOKEN"):
|
||||
api_token = os.getenv("GIT_CFG_MAPPER_TOKEN")
|
||||
else:
|
||||
log("no gitea api token found in CLI params nor in ENV", LogLevel.ERROR)
|
||||
sys.exit(1)
|
||||
|
||||
res = subprocess.run(
|
||||
args=["git-chglog", "-t", ".chglog/RELEASE_CHANGELOG.tpl.md"],
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
if res.returncode != 0:
|
||||
log(
|
||||
f'failed to generate release body: {res.stderr.decode("UTF-8")}',
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
response = requests.post(
|
||||
url=f"{GITEA_API}/releases",
|
||||
headers={"Authorization": f"token {api_token}"},
|
||||
json={
|
||||
"body": res.stdout.decode("UTF-8"),
|
||||
"draft": False,
|
||||
"prerelease": False,
|
||||
"name": release,
|
||||
"tag_name": release,
|
||||
},
|
||||
)
|
||||
if not response.ok:
|
||||
log(
|
||||
f"failed to generate release (status {response.status_code}): {response.json()}",
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
body: Dict[str, Any] = response.json()
|
||||
release_id = body.get("id")
|
||||
if not release_id:
|
||||
log("no release id found in response body", LogLevel.ERROR)
|
||||
sys.exit(1)
|
||||
|
||||
response = requests.post(
|
||||
url=f"{GITEA_API}/releases/{release_id}/assets",
|
||||
headers={"Authorization": f"token {api_token}"},
|
||||
files={
|
||||
"attachment": (
|
||||
"x86-x64_linux_config-mapper",
|
||||
open("build/x86-x64_linux_config-mapper", "rb"),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
if not response.ok:
|
||||
log(
|
||||
f"failed to upload linux binary (status: {response.status_code}): {response.json()}",
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
response = requests.post(
|
||||
url=f"{GITEA_API}/releases/{release_id}/assets",
|
||||
headers={"Authorization": f"token {api_token}"},
|
||||
files={
|
||||
"attachment": (
|
||||
"x86-x64_darwin_config-mapper",
|
||||
open("build/x86-x64_darwin_config-mapper", "rb"),
|
||||
)
|
||||
},
|
||||
)
|
||||
if not response.ok:
|
||||
log(
|
||||
f"failed to upload darwin binary (status: {response.status_code}): {response.json()}",
|
||||
LogLevel.ERROR,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
log("Done !")
|
75
release.sh
75
release.sh
|
@ -1,75 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
VERSION=v0.5.0
|
||||
|
||||
log() {
|
||||
NTR=$'\033[0m' # * Neutral
|
||||
INF=$'\033[0;34m' # * Blue (info)
|
||||
WRN=$'\033[1;33m' # * Yellow (warning)
|
||||
ERR=$'\033[1;31m' # * Red (error)
|
||||
|
||||
log_lvl=""
|
||||
case $1 in
|
||||
INFO)
|
||||
log_lvl="${INF}$1"
|
||||
;;
|
||||
WARNING)
|
||||
log_lvl="${WRN}$1"
|
||||
;;
|
||||
ERROR)
|
||||
log_lvl="${ERR}$1"
|
||||
;;
|
||||
esac
|
||||
|
||||
log_lvl="${log_lvl}${NTR}"
|
||||
msg="${log_lvl}\t$2"
|
||||
|
||||
echo -e "${msg}"
|
||||
}
|
||||
|
||||
log "INFO" "checking required dependencies to create release"
|
||||
if ! type git 1> /dev/null; then
|
||||
log "ERROR" "\"git\" binary not available"
|
||||
exit 1
|
||||
fi
|
||||
if ! type sd 1> /dev/null; then
|
||||
log "ERROR" "\"sd\" binary not available"
|
||||
exit 1
|
||||
fi
|
||||
if ! type gh 1> /dev/null; then
|
||||
log "ERROR" "\"gh\" binary not available"
|
||||
exit 1
|
||||
fi
|
||||
if ! type go 1> /dev/null; then
|
||||
log "ERROR" "\"go\" binary not available"
|
||||
exit 1
|
||||
fi
|
||||
if ! type git-chglog 1> /dev/null; then
|
||||
log "ERROR" "\"git-chglog\" binary not available"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
read -p "Enter a release version (vX.Y.Z): " release
|
||||
|
||||
log "INFO" "updating release version in files"
|
||||
sd "Version: \"$VERSION\"" "Version: \"$release\"" cmd/cli.go
|
||||
sd "VERSION=$VERSION" "VERSION=$release" release.sh
|
||||
|
||||
log "INFO" "updating changelog"
|
||||
git-chglog --next-tag $release --output CHANGELOG.md
|
||||
|
||||
log "INFO" "commit & push changes"
|
||||
git add .
|
||||
git commit -m "$release"
|
||||
git push
|
||||
git tag -a $release -m $release
|
||||
git push --tags
|
||||
|
||||
log "INFO" "building Linux binary"
|
||||
GOOS=linux go build -o build/x86-x64_linux_config-mapper
|
||||
|
||||
log "INFO" "building Darwin binary"
|
||||
GOOS=darwin go build -o build/x86-x64_darwin_config-mapper
|
||||
|
||||
log "INFO" "creating release"
|
||||
git-chglog -t .chglog/RELEASE_CHANGELOG.tpl.md | gh release create -F - v0.4.0 build/x86-x64_*
|
Reference in New Issue