Skip to content

Commit

Permalink
Merge pull request #2 from pojntfx/fix-multi-arch-pulls
Browse files Browse the repository at this point in the history
[WIP] Pull and tag multi-arch images explicitly (#1)
  • Loading branch information
pojntfx authored Aug 26, 2021
2 parents dc75a49 + 801423b commit ca29bfd
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 10 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/hydrun.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ jobs:
go-version: 1.16
- name: Build with hydrun
run: go run main.go -o golang ./Hydrunfile
- name: Publish branch preview release to GitHub releases
if: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/v') && !startsWith(github.ref, 'refs/pull') }}
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: branch-${{ github.ref }}
prerelease: true
files: |
out/*
- name: Publish pre-release to GitHub releases
if: ${{ github.ref == 'refs/heads/main' }}
uses: marvinpinto/action-automatic-releases@latest
Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,14 @@ Execute a command for the current directory on multiple architectures and operat
See https://github.com/pojntfx/hydrun for more information.

Usage: hydrun [OPTION...] "<COMMAND...>"
-a, --arch string Comma-separated list of architectures to run on (default "amd64")
-c, --context string Directory to use in the container
-e, --extra-args string Extra arguments to pass to the Docker command
-i, --it Attach stdin and setup a TTY
-j, --jobs int Maximum amount of parallel jobs (default 1)
-o, --os string Comma-separated list of operating systems to run on (default "debian")
-a, --arch string Comma-separated list of architectures to run on (default "amd64")
-c, --context string Directory to use in the container
-e, --extra-args string Extra arguments to pass to the Docker command
-i, --it Attach stdin and setup a TTY
-j, --jobs int Maximum amount of parallel jobs (default 1)
-o, --os string Comma-separated list of operating systems (Docker images) to run on (default "debian")
-p, --pull Always pull the specified tags of the operating systems (Docker images)
-q, --quiet Disable logging executed commands
```

## Contributing
Expand Down
60 changes: 56 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ Usage: %s [OPTION...] "<COMMAND...>"

// Parse flags
archFlag := pflag.StringP("arch", "a", "amd64", "Comma-separated list of architectures to run on")
osFlag := pflag.StringP("os", "o", "debian", "Comma-separated list of operating systems to run on")
osFlag := pflag.StringP("os", "o", "debian", "Comma-separated list of operating systems (Docker images) to run on")
jobFlag := pflag.Int64P("jobs", "j", 1, "Maximum amount of parallel jobs")
itFlag := pflag.BoolP("it", "i", false, "Attach stdin and setup a TTY")
contextFlag := pflag.StringP("context", "c", "", "Directory to use in the container")
extraArgs := pflag.StringP("extra-args", "e", "", "Extra arguments to pass to the Docker command")
pullFlag := pflag.BoolP("pull", "p", false, "Always pull the specified tags of the operating systems (Docker images)")
quietFlag := pflag.BoolP("quiet", "q", false, "Disable logging executed commands")

pflag.Parse()

Expand Down Expand Up @@ -81,14 +83,58 @@ Usage: %s [OPTION...] "<COMMAND...>"
}
}

// Pull and tag images
for _, target := range targets {
existsCmd := exec.Command("docker", strings.Split(fmt.Sprintf(`inspect %v`, getImageNameWithSuffix(target.OS, target.Architecture)), " ")...)

if !*quietFlag {
log.Println(existsCmd)
}

shouldPullAndTag := true
if *pullFlag {
shouldPullAndTag = false
} else {
if output, err := existsCmd.CombinedOutput(); err != nil {
if strings.Contains(string(output), "Error: No such object") {
shouldPullAndTag = false
} else {
log.Fatalln("could not check if image already exists:", err)
}
}
}

if !shouldPullAndTag {
runCmd := exec.Command("docker", strings.Split(fmt.Sprintf(`pull --platform linux/%v %v`, target.Architecture, target.OS), " ")...)

if !*quietFlag {
log.Println(runCmd)
}

if output, err := runCmd.CombinedOutput(); err != nil {
log.Fatalln("could not pull image:", err.Error()+":", string(output))
}

tagCmd := exec.Command("docker", strings.Split(fmt.Sprintf(`tag %v %v`, target.OS, getImageNameWithSuffix(target.OS, target.Architecture)), " ")...)

if !*quietFlag {
log.Println(tagCmd)
}

if output, err := tagCmd.CombinedOutput(); err != nil {
log.Fatalln("could not tag image:", err.Error()+":", string(output))
}
}
}

// Setup concurrency
sem := semaphore.NewWeighted(*jobFlag)
ctx := context.Background()

for _, target := range targets {
// Aquire lock
if err := sem.Acquire(ctx, 1); err != nil {
log.Fatalln("could acquire lock:", err)
log.Fatalln("could not acquire lock:", err)
}

go func(t Target) {
Expand All @@ -107,13 +153,15 @@ Usage: %s [OPTION...] "<COMMAND...>"
}

return args
}(), t.OS)
}(), getImageNameWithSuffix(t.OS, t.Architecture))
commandArgs := fmt.Sprintf(`cd /data && %v`, t.Command)

// Construct the command
cmd := exec.Command("docker", append(strings.Split(dockerArgs, " "), commandArgs)...)

log.Println(cmd)
if !*quietFlag {
log.Println(cmd)
}

// Handle interactivity
if *itFlag {
Expand Down Expand Up @@ -168,3 +216,7 @@ Usage: %s [OPTION...] "<COMMAND...>"
// Wait till all targets have run
sem.Acquire(ctx, *jobFlag)
}

func getImageNameWithSuffix(image, architecture string) string {
return image + "-" + strings.Replace(architecture, "/", "-", -1)
}

0 comments on commit ca29bfd

Please sign in to comment.