-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4d08e7b
Showing
16 changed files
with
497 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Set the workflow name. | ||
name: CI | ||
|
||
# Execute the workflow on pushes and pull requests. | ||
on: [push, pull_request] | ||
|
||
jobs: | ||
linux: | ||
name: Linux | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: '^1.17' | ||
- run: docker version | ||
- run: go version | ||
- run: ./build.sh | ||
- uses: actions/upload-artifact@v2 | ||
with: | ||
name: binaries | ||
path: mutagen-ssh-wrapper.tar.gz | ||
versioning: | ||
name: Versioning | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: '^1.17' | ||
- run: go version | ||
- name: "Analyze version information and release status" | ||
id: analyze | ||
run: | | ||
# Determine whether or not this is a release build. | ||
RELEASE="${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}" | ||
# Determine version target information for Go. If this is a release, | ||
# then we'll use the tag, otherwise we'll use the raw commit identifier. | ||
if [ "${RELEASE}" = "true" ]; then | ||
TARGET="${GITHUB_REF#refs/tags/}" | ||
else | ||
TARGET="${GITHUB_SHA}" | ||
fi | ||
# Set outputs. | ||
echo ::set-output name=release::${RELEASE} | ||
echo ::set-output name=target::${TARGET} | ||
outputs: | ||
release: ${{ steps.analyze.outputs.release }} | ||
target: ${{ steps.analyze.outputs.target }} | ||
release: | ||
name: Release | ||
runs-on: ubuntu-latest | ||
needs: [linux, versioning] | ||
if: ${{ needs.versioning.outputs.release == 'true' }} | ||
steps: | ||
- uses: actions/download-artifact@v2 | ||
with: | ||
name: binaries | ||
path: . | ||
- uses: softprops/action-gh-release@v1 | ||
with: | ||
files: | | ||
mutagen-ssh-wrapper.tar.gz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
|
||
# Dependency directories (remove the comment below to include it) | ||
# vendor/ | ||
|
||
# IDE specific | ||
/.vscode | ||
|
||
# Output dir | ||
/out | ||
|
||
# Bundle | ||
*.tar.gz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2021 Duckly | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# mutagen-ssh-wrapper | ||
Mutagen SSH wrapper for Windows |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/bin/sh | ||
set -e | ||
|
||
GOOS=windows GOARCH=386 go build -o ./out/ ./cmd/ssh | ||
GOOS=windows GOARCH=386 go build -o ./out/ ./cmd/scp | ||
GOOS=windows GOARCH=386 go build -o ./out/ ./cmd/grun | ||
tar czf mutagen-ssh-wrapper.tar.gz -C ./out scp.exe ssh.exe grun.exe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"strconv" | ||
|
||
"golang.org/x/sync/errgroup" | ||
"ssh-wrapper/cmd" | ||
) | ||
|
||
func main() { | ||
if len(os.Args) < 2 { | ||
if len(os.Args) == 1 { | ||
fmt.Fprintln(os.Stderr, "Error: missing arguments: parent PID and command") | ||
} else { | ||
fmt.Fprintln(os.Stderr, "Error: missing command argument") | ||
} | ||
os.Exit(1) | ||
} | ||
|
||
commandName, args := os.Args[2], os.Args[3:] | ||
|
||
parentPid, err := strconv.Atoi(os.Args[1]) | ||
if err != nil { | ||
fmt.Fprintln(os.Stderr, "Error: parent PID is not a number:", parentPid) | ||
os.Exit(1) | ||
} | ||
|
||
parentProcess, err := os.FindProcess(parentPid) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error: cannot find process PID %d: %v", parentPid, err) | ||
os.Exit(1) | ||
} | ||
|
||
g, ctx := errgroup.WithContext(context.Background()) | ||
|
||
command := exec.CommandContext(ctx, commandName, args...) | ||
command.Stdin = os.Stdin | ||
command.Stdout = os.Stdout | ||
command.Stderr = os.Stderr | ||
|
||
// Wait for the child process to finish | ||
g.Go(func() error { | ||
cmd.WrapRunAndExit(command) | ||
return nil | ||
}) | ||
|
||
// Wait for the parent process to finish. If so, kill the child process | ||
g.Go(func() error { | ||
_, err := parentProcess.Wait() | ||
command.Process.Kill() | ||
return err | ||
}) | ||
|
||
g.Wait() | ||
os.Exit(1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path" | ||
"path/filepath" | ||
"runtime" | ||
"strconv" | ||
"strings" | ||
"syscall" | ||
|
||
"ssh-wrapper/pkg/process" | ||
) | ||
|
||
const ( | ||
MUTAGEN_SSH_CONFIG = "MUTAGEN_SSH_CONFIG" | ||
MUTAGEN_CONNECT_TIMEOUT_IN_SECONDS = 20 | ||
) | ||
|
||
func ProcessArgs() []string { | ||
sshConfig := os.Getenv(MUTAGEN_SSH_CONFIG) | ||
if sshConfig == "" { | ||
fmt.Fprintln(os.Stderr, "Error: MUTAGEN_SSH_CONFIG environment variable is not set") | ||
os.Exit(1) | ||
} | ||
|
||
// Increase the default timeout | ||
args := os.Args[1:] | ||
for i, arg := range args { | ||
if strings.HasPrefix(arg, "-oConnectTimeout=") { | ||
args[i] = fmt.Sprintf("-oConnectTimeout=%d", MUTAGEN_CONNECT_TIMEOUT_IN_SECONDS) | ||
break | ||
} | ||
} | ||
|
||
return append([]string{fmt.Sprintf("-F%s", sshConfig)}, args...) | ||
} | ||
|
||
func WrapRunAndExit(command *exec.Cmd) { | ||
command.Stdin = os.Stdin | ||
command.Stdout = os.Stdout | ||
command.Stderr = os.Stderr | ||
|
||
if err := command.Run(); err != nil { | ||
if exiterr, ok := err.(*exec.ExitError); ok { | ||
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { | ||
os.Exit(status.ExitStatus()) | ||
} | ||
} | ||
os.Exit(1) | ||
} | ||
os.Exit(0) | ||
} | ||
|
||
func Grun(commandName string, args ...string) { | ||
args = append([]string{strconv.Itoa(os.Getpid()), commandName}, args...) | ||
|
||
self, err := os.Executable() | ||
if err != nil { | ||
fmt.Fprintln(os.Stderr, "Error: cannot get current executable path") | ||
os.Exit(1) | ||
} | ||
|
||
grun := path.Join(filepath.Dir(self), process.ExecutableName("grun", runtime.GOOS)) | ||
command := exec.CommandContext(context.Background(), grun, args...) | ||
WrapRunAndExit(command) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"ssh-wrapper/pkg/ssh" | ||
"ssh-wrapper/cmd" | ||
) | ||
|
||
func main() { | ||
args := cmd.ProcessArgs() | ||
|
||
commandName, err := ssh.ScpCommandPath() | ||
if err != nil { | ||
fmt.Fprintln(os.Stderr, "Error: unable to set up SCP invocation:", err) | ||
os.Exit(1) | ||
} | ||
|
||
cmd.Grun(commandName, args...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"ssh-wrapper/cmd" | ||
"ssh-wrapper/pkg/ssh" | ||
) | ||
|
||
func main() { | ||
args := cmd.ProcessArgs() | ||
|
||
commandName, err := ssh.SshCommandPath() | ||
if err != nil { | ||
fmt.Fprintln(os.Stderr, "Error: unable to set up SSH invocation:", err) | ||
os.Exit(1) | ||
} | ||
|
||
cmd.Grun(commandName, args...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module ssh-wrapper | ||
|
||
go 1.17 | ||
|
||
require golang.org/x/sync v0.0.0-20210220032951-036812b2e83c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= | ||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package process | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"runtime" | ||
) | ||
|
||
// FindCommand searches for a command with the specified name within the | ||
// specified list of directories. It's similar to os/exec.LookPath, except that | ||
// it allows one to manually specify paths, and it uses a slightly simpler | ||
// lookup mechanism. | ||
func FindCommand(name string, paths []string) (string, error) { | ||
// Iterate through the directories. | ||
for _, path := range paths { | ||
// Compute the target name. | ||
target := filepath.Join(path, ExecutableName(name, runtime.GOOS)) | ||
|
||
// Check if the target exists and has the correct type. | ||
// TODO: Should we do more extensive (and platform-specific) testing on | ||
// the resulting metadata? See, e.g., the implementation of | ||
// os/exec.LookPath. | ||
if metadata, err := os.Stat(target); err != nil { | ||
if os.IsNotExist(err) { | ||
continue | ||
} | ||
return "", fmt.Errorf("unable to query file metadata: %w", err) | ||
} else if metadata.Mode()&os.ModeType != 0 { | ||
continue | ||
} else { | ||
return target, nil | ||
} | ||
} | ||
|
||
// Failure. | ||
return "", errors.New("unable to locate command") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package process | ||
|
||
// ExecutableName computes the name for an executable for a given base name on a | ||
// specified operating system. | ||
func ExecutableName(base, goos string) string { | ||
// If we're on Windows, append ".exe". | ||
if goos == "windows" { | ||
return base + ".exe" | ||
} | ||
|
||
// Otherwise return the base name unmodified. | ||
return base | ||
} |
Oops, something went wrong.