Skip to content

Also snag interpreter#52

Merged
MusicalNinjaDad merged 16 commits into
mainfrom
interpreter_missing
Oct 25, 2025
Merged

Also snag interpreter#52
MusicalNinjaDad merged 16 commits into
mainfrom
interpreter_missing

Conversation

@MusicalNinjaDad

@MusicalNinjaDad MusicalNinjaDad commented Oct 25, 2025

Copy link
Copy Markdown
Owner

Fixes #49

Summary by Sourcery

Enable snaggle to include the interpreter binary when present, adjust tests to verify interpreter linking, and enhance CI with targeted triggers and a Docker-based test workflow

New Features:

  • Support linking an ELF interpreter during the snag process
  • Add a Docker-based CI workflow to validate snaggle usage in container builds

Enhancements:

  • Update CLI and core tests to expect interpreter linkage for dynamic executables

CI:

  • Restrict CI triggers to Go source files and workflow config changes
  • Add a Test usage in Docker build workflow in GitHub Actions

Tests:

  • Introduce test.Dockerfile and a Docker-based test job to run snapped binaries

@sourcery-ai

sourcery-ai Bot commented Oct 25, 2025

Copy link
Copy Markdown

Reviewer's Guide

This PR extends Snaggle’s behavior to link ELF interpreters, updates tests to account for interpreter linking, refines CI triggers, and introduces a Docker-based workflow for integration testing.

Class diagram for updated Snaggle linking logic

classDiagram
    class File {
        +string Interpreter
        +[]string Dependencies
    }
    class Snaggle {
        +Snaggle(path string, root string) error
    }
    class errgroup_Group {
        +Go(func() error)
    }
    File <.. Snaggle : uses
    errgroup_Group <.. Snaggle : uses
    Snaggle o-- File : reads
    Snaggle o-- errgroup_Group : manages link tasks
Loading

File-Level Changes

Change Details Files
Support linking ELF interpreter
  • Added conditional block to enqueue interpreter in errgroup for linking
  • Inserted TODO about making interpreter linking safer
snaggle.go
Update tests to validate interpreter linking
  • Appended interpreter path to expected outputs when binary is dynamic and not a library
  • Introduced TODO noting test cases need cleanup
snaggle/cli_test.go
snaggle_test.go
Restrict CI workflow triggers to relevant files
  • Added path filters in CI config for .go files and ci.yml
.github/workflows/ci.yml
Introduce Docker-based integration test workflow
  • Added a new CI workflow defining Docker build and run steps
  • Provided a Dockerfile for runtime testing
.github/workflows/test_docker.yml
test.Dockerfile

Assessment against linked issues

Issue Objective Addressed Explanation
#49 Ensure that the snaggle tool copies the interpreter (e.g., /lib64/ld-linux) required by dynamic executables into the runtime environment.
#49 Update tests to verify that the interpreter is copied and available in the runtime environment.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot 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.

Hey there - I've reviewed your changes - here's some feedback:

  • Rather than inlining interpreter linking in two places, move that logic into your test case definitions to avoid duplication and make the tests cleaner.
  • Before merging, address the “make linking interpreter safer” TODO by adding proper validation or abstraction around interpreter path handling.
  • The new CI and docker workflows introduce a lot of duplication—consider consolidating build steps or merging them into a single workflow for maintainability.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Rather than inlining interpreter linking in two places, move that logic into your test case definitions to avoid duplication and make the tests cleaner.
- Before merging, address the “make linking interpreter safer” TODO by adding proper validation or abstraction around interpreter path handling.
- The new CI and docker workflows introduce a lot of duplication—consider consolidating build steps or merging them into a single workflow for maintainability.

## Individual Comments

### Comment 1
<location> `snaggle/cli_test.go:73-74` </location>
<code_context>
 			expectedOut := make([]string, 0, 1+len(tc.ExpectedElf.Dependencies))
 			expectedOut = append(expectedOut, tc.ExpectedElf.Path+" -> "+binPath)
+			// ugly - should be in the tc - needs a tidy
+			if tc.ExpectedElf.IsDyn() && !tc.ExpectedElf.IsLib() {
+				expectedOut = append(expectedOut, tc.ExpectedElf.Interpreter+" -> "+filepath.Join(tmp, P_ld_linux))
+			}
 			var libCopies []string
</code_context>

<issue_to_address>
**suggestion (testing):** No test for error conditions when interpreter linking fails.

Add a test case with an invalid interpreter path or failed linking to verify proper error handling.

Suggested implementation:

```golang
			binPath := filepath.Join(tmp, "bin", filepath.Base(tc.ExpectedElf.Name))
			expectedOut := make([]string, 0, 1+len(tc.ExpectedElf.Dependencies))
			expectedOut = append(expectedOut, tc.ExpectedElf.Path+" -> "+binPath)
			// ugly - should be in the tc - needs a tidy
			if tc.ExpectedElf.IsDyn() && !tc.ExpectedElf.IsLib() {
				expectedOut = append(expectedOut, tc.ExpectedElf.Interpreter+" -> "+filepath.Join(tmp, P_ld_linux))
			}
			var libCopies []string
			for _, lib := range tc.ExpectedElf.Dependencies {
				copy := filepath.Join(tmp, "lib64", filepath.Base(lib))
			}

			// Test error condition: interpreter linking fails
			t.Run("interpreter linking fails", func(t *testing.T) {
				invalidElf := tc.ExpectedElf
				invalidElf.Interpreter = "/invalid/interpreter/path"
				invalidElfDyn := invalidElf.IsDyn() && !invalidElf.IsLib()
				if invalidElfDyn {
					// Simulate the linking function, expecting an error
					err := linkInterpreter(invalidElf.Interpreter, filepath.Join(tmp, P_ld_linux))
					if err == nil {
						t.Errorf("expected error when linking invalid interpreter, got nil")
					}
				}
			})

```

- You must implement or mock the `linkInterpreter` function to simulate interpreter linking and error return for invalid paths.
- If your test table (`tc`) is outside this snippet, you may want to add a dedicated test case to it for more coverage.
- Adjust the error check to match your actual error handling logic if it differs.
</issue_to_address>

### Comment 2
<location> `snaggle_test.go:36-37` </location>
<code_context>
 			expectedOut := make([]string, 0, 1+len(tc.ExpectedElf.Dependencies))
 			expectedOut = append(expectedOut, tc.ExpectedElf.Path+" -> "+binPath)
+			// ugly - should be in the tc - needs a tidy
+			if tc.ExpectedElf.IsDyn() && !tc.ExpectedElf.IsLib() {
+				expectedOut = append(expectedOut, tc.ExpectedElf.Interpreter+" -> "+filepath.Join(tmp, P_ld_linux))
+			}
 			var libCopies []string
</code_context>

<issue_to_address>
**suggestion (testing):** Missing test for interpreter linking error scenarios.

Add a test case for scenarios where the interpreter is missing or fails to link, ensuring errors are handled and reported correctly.

Suggested implementation:

```golang
			binPath := filepath.Join(tmp, "bin", filepath.Base(tc.ExpectedElf.Name))
			expectedOut := make([]string, 0, 1+len(tc.ExpectedElf.Dependencies))
			expectedOut = append(expectedOut, tc.ExpectedElf.Path+" -> "+binPath)
			// TODO: #51 ugly - should be in the tc - needs a tidy
			if tc.ExpectedElf.IsDyn() && !tc.ExpectedElf.IsLib() {
				expectedOut = append(expectedOut, tc.ExpectedElf.Interpreter+" -> "+filepath.Join(tmp, P_ld_linux))
			}
			// Test interpreter missing/failure scenario
			if tc.ExpectedElf.Interpreter == "" || tc.ExpectedElf.Interpreter == "missing" {
				expectedErr := "interpreter missing or failed to link"
				if err == nil || !strings.Contains(err.Error(), expectedErr) {
					t.Errorf("expected error for missing interpreter, got: %v", err)
				}
			}
			var libCopies []string
			for _, lib := range tc.ExpectedElf.Dependencies {
				copy := filepath.Join(tmp, "lib64", filepath.Base(lib))

```

You will also need to:
1. Add a test case to your test table (where `tc` is defined) with `ExpectedElf.Interpreter` set to `""` or `"missing"` to trigger this scenario.
2. Ensure that the test setup simulates the missing interpreter (e.g., by not creating the interpreter file or by setting the field appropriately).
3. Make sure the test logic sets `err` when the interpreter is missing, so the error assertion works.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread snaggle/cli_test.go
Comment thread snaggle_test.go
@codecov

codecov Bot commented Oct 25, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.13%. Comparing base (2b3dc8a) to head (3408722).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #52      +/-   ##
==========================================
+ Coverage   74.00%   74.13%   +0.12%     
==========================================
  Files           5        5              
  Lines         404      406       +2     
==========================================
+ Hits          299      301       +2     
  Misses         71       71              
  Partials       34       34              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@MusicalNinjaDad MusicalNinjaDad merged commit cdd04ab into main Oct 25, 2025
8 checks passed
@MusicalNinjaDad MusicalNinjaDad deleted the interpreter_missing branch October 25, 2025 19:55
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.

docker runtime built with snaggle fails: exec /bin/tini: no such file or directory

1 participant