Skip to content

OPRT2 skeleton - #407

Merged
fheinecke merged 5 commits into
mainfrom
fred/oprt2-3
Oct 21, 2025
Merged

OPRT2 skeleton#407
fheinecke merged 5 commits into
mainfrom
fred/oprt2-3

Conversation

@fheinecke

@fheinecke fheinecke commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Skeleton of #400. Most of the concrete implementations have been removed. This should show the general program flow. This is based on #403, but I'll change the base branch after that merges.

About one third (~220 lines) of this is license headers.

@fheinecke
fheinecke requested a review from a team as a code owner September 30, 2025 21:23
@socket-security

socket-security Bot commented Sep 30, 2025

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedgolang.org/​x/​sync@​v0.17.099100100100100

View full report

Comment thread tools/oprt2/cmd/oprt2/main.go Outdated
Comment thread tools/oprt2/cmd/oprt2/main.go Outdated
cancel()
}

err = errors.Join(append([]error{err}, errs...)...)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The named return value with assignments in defers gets a little tough to reason about.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This error needs to be caught and handled (returned to user). What can I do to make this more clear?

Comment thread tools/oprt2/cmd/oprt2/main.go Outdated
Comment thread tools/oprt2/cmd/oprt2/main.go Outdated
Comment on lines +19 to +33
type Authenticator struct {
// Not implemented
}
type PackageManager struct {
// Not implemented
}

type Attune struct {
Authentication Authenticator
ParallelUploadLimit uint
}

type Logger struct {
// Not implemented
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These structs seem like they "do things" (sorry for lack of a better term).

I'd expect types in a config package to be plain-old data that describes configuration.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agree with this, these seem misplaced - unless they are supposed to represent configuration structs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

unless they are supposed to represent configuration structs.

They are. The previous PR demonstrated this. These are intended to map to a config file exactly.


// ParseOPRT2ConfigFile loads the config file into a new config struct and returns it.
// Validation and defaults are handled in accordance to the `jsonschema` struct tags.
func ParseOPRT2ConfigFile(configFilePath string) (*OPRT2, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the organization of these packages should be inverted to keep related code together.

Right now this config package is a bit of a dumping ground for separate functionality (logging, authenticating with Attune, parsing files, dealing with package managers).

What's more idiomatic is to create packages based on their functionality (for example, we'd have attune.Authenticator instead of config.AttuneAuthenticator).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Glad to take this approach if you like, but this will couple config file types (including the overall config file structure) to the business logic. The current approach is designed to make the config fit the business logic, but inverting this will switch this so that the business logic packages needs to fit the config.

For some additional context, this tool was written with the intent for the business logic pieces to eventually be called as a library via another program. This was one of the explicit requirements provided to me and reiterated while working on this.

Which would you prefer?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agree with Zac, I think my comment above on the loader.go is basically trying to convey the same.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've moved all the other functions out of the package, but I'm planning on leaving the config file parsing functions here unless there is a compelling reason not to. The structs within this package match 1:1 exactly with config file objects, so IMO this is an appropriate place to house generating instances of these config structs from the config file.

Comment thread tools/oprt2/pkg/packagemanager/packagemanager.go Outdated
@fheinecke
fheinecke requested a review from zmb3 October 14, 2025 16:18
Comment thread tools/oprt2/pkg/logging/context.go Outdated
Comment thread tools/oprt2/pkg/filemanager/filemanager.go
Comment thread tools/oprt2/pkg/filemanager/filemanager.go Outdated

// Hook defines function(s) that should be called during different stages
// of a command execution's lifecycle.
type Hook interface {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this an abstraction that's really needed? How are you planning to use it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is this an abstraction that's really needed?

Yes, or there will be significant coupling and complexity when building commands based on configuration provided.

Here are examples of how this will be used:

The alternative is coupling all of this logic together.

Comment thread tools/oprt2/pkg/packagemanager/packagemanager.go Outdated
packageManagers, closablePackageManagers, err := config.GetPackageManagers(ctx, c.PackageManagers, authenticator)
// Cleanup must occur for all created package managers even if an error is returned. This ensures that if some are
// created but some fail, the ones that were created don't leak.
defer func() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Similar to my suggestion above - can we return appropriate cleanup method and just defer it here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The code is already doing as close to this as can be achieved - see above comment

)

// Provider provides a certificate for client authentication.
type Provider interface {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What are the providers you're expecting to implement?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Local filesystem (PEM x509 certs files on disk) and certs via tbot workload identity (see here)


// buildCommandDebugString builds a textual version of cmd for debug logging.
// This should never be directly executed.
func buildCommandDebugString(cmd *exec.Cmd) string {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Something to consider - can the command ever include sensitive info in it that should not be logged?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Absolutely it can, but I can't feasibly guess what this will be or where it will come from. Logging sensitive information would require all of the below:

  • Debug logging enabled
  • Non-local/untrusted environment (e.g. pipelines)
  • A command with credentials or other sensitive values

IMO this is reasonable for debugging for now.

Comment thread tools/oprt2/pkg/config/loader.go Outdated

// ParseOPRT2ConfigFile loads the config file into a new config struct and returns it.
// Validation and defaults are handled in accordance to the `jsonschema` struct tags.
func ParseOPRT2ConfigFile(configFilePath string) (*OPRT2, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agree with Zac, I think my comment above on the loader.go is basically trying to convey the same.

@fheinecke
fheinecke changed the base branch from fred/oprt2-2 to main October 16, 2025 18:43
@fheinecke
fheinecke requested a review from r0mant October 17, 2025 21:01

@r0mant r0mant left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks reasonable to me now, just a couple leftover comments.

Comment thread tools/oprt2/pkg/commandrunner/runner.go
Comment thread tools/oprt2/pkg/commandrunner/runner.go Outdated
Comment thread tools/oprt2/pkg/commandrunner/runner.go Outdated
Comment thread tools/oprt2/pkg/config/config.go Outdated
@fheinecke
fheinecke merged commit 1334a4f into main Oct 21, 2025
9 checks passed
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.

3 participants