Azure / azure-dev

A developer CLI that reduces the time it takes for you to get started on Azure. The Azure Developer CLI (azd) provides a set of developer-friendly commands that map to key stages in your workflow - code, build, deploy, monitor, repeat.
https://aka.ms/azd
MIT License
402 stars 195 forks source link

Improve cli project layout #1233

Open weikanglim opened 1 year ago

weikanglim commented 1 year ago

As our codebase has involved with increasing complexity and functionality, we need a well-defined project layout that is able to organize things efficiently and with hopefully little confusion. I'd like the project layout to be opinionated as a result to avoid confusion.

Problem

The key problem that I've noticed is how to cleanly separate code for a given domain/subsystem such as auth, infra, environment. Taking a look at the environment package, we can see the desire for the following separation:

Proposal

After reviewing a few different examples, I've opted for the non-official standard project layout for Go: https://github.com/golang-standards/project-layout. The only caveat is instead of internal/app/azd, I'm opting for internal/azd to avoid the extra directory structure.

cmd/         // entrypoint for applications (CLIs/services) built in the repository
    azd/
        main.go
internal/
   azd/         // Application-layer logic for azd CLI. Only surfaced through wire by actions/commands
        auth/
        environment/
        cmd/         //  entry-point for all azd commands
   pkg/         // Internal library libraries to be consumed application wide.
        auth/         // Application shared library
        environment/
        azsdk/
        config/
pkg/         // Packages for external distribution. Unable to depend on internal packages
   cmdsubst/
   contracts/
   exec/    
   environment/ 
   osversion/
   password/
tools/
   azddocgen/
        main.go

Example

Let's say we're building a new subsystem for auth, that will be used in azd login and azd logout. We would do the following:

We largely avoid package naming collision, since internal/azd/auth is only imported by cmd, whereas if internal/pkg/auth is imported by all other packages. The only time where collisions would happen is inside cmd, that could be reusing both the internal/azd/auth and internal/pkg/auth. In these case, we should aliasazd/authintoazdauth`.

ellismg commented 1 year ago

I love this idea.

One small note - to start with, I would prefer if we kept all our packages, with the exception of the "contracts" package inside of internal/pkg. The contracts package should be external because it's something we want to contractually guarantee about azd but I think the rest of the packages should remain internal. I don't think we want to give the impressions these are general purpose packages that are useful outside of the context of azd or that might be covered by anything that looks like the Go Compatibility Promise.