github.com/joshdk/godel@v0.0.0-20170529232908-862138a45aee/docs/Architecture.md (about)

     1  gödel consists of the `godelw` wrapper script, the project configuration files in `godel/config` and the `godel` Go
     2  executable.
     3  
     4  godelw
     5  ------
     6  `godelw` is a bash script that is used as the entry point for gödel. The purpose of the script is to locate and invoke
     7  the real `godel` executable and to provide it with the configuration specified in the current project.
     8  
     9  If the executable exists at the expected location, it is invoked. The `godelw` script is built as part of the
    10  distribution and embeds the checksum of the `godel` executable in its source and verifies that the checksum of the
    11  executable it is invoking matches the checksum stored in its source.
    12  
    13  If the executable does not exist, then the wrapper script gets the URL for the distribution from the
    14  `godel/config/config.properties` file, downloads the distribution from that location (using `wget` or `curl`), verifies
    15  the checksum of the downloaded distribution (if provided), expands the distribution into the expected location and then
    16  invokes it.
    17  
    18  This setup is used so that the `godel` executable itself does not need to be checked in as part of a project.
    19  
    20  The `godelw` script invokes the `godel` executable with the `--wrapper` flag that provides the location of the invoking
    21  wrapper script. This value is used by `godel` to determine the location from which the project configuration should be
    22  loaded. All of the user-provided arguments to `godelw` are passed on directly to `godel`.
    23  
    24  godel
    25  -----
    26  `godel` is a single Go executable. It contains several Go libraries that use [`amalgomate`](https://github.com/palantir/amalgomate)
    27  to combine disparate Go `main` programs into a single library. Thus, `godel` contains and can run as several disparate
    28  Go programs such as `errcheck`, `go-junit-report` and others.
    29  
    30  Many `godel` tasks act as an orchestrator of other sub-tasks. For example, the `check` command uses `okgo` to run
    31  several different checks like `deadcode` and `errcheck`. The nifty thing is that, because `godel` embeds the
    32  functionality of these programs and can run as them, the programs do not need to be separately installed. Instead, when
    33  `godel` needs the functionality of one of these programs, it re-invokes itself as a sub-process with specific arguments
    34  that instruct it to run as a specific sub-program.
    35  
    36  This can be observed by manually invoking `godel` with special syntax:
    37  
    38  ```
    39  ./godelw __check __errcheck --help
    40  Usage of /Users/nmiyake/.godel/dists/godel-0.9.0/bin/darwin-amd64/godel:
    41    -abspath
    42          print absolute paths to files
    43    -asserts
    44          if true, check for ignored type assertion results
    45    -blank
    46          if true, check for errors assigned to blank identifier
    47    -ignore value
    48          comma-separated list of pairs of the form pkg:regex
    49              the regex is used to ignore names within pkg (default "fmt:.*")
    50    -ignorepkg string
    51          comma-separated list of package paths to ignore
    52    -ignoretests
    53          if true, checking of _test.go files is disabled
    54    -tags value
    55          space-separated list of build tags to include
    56    -verbose
    57          produce more verbose logging
    58  ```
    59  
    60  When `godel` is invoked with `__check __errcheck`, it runs in a manner that is identical to running the stand-alone
    61  `errcheck` program. Thus, when `godel` needs the functionality of `errcheck`, it can invoke itself as a subprocess with
    62  these arguments to get the functionality.
    63  
    64  Package scope definition
    65  ------------------------
    66  gödel defines global configuration that is used to specify the scope of the files that it should deal with. Projects
    67  often have certain classes of files that should not be operated on by automated tooling (for example, the `vendor`
    68  directory or generated source directories). The `godel/config/exclude.yml` file is used to define rules for excluding
    69  certain paths from consideration. The `cfgcli` package is used so that all of the tasks (including those defined by
    70  other stand-alone applications) can receive this configuration and thus operate on the same set of files.
    71  
    72  Task encapsulation
    73  ------------------
    74  gödel is composed of many independent tasks. Some of the simple tasks are implemented directly in the gödel project.
    75  However, in order to prevent the project from becoming a single monolithic program, the large pieces of core
    76  functionality are implemented as independent sub-programs that also expose their functionality as a library. For
    77  example, `distgo` handles building products, creating distributions and running publish operations, while `okgo` handles
    78  running all of the code checks.
    79  
    80  Most of the sub-programs define a configuration file from which its configuration is read. The configuration file
    81  typically contains program-specific configuration and an `exclude` object that specifies files and directories that
    82  should be excluded from consideration.
    83  
    84  However, when run as part of `godel`, the `exclude` configuration is typically defined globally in `exclude.yml`.
    85  Requiring every separate sub-program to copy the `exclude` block would be cumbersome and error-prone. In order to deal
    86  with this, sub-programs also accept configuration as a JSON string provided by the `--json` flag and can either combine
    87  the JSON configuration with the file-based one or override the file-based configuration using the values provided in the
    88  JSON. The `github.com/palantir/pkg/cli/cfgcli` provides a common API to do this.
    89  
    90  Task API
    91  --------
    92  Tasks that are implemented as sub-programs use the `github.com/palantir/pkg/cli/cfgcli` package as an API to manage
    93  configuration. Tasks should use declarative file-based configuration. Most tasks have a corresponding configuration file
    94  in `godel/config` -- for example, the `check` task is configured using `godel/config/check.yml`, while the `distgo`
    95  tasks (`build`, `dist`, `publish`, etc.) are configured using `godel/config/dist.yml`.
    96  
    97  When a task is invoked using `godel`, `godel` configures the global variables in the `cfgcli` package to store the
    98  proper values for the configuration file and JSON configuration for the task. The JSON configuration is populated with
    99  the `exclude` contents specified in `godel/config/exclude.yml` so that sub-programs can use the global excludes.