Compare commits

...

4 Commits

Author SHA1 Message Date
DataHearth 7c1c71ad55
chore: update CHANGELOG v0.6.1 2022-10-04 22:47:06 +02:00
DataHearth 5682db8ac9
chore(process): add just and goreleaser 2022-10-02 21:15:10 +02:00
DataHearth 29e0be566c
chore(doc): update README.md 2022-09-12 18:47:10 +02:00
DataHearth b27c1f9e89
feat(ssh): add possibilty to use multiple SSH configurations 2022-09-12 18:40:40 +02:00
17 changed files with 158 additions and 250 deletions

7
.gitignore vendored
View File

@ -1,4 +1,5 @@
.config-mapper.yml
.env
.DS_STORE
build
.DS_Store
.env
dist/
.config-mapper.yml

29
.goreleaser.yaml Normal file
View File

@ -0,0 +1,29 @@
before:
hooks:
- go mod tidy
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
archives:
- replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
gitea_urls:
api: https://gitea.antoine-langlois.net/api/v1
download: https://gitea.antoine-langlois.net
release:
gitea:
owner: DataHearth
name: config-mapper
mode: append
checksum:
name_template: "checksums.txt"
snapshot:
name_template: "{{ incpatch .Version }}-next"

View File

@ -3,8 +3,14 @@
## [Unreleased]
<a name="v0.6.1"></a>
## [v0.6.1] - 2022-10-02
### Features
- **ssh:** add possibilty to use multiple SSH configurations
<a name="v0.6.0"></a>
## [v0.6.0] - 2022-08-20
## [v0.6.0] - 2022-08-21
### Bug Fixes
- **configuration:** remove installation-order default value
- **items:** fix stdout when no path is available
@ -16,7 +22,7 @@
<a name="v0.5.0"></a>
## [v0.5.0] - 2022-08-01
## [v0.5.0] - 2022-07-10
### Bug Fixes
- **git:** use go-git for adding removed file (workaround)
@ -25,7 +31,7 @@
<a name="v0.4.0"></a>
## [v0.4.0] - 2022-08-01
## [v0.4.0] - 2022-06-16
### Bug Fixes
- **config:** don't throw error when file not available on OS
- **save:** remove folder before copy (avoid unwanted files)
@ -36,15 +42,17 @@
<a name="v0.3.0"></a>
## [v0.3.0] - 2022-08-01
## [v0.3.0] - 2022-06-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-08-01
## [v0.2.0] - 2022-05-23
### 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
@ -54,15 +62,24 @@
### 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-07-31
## v0.1.0 - 2022-02-27
### Bug Fixes
- **config:** fix config path check
- **copy:** use io.Copy instead of custom copy
@ -81,7 +98,8 @@
- **config:** add yaml tags for yaml.v3
[Unreleased]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.6.0...HEAD
[Unreleased]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.6.1...HEAD
[v0.6.1]: https://gitea.antoine-langlois.net/DataHearth/config-mapper/compare/v0.6.0...v0.6.1
[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

View File

@ -11,32 +11,28 @@ When copying a file from your configuration repository to your system, it's perf
The system is detected automatically. You just need to specify whether the related field in case of `files` or folders `sections` (fields: `darwin` | `linux`).
You can get a configuration template [here](https://raw.githubusercontent.com/DataHearth/config-mapper/main/.config-mapper.yml.template).
You can get a configuration template [here](https://gitea.antoine-langlois.net/DataHearth/config-mapper/raw/branch/main/.config-mapper.yml.template).
### Installation
Using a pre-build binary:
- Using a pre-build binary
- `wget`
Binaries are available in the `release` section at [https://gitea.antoine-langlois.net/DataHearth/config-mapper/releases](https://gitea.antoine-langlois.net/DataHearth/config-mapper/releases).
- Building from source:
```bash
wget https://github.com/DataHearth/config-mapper/releases/download/{RELEASE}/x86-x64_{linux|darwin}_config-mapper -O $HOME/.local/bin/
```
- `gh`
```bash
gh release download -r DataHearth/config-mapper {RELEASE} -d $HOME/.local/bin/ -p "x86-x64_{linux|darwin}_config-mapper"
```
Building from source:
```bash
git clone git@github.com:datahearth/config-mapper.git
git clone https://gitea.antoine-langlois.net/DataHearth/config-mapper.git
cd config-mapper
go build -o $HOME/.local/bin/config-mapper
```
- With Golang cli
```bash
go install gitea.antoine-langlois.net/datahearth/config-mapper@latest
```
### Setup
Create a file called `.config-mapper.yml` in your `home` directory (it is the default search path for config-mapper).

View File

@ -6,9 +6,9 @@ import (
"strconv"
"time"
mapper "github.com/datahearth/config-mapper/internal"
"github.com/datahearth/config-mapper/internal/configuration"
"github.com/datahearth/config-mapper/internal/git"
mapper "gitea.antoine-langlois.net/datahearth/config-mapper/internal"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/configuration"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/git"
"github.com/fatih/color"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@ -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.6.0",
Version: "v0.6.1",
}
var initCmd = &cobra.Command{
Use: "init",

4
go.mod
View File

@ -1,4 +1,4 @@
module github.com/datahearth/config-mapper
module gitea.antoine-langlois.net/datahearth/config-mapper
go 1.17
@ -6,6 +6,7 @@ require (
github.com/fatih/color v1.13.0
github.com/gernest/wow v0.1.0
github.com/go-git/go-git/v5 v5.4.2
github.com/mitchellh/mapstructure v1.5.0
github.com/spf13/cobra v1.3.0
github.com/spf13/viper v1.10.1
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
@ -28,7 +29,6 @@ require (
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/spf13/afero v1.6.0 // indirect

3
go.sum
View File

@ -313,8 +313,9 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=

View File

@ -22,7 +22,7 @@ type Git struct {
Name string `mapstructure:"name" yaml:"name"`
Email string `mapstructure:"email" yaml:"email"`
BasicAuth BasicAuth `mapstructure:"basic-auth" yaml:"basic-auth"`
SSH Ssh `mapstructure:"ssh" yaml:"ssh"`
SSH interface{} `mapstructure:"ssh" yaml:"ssh"`
}
type BasicAuth struct {

View File

@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
osUser "os/user"
"strings"
@ -156,7 +155,7 @@ func getUriContent(uri string) (string, string, error) {
func createPubKeyAuth(key string) (ssh.AuthMethod, error) {
var signer ssh.Signer
privateKey, err := ioutil.ReadFile(key)
privateKey, err := os.ReadFile(key)
if err != nil {
return nil, err
}

View File

@ -2,16 +2,18 @@ package git
import (
"errors"
"fmt"
"os"
"time"
"github.com/datahearth/config-mapper/internal/configuration"
"github.com/datahearth/config-mapper/internal/misc"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/configuration"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/misc"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
"github.com/mitchellh/mapstructure"
)
var (
@ -48,25 +50,45 @@ func NewRepository(config configuration.Git, repoPath string) (RepositoryActions
return nil, err
}
if config.SSH.Passphrase != "" && config.SSH.PrivateKey != "" {
privateKey, err := misc.AbsolutePath(config.SSH.PrivateKey)
if err != nil {
switch sshConfig := config.SSH.(type) {
case map[string]interface{}:
var outConfig configuration.Ssh
if err := mapstructure.Decode(sshConfig, &outConfig); err != nil {
return nil, err
}
if _, err := os.Stat(privateKey); err != nil {
return nil, err
}
auth, err = ssh.NewPublicKeysFromFile("git", privateKey, config.SSH.Passphrase)
auth, err = getSSHAuthMethod(outConfig)
if err != nil {
return nil, err
}
} else {
auth = &http.BasicAuth{
Username: config.BasicAuth.Username,
Password: config.BasicAuth.Password,
case []interface{}:
for i, c := range sshConfig {
if _, ok := c.(map[interface{}]interface{}); !ok {
fmt.Printf("invalid format for configuration n°%d", i)
continue
}
var outConfig configuration.Ssh
if err := mapstructure.Decode(c, &outConfig); err != nil {
fmt.Printf("failed to decode ssh configuration n°%d: %v\n", i, err)
continue
}
auth, err = getSSHAuthMethod(outConfig)
if err != nil {
fmt.Printf("failed to create SSH authentication method for configuration n°%d: %v\n", i, err)
continue
}
}
if auth == nil {
auth = &http.BasicAuth{
Username: config.BasicAuth.Username,
Password: config.BasicAuth.Password,
}
}
default:
return nil, errors.New("git ssh configuration canno't be unmarshaled. Please, pass a valid configuration")
}
repo := &Repository{
@ -170,3 +192,25 @@ func (r *Repository) GetAuthor() *object.Signature {
When: time.Now(),
}
}
func getSSHAuthMethod(config configuration.Ssh) (transport.AuthMethod, error) {
if config.Passphrase == "" && config.PrivateKey == "" {
return nil, errors.New("passphrase and private are empty")
}
privateKey, err := misc.AbsolutePath(config.PrivateKey)
if err != nil {
return nil, err
}
if _, err := os.Stat(privateKey); err != nil {
return nil, err
}
auth, err := ssh.NewPublicKeysFromFile("git", privateKey, config.Passphrase)
if err != nil {
return nil, err
}
return auth, nil
}

View File

@ -6,7 +6,7 @@ import (
"os"
"strings"
"github.com/datahearth/config-mapper/internal/misc"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/misc"
)
type Index struct {

View File

@ -7,9 +7,9 @@ import (
"path"
"strings"
"github.com/datahearth/config-mapper/internal/configuration"
"github.com/datahearth/config-mapper/internal/git"
"github.com/datahearth/config-mapper/internal/misc"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/configuration"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/git"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/misc"
"github.com/fatih/color"
"github.com/spf13/viper"
)
@ -57,7 +57,7 @@ func (e *Items) Action(action string) {
continue
}
if storagePath == "" && systemPath == "" {
fmt.Printf("⛔ Skipping %s\n", src)
fmt.Println("⛔ Skipping")
continue
}

View File

@ -9,7 +9,7 @@ import (
"runtime"
"strings"
"github.com/datahearth/config-mapper/internal/configuration"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/configuration"
)
func AbsolutePath(p string) (string, error) {

View File

@ -7,7 +7,7 @@ import (
"runtime"
"strings"
"github.com/datahearth/config-mapper/internal/configuration"
"gitea.antoine-langlois.net/datahearth/config-mapper/internal/configuration"
"github.com/gernest/wow"
"github.com/gernest/wow/spin"
"github.com/spf13/viper"

12
justfile Normal file
View File

@ -0,0 +1,12 @@
set shell := ["zsh", "-uc"]
set dotenv-load
default:
@just --list
publish version:
git-chglog --next-tag {{version}} --output CHANGELOG.md
git add CHANGELOG.md && git commit -m "chore: update CHANGELOG {{version}}"
git tag -a {{version}} -m "{{version}}"
git push --follow-tags
goreleaser release --rm-dist --release-notes <(git-chglog -t .chglog/RELEASE_CHANGELOG.tpl.md)

View File

@ -1,6 +1,6 @@
package main
import "github.com/datahearth/config-mapper/cmd"
import "gitea.antoine-langlois.net/datahearth/config-mapper/cmd"
func main() {
cmd.Execute()

View File

@ -1,192 +0,0 @@
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 !")