Skip to content

Commit

Permalink
Add version compatibility checking (#79)
Browse files Browse the repository at this point in the history
* Upgrade dependencies

* Update outdated terms in `README.md`

* Display pallet's configured path & readme file when they're provided

* Remove redundant newline after printing pallet readme

* Fix an outdated CLI arg in `README.md`

* Discuss reasoning for Forklift's current governance model in `README.md`

* Automatically detect tool version when possible

* Add version compatibility checks between pallets & the cli tool

* Rename some method receivers

* Add Forklift version compatibility checks with pallet requirements
  • Loading branch information
ethanjli authored Oct 18, 2023
1 parent ace825d commit b7f93c8
Show file tree
Hide file tree
Showing 29 changed files with 848 additions and 516 deletions.
2 changes: 2 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ builds:
- id: forklift
main: ./cmd/forklift
binary: forklift
ldflags:
- -s -w -X main.buildVersion={{.Version}} -X main.buildCommit={{.Commit}} -X main.buildCommitTimestamp={{.CommitTimestamp}} -X main.buildSummary={{.Summary}} -X main.builtBy=goreleaser
env:
- CGO_ENABLED=0
targets:
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- The `forklift-pallet.yml` file can now optionally specify a README file and a pallet path.
- The `forklift-pallet.yml` file can now optionally specify a README file and a pallet path. When specified, those fields are displayed by the `plt show` and `dev plt show` commands.
- The `.deploy.yml` files now have a `disabled` boolean flag which specifies whether that deployment definition should be ignored (so that it is excluded from `plt plan`, `plt check`, and `plt apply` commands).

### Changed

- The `forklift-repository.yml` and `forklift-pallet.yml` now have a `forklift-version` field which indicates that the repository/pallet was written assuming the semantics of a given version of Forklift, and which sets the minimum version of Forklift required to use the repository/pallet. The Forklift version of a pallet cannot be less than the Forklift version of any repo required by the pallet. The Forklift tool also checks version compatibility - an older version of the Forklift tool is incompatible with repositories/pallets with newer Forklift versions, and the Forklift tool is also sets the minimum Forklift version of any repository/pallet it is compatible with (so for example v0.4.0 of the Forklift tool is incompatible with any repositories/pallets with Forklift version below v0.4.0, due to other breaking changes made for Forklift v0.4.0).
- (Breaking change) The `forklift-version-lock.yml` file now requires a `type` field which specifies whether the version lock is to be interpreted as a tagged version or as a pseudoversion. The `commit` and `timestamp` fields are now required for all types, instead of being used to determine whether the version lock is for a tagged version or a pseudoversion.

### Fixed
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,17 @@ diff: ## git diff
RES=$$(git status --porcelain) ; if [ -n "$$RES" ]; then echo $$RES && exit 1 ; fi

.PHONY: build
build: ## Use goreleaser-cross (due to macOS CGo requirement) to run goreleaser --snapshot --skip-publish --clean
build: ## Use goreleaser-cross (due to macOS CGo requirement) to run goreleaser --snapshot --skip=publish --clean
build: install
$(call print-target)
goreleaser --snapshot --skip-publish --clean
goreleaser --snapshot --skip=publish --clean
# docker run \
# --rm \
# -v /var/run/docker.sock:/var/run/docker.sock \
# -v `pwd`:/go/src/$(PACKAGE_NAME) \
# -w /go/src/$(PACKAGE_NAME) \
# ghcr.io/goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
# --snapshot --skip-publish --clean
# --snapshot --skip=publish --clean

.PHONY: release
release: ## Use goreleaser-cross (due to macOS CGo requirement) to run goreleaser --clean
Expand Down
44 changes: 22 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Forklift is guided by the following values for infrastructural software in the P
- Thoughtfulness: Its design must be rigorous, deliberate, and considerate of how it will impact people. We must not commit to new features or changes in system behavior until we thoroughly understand their consequences.
- Transparency: Its architecture and behavior must be sufficiently simple and easy to observe, fully explain, fully understand, troubleshoot, and learn from.

Currently, development of Forklift prioritizes the needs of the PlanktoScope community; decisions are made by the PlanktoScope software's maintainer in consultation with the PlanktoScope community in meetings open to the entire community.
Currently, development of Forklift prioritizes the needs of the PlanktoScope community; decisions are made by the PlanktoScope software's maintainer as a "benevolent dictator"/"mad scientist" in consultation with the PlanktoScope community in online meetings and discussion channels open to the entire community. Because Forklift is still an experimental tool and is only used for the PlanktoScope software, governance of the github.com/PlanktoScope/forklift repository will remain in this benevolent-dictatorship model in order to ensure that the Forklift system develops in a cohesive way consistent with the values listed above and with the PlanktoScope community's use-case for Forklift. We encourage anyone who is interested in Forklift to fork this repository for experimentation and/or to [start discussions on GitHub](https://github.com/PlanktoScope/forklift/discussions/new/choose), though we can't make any guarantees about the stability of any APIs or about our capacity to address any external code contributions or feature requests.

### Architecture

Expand All @@ -52,66 +52,66 @@ tar -xzf forklift_{version number}_{os}_{cpu architecture}.tar.gz forklift

Then you may need to move the forklift binary into a directory in your system path, or you can just run the forklift binary in your current directory (in which case you should replace `forklift` with `./forklift` in the commands listed below), or you can just run the forklift binary by its absolute/relative path (in which case you should replace `forklift` with the absolute/relative path of the binary in the commands listed below).

### Deploy a published environment
### Deploy a published pallet

Once you have forklift, you will need to clone a Pallet environment to your local environment. For example, you can clone the latest unstable version (on the `edge` branch) of the [`github.com/PlanktoScope/pallets-env`](https://github.com/PlanktoScope/pallets-env) environment using the command:
Once you have forklift, you will need to clone a pallet to your Docker host. For example, you can clone the latest unstable version (on the `edge` branch) of the [`github.com/PlanktoScope/pallet-standard`](https://github.com/PlanktoScope/pallet-standard) pallet using the command:
```
forklift env clone github.com/PlanktoScope/pallets-env@edge
forklift plt clone github.com/PlanktoScope/pallet-standard@edge
```

Then you will need to download the Pallet repositories specified by your local environment into your local cache, so that you can deploy packages provided by those repositories. You can download the necessary repositories using the command:
Then you will need to download the Forklift repositories specified by your local pallet into your local cache, so that you can deploy packages provided by those repositories according to the pallet's configuration. You can download the necessary repositories using the command:
```
forklift env cache-repo
forklift plt cache-repo
```

Then you will need to apply the package deployments as configured by your local environment, into your Docker Swarm. You can apply the deployments using the command (note that you need `sudo -E` unless you are running the Docker in [rootless mode](https://docs.docker.com/engine/security/rootless/) or your user is in [the `docker` group](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)):
Then you will need to apply the package deployments as configured by your local pallet, into your Docker Swarm. You can apply the deployments using the command (note that you need `sudo -E` unless you are running the Docker in [rootless mode](https://docs.docker.com/engine/security/rootless/) or your user is in [the `docker` group](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)):
```
sudo -E forklift env apply
sudo -E forklift plt apply
```

### Work on a development environment
### Work on a development pallet

First, you will need to make/download a Pallet environment somewhere on your local file system. For example, you can clone the latest unstable version (on the `edge` branch) of the [`github.com/PlanktoScope/pallets-env`](https://github.com/PlanktoScope/pallets-env) environment using the command:
First, you will need to make/download a pallet somewhere on your local file system. For example, you can clone the latest unstable version (on the `edge` branch) of the [`github.com/PlanktoScope/pallet-standard`](https://github.com/PlanktoScope/pallet-standard) pallet using the command:

```
git clone https://github.com/PlanktoScope/pallets-env
git clone https://github.com/PlanktoScope/pallet-standard
```

Then you will need to download/install forklift (see instructions in the "Download/install forklift" section above). Once you have forklift, you can run commands using the `dev env` subcommand; if forklift is in your system path, you can simply run commands within the directory containing your development environment, or any subdirectory of it. For example, if your development environment is at `/home/pi/dev/pallets-env`, you can run the following commands to see some information about your development environment:
Then you will need to download/install forklift (see instructions in the ["Download/install forklift"](#downloadinstall-forklift) section above). Once you have forklift, you can run commands using the `dev plt` subcommand; if forklift is in your system path, you can simply run commands within the directory containing your development pallet, or any subdirectory of it. For example, if your development pallet is at `/home/pi/dev/pallet-standard`, you can run the following commands to see some information about your development pallet:

```
cd /home/pi/dev/pallets-env
forklift dev env show
cd /home/pi/dev/pallet-standard
forklift dev plt show
```

You can also run the command from anywhere else on your filesystem by specifying the path of your development environment. For example, if your forklift binary is in `/home/pi`, you can run any the following sets of commands to see the same information about your development environment:
You can also run the command from anywhere else on your filesystem by specifying the path of your development pallet. For example, if your forklift binary is in `/home/pi`, you can run any the following sets of commands to see the same information about your development pallet:

```
cd /home/pi/
./forklift dev --cwd ./dev/pallets-env env show
./forklift dev --cwd ./dev/pallet-standard plt show
```

```
cd /etc/
/home/pi/forklift dev --cwd /home/pi/dev/pallets-env env show
/home/pi/forklift dev --cwd /home/pi/dev/pallet-standard plt show
```

You can also use the `forklift dev env add-repo` command to add additional Pallet repositories to your development environment, and to change the versions of Pallet repositories already added to your development environment.
You can also use the `forklift dev plt add-repo` command to add additional Forklift repositories to your development pallet, and to change the versions of Forklift repositories already added to your development pallet.

You can also run commands like `forklift dev env cache-repo` and `sudo -E forklift dev env apply` (with appropriate values in the `--cwd` flag if necessary) to download the Pallet repositories specified by your development environment into your local cache and deploy the packages provided by those repositories according to the configuration in your development environment. This is useful if, for example, you want to make some experimental changes to your development environment and test them on your local machine before committing and pushing those changes onto GitHub.
You can also run commands like `forklift dev plt cache-repo` and `sudo -E forklift dev plt apply` (with appropriate values in the `--cwd` flag if necessary) to download the Forklift repositories specified by your development pallet into your local cache and deploy the packages provided by those repositories according to the configuration in your development pallet. This is useful if, for example, you want to make some experimental changes to your development pallet and test them on your local machine before committing and pushing those changes onto GitHub.

Finally, you can run the `forklift dev env check` command to check the environment for any problems, such as resource constraint violations.
Finally, you can run the `forklift dev plt check` command to check the pallet for any problems, such as resource constraint violations.

You can also override cached repos with repos from your filesystem by specifying one or more directories containing one or more repos; then the repos in those directories will be used instead of the respective repos from the cache, regardless of repo version. For example:

```
cd /home/pi/
/home/pi/forklift dev --cwd /home/pi/dev/pallets-env env --repo /home/pi/forklift/dev/pallets check
/home/pi/forklift dev --cwd /home/pi/dev/pallet-standard plt --repos /home/pi/forklift/dev/pallets check
```

## Similar projects

The following projects solve related problems with containers, though they make different trade-offs compared to Forklift and Pallets:
The following projects solve related problems with containers, though they make different trade-offs compared to Forklift:

- poco enables Git-based management of Docker Compose projects and collections (*catalogs*) of projects and repositories and provides some similar functionalities to forklift: https://github.com/shiwaforce/poco
- Terraform (an inspiration for this project) has a Docker Provider which enables declarative management of Docker hosts and Docker Swarms from a Terraform configuration: https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs
Expand Down
3 changes: 3 additions & 0 deletions cmd/forklift/cache/repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func printCachedRepo(indent int, cache *forklift.FSRepoCache, repo *core.FSRepo)
fcli.IndentedPrintf(indent, "Cached repo: %s\n", repo.Path())
indent++

fcli.IndentedPrintf(indent, "Forklift version: %s\n", repo.Def.ForkliftVersion)
fmt.Println()

fcli.IndentedPrintf(indent, "Version: %s\n", repo.Version)
fcli.IndentedPrintf(indent, "Path in cache: %s\n", core.GetSubdirPath(cache, repo.FS.Path()))
fcli.IndentedPrintf(indent, "Description: %s\n", repo.Def.Repo.Description)
Expand Down
30 changes: 16 additions & 14 deletions cmd/forklift/dev/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@ import (

var defaultWorkingDir, _ = os.Getwd()

var Cmd = &cli.Command{
Name: "dev",
Aliases: []string{"development"},
Usage: "Facilitates development and maintenance in the current working directory",
Subcommands: []*cli.Command{
plt.Cmd,
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "cwd",
Value: defaultWorkingDir,
Usage: "Path of the current working directory",
EnvVars: []string{"FORKLIFT_CWD"},
func MakeCmd(toolVersion, minVersion string) *cli.Command {
return &cli.Command{
Name: "dev",
Aliases: []string{"development"},
Usage: "Facilitates development and maintenance in the current working directory",
Subcommands: []*cli.Command{
plt.MakeCmd(toolVersion, minVersion),
},
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "cwd",
Value: defaultWorkingDir,
Usage: "Path of the current working directory",
EnvVars: []string{"FORKLIFT_CWD"},
},
},
}
}
Loading

0 comments on commit b7f93c8

Please sign in to comment.