Skip to content

refactor(cli)!: Refactor execution state handling and rename module - #5

Merged
ChristianPraiss merged 1 commit into
mainfrom
refactor/improve-command-execution-logic-and-update-module
Jul 28, 2026
Merged

refactor(cli)!: Refactor execution state handling and rename module#5
ChristianPraiss merged 1 commit into
mainfrom
refactor/improve-command-execution-logic-and-update-module

Conversation

@ChristianPraiss

Copy link
Copy Markdown
Contributor

Summary

  • Join a container's entries into a single set -e shell script so cd/export/etc. persist across chained commands, while preserving fail-fast behavior
  • Rename module from devops-parallel-runner to devops-cli across go.mod, README.md, and .golangci.yml (breaking change)
  • Add a new reinstall command that downloads and installs the latest release binary for the current platform

Test plan

  • go test ./...
  • devops reinstall on macOS (arm64/amd64) and verify the binary is replaced
  • Run a module command with multiple chained entries and confirm cd/export state carries over and a failing entry stops the rest

Copilot AI review requested due to automatic review settings July 28, 2026 13:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors how per-container command entries are executed so shell state (e.g., cd, export) persists across chained entries, renames the Go module to github.com/convidera/devops-cli (breaking change), and introduces a devops reinstall command to self-update by downloading the latest release binary.

Changes:

  • Combine per-container entries into a single sh -c script with set -e to preserve shell state and stop on first failure.
  • Rename module/import paths and documentation references from devops-parallel-runner to devops-cli.
  • Add a reinstall command that downloads and replaces the current executable with the latest release asset.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
exec.go Runs all entries for a container in one shell invocation via joinEntries() to preserve shell state and fail-fast behavior.
exec_test.go Adds tests verifying shell state carryover and that failures stop subsequent entries.
reinstall.go Implements devops reinstall to download the latest release asset and replace the current binary.
main.go Wires the new reinstall command into CLI dispatch and help output.
README.md Updates install instructions for renamed repo/module and documents the new execution semantics and reinstall command.
go.mod Renames the module path to github.com/convidera/devops-cli.
.golangci.yml Updates goimports local prefix to the new module path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread exec.go
Comment on lines 20 to +24
for container, entries := range containers {
fmt.Printf("Running commands for: %s\n", container)
for _, entry := range entries {
fmt.Printf("Executing: %s\n", entry.Script)
if err := runScript(container, entry.Script, extraArgs); err != nil {
return fmt.Errorf("[%s/%s] command failed: %w", m.Name, container, err)
}
}
Comment thread reinstall.go
Comment on lines +3 to +10
import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"runtime"
)
Comment thread reinstall.go Outdated
Comment on lines +78 to +83
func downloadBinary(url string) ([]byte, error) {
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("downloading release: %w", err)
}
defer resp.Body.Close()
Comment thread reinstall.go
Comment on lines +14 to +18
// runReinstall downloads the latest release binary for the current platform
// and replaces the currently running executable with it.
func runReinstall() int {
asset, ok := releaseAsset(runtime.GOOS, runtime.GOARCH)
if !ok {
This major refactor updates how commands are executed to reliably share state across multiple chained scripts within a single container context. We now join individual entries into atomic shell blocks, prefixed by 'set -e', ensuring environmental changes (like `cd` or `export`) persist, and guaranteeing fail-fast behavior upon error.

Additionally, this commit addresses the necessary project module name change: devops-parallel-runner is renamed to devops-cli across go.mod, README.md, and .golangci.yml. Please note that this renaming constitutes a breaking change.

Finally, a new 'reinstall' command handler has been introduced for enhanced operational control.
Copilot AI review requested due to automatic review settings July 28, 2026 13:34
@ChristianPraiss
ChristianPraiss force-pushed the refactor/improve-command-execution-logic-and-update-module branch from 25fca0e to 48310d0 Compare July 28, 2026 13:34
@ChristianPraiss
ChristianPraiss merged commit aabd735 into main Jul 28, 2026
3 checks passed
@ChristianPraiss
ChristianPraiss deleted the refactor/improve-command-execution-logic-and-update-module branch July 28, 2026 13:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

reinstall.go:90

  • downloadBinary uses http.Get with the default client (no timeout) and io.ReadAll with no size limit. This can hang indefinitely on network issues and can allocate unbounded memory if the response is unexpectedly large.
func downloadBinary(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("downloading release: %w", err)
	}
	defer func() { _ = resp.Body.Close() }()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("downloading release: unexpected status %s", resp.Status)
	}

	data, err := io.ReadAll(resp.Body)
	if err != nil {

exec.go:23

  • The loop logs each entry as "Executing" before the combined script actually runs. If an early entry fails, later entries will have been printed as executed even though they never ran. Consider changing the wording to avoid misleading output (or emit the per-entry log lines from inside the generated script).
	for container, entries := range containers {
		fmt.Printf("Running commands for: %s\n", container)
		for _, entry := range entries {
			fmt.Printf("Executing: %s\n", entry.Script)
		}

reinstall.go:31

  • The new reinstall flow is untested. Since the repo runs go test ./... in CI, adding unit tests (e.g., for releaseAsset mapping and download/HTTP error handling via httptest) would help prevent regressions without needing real GitHub network calls.
func runReinstall() int {
	asset, ok := releaseAsset(runtime.GOOS, runtime.GOARCH)
	if !ok {
		fmt.Fprintf(os.Stderr, "error: no release binary available for %s/%s\n", runtime.GOOS, runtime.GOARCH)
		return 1
	}

	target := selfPath()
	url := releaseBaseURL + "/" + asset

	fmt.Printf("Downloading %s...\n", url)
	data, err := downloadBinary(url)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		return 1
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants