Skip to content

Commit

Permalink
Merge pull request #76 from davidovich/implement-fs
Browse files Browse the repository at this point in the history
Implement fs
  • Loading branch information
davidovich authored Nov 5, 2021
2 parents d6a3c34 + c259051 commit f5d6cb0
Show file tree
Hide file tree
Showing 38 changed files with 386 additions and 350 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ version: 2
jobs:
build:
docker:
- image: circleci/golang:1.15
- image: circleci/golang:1.17
environment:
GO111MODULE=on
steps:
Expand Down
33 changes: 9 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,43 +1,29 @@
SHELL=/bin/bash

HAS_PACKR2 := $(shell command -v packr2)
HAS_GOBIN := $(shell command -v gobin)
HAS_GOCOVERUTIL := $(shell command -v gocoverutil)

ifndef HAS_GOBIN
$(shell GO111MODULE=off go get -u github.com/myitcv/gobin 2>/dev/null)
endif

export GO111MODULE := on

SCAFFOLD_BIN := bin/scaffold
PACKR_FILE := internal/scaffold/scaffold-packr.go
SCAFFOLD_SRCS := $(shell GO111MODULE=on go list -f '{{ $$dir := .Dir}}{{range .GoFiles}}{{ printf "%s/%s\n" $$dir . }}{{end}}' github.com/davidovich/summon/scaffold/...)
COVERAGE_PERCENT_FILE := $(CURDIR)/build/coverage-percent.txt

DOC_REPO_NAME := davidovich.github.io
DOC_REPO := [email protected]:davidovich/$(DOC_REPO_NAME).git
SUMMON_BADGE_JSON_FILE := $(DOC_REPO_NAME)/shields/summon/summon.json

ASSETS := $(shell find internal/templates/scaffold)
ASSETS := $(shell find internal/scaffold/templates/scaffold)

all: $(PACKR_FILE) test $(SCAFFOLD_BIN)
all: test $(SCAFFOLD_BIN)

.PHONY: bin
bin: $(PACKR_FILE) $(SCAFFOLD_BIN)
bin: $(SCAFFOLD_BIN)

.PHONY: $(SCAFFOLD_BIN)
$(SCAFFOLD_BIN): $(PACKR_FILE)
@mkdir -p bin
$(SCAFFOLD_BIN): $(ASSETS) $(SCAFFOLD_SRCS)
go build -o $@ $(@F)/$(@F).go

$(PACKR_FILE): $(ASSETS)
ifndef HAS_PACKR2
gobin github.com/gobuffalo/packr/v2/packr2
endif
cd internal/scaffold && packr2

GO_TESTS := pkg internal cmd
COVERAGE := $(foreach t,$(GO_TESTS),build/coverage/report/$(t))
COVERAGE := build/coverage/report/summon
MERGED_COVERAGE := build/coverage/report/cover.merged.out
HTML_COVERAGE := build/coverage/html/index.html

Expand All @@ -57,7 +43,7 @@ $(COVERAGE_PERCENT_FILE): $(MERGED_COVERAGE)

$(MERGED_COVERAGE): $(COVERAGE)
ifndef HAS_GOCOVERUTIL
gobin github.com/AlekSi/[email protected]
go install github.com/AlekSi/[email protected]
endif
gocoverutil -coverprofile=$@ merge $^

Expand All @@ -67,7 +53,7 @@ $(HTML_COVERAGE): $(MERGED_COVERAGE)

$(COVERAGE):
@mkdir -p $(@D)
go test ./$(@F)/... --cover -coverprofile $@ -v
go test ./... --cover -coverprofile $@ -v

.PHONY: update-coverage-badge
update-coverage-badge: $(COVERAGE_PERCENT_FILE)
Expand All @@ -78,12 +64,11 @@ else
rm -rf /tmp/$(DOC_REPO_NAME)
git -C /tmp clone $(DOC_REPO)
cd /tmp/$(DOC_REPO_NAME) && \
gobin -run github.com/davidovich/summon-example-assets/summon shields.io/coverage.json.gotmpl --json "{\"Coverage\": \"$$(cat $(COVERAGE_PERCENT_FILE))\"}" -o- > /tmp/$(SUMMON_BADGE_JSON_FILE)
go run github.com/davidovich/summon-example-assets@3c2e66d7 shields.io/coverage.json.gotmpl --json "{\"Coverage\": \"$$(cat $(COVERAGE_PERCENT_FILE))\"}" -o- > /tmp/$(SUMMON_BADGE_JSON_FILE)
git -C /tmp/$(DOC_REPO_NAME) diff-index --quiet HEAD || git -C /tmp/$(DOC_REPO_NAME) -c [email protected] -c user.name=automation commit -am "automated coverage commit of $$(cat $(COVERAGE_PERCENT_FILE)) %" || true
git -C /tmp/$(DOC_REPO_NAME) push
endif

.PHONY: clean
clean:
packr2 clean
rm -rf bin build
109 changes: 62 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [How it Works](#how-it-works)
- [Configuration](#configuration)
- [Data repository](#data-repository)
- [Migration from versions prior to v0.13.0](#migration-from-versions-prior-to-v0130)
- [Summon config File](#summon-config-file)
- [Build](#build)
- [Install](#install)
Expand Down Expand Up @@ -45,27 +46,40 @@ state (packed scripts or pinned versions of binaries).

> NOTE: This project is still a WIP and experimental.
To install, you first need to create something to install by populating a [data repository](#Configuration). Then, this data repo is installed by using [gobin](https://github.com/myitcv/gobin) (or go install):
To install, you first need to create something to install by populating a
[data repository](#Configuration). Then, this data repo is installed by using
the `go install` command:

```bash
gobin [your-summon-data-repo]/summon
go install [your-summon-data-repo]/summon@latest
```

Assuming there is a my-team-utility.sh script hosted in the data repo, (see how to [configure](#Configuration) below) you can do things like:
Assuming there is a my-team-utility.sh script hosted in the data repo, (see how
to [configure](#Configuration) below) you can do things like:

```bash
bash $(summon my-team-utility.sh)
```

## How it Works

Summon is a library which is consumed by an asset repository (which, by default, has also the `summon` name). This asset repository, managed by your team, provides the summon executable command (it's main() function is in summon/summon.go).
The library provides the command-line interface, so no coding is necessary in the assert repo.
Summon is a library which is consumed by an asset repository (which, by default,
has also the `summon` name). This asset repository, managed by your team,
provides the summon executable command (it's main() function is in
summon/summon.go). The library provides the command-line interface, so no
coding is necessary in the assert repo.

Summon also provides a boostrapping feature in the scaffold command.

Summon builds upon [packr2](https://github.com/gobuffalo/packr/tree/master/v2) to convert an arbitrary tree of files in go compilable source
which you then bootstrap at destination using standard go get or [gobin](https://github.com/myitcv/gobin). The invoked files are then placed locally and the summoned file path is returned so it can be consumed by other shell operations.
> New in v0.13.0
Summon builds upon the new go 1.16 [embed.FS](https://pkg.go.dev/embed) feature
used to pack assets in a go binary. You then install this at destination using
standard `go install`.

When you invoke this binary with a contained asset path, the invoked files are
placed locally and the summoned file path is returned so it can be consumed by
other shell operations.

## Configuration

Expand All @@ -76,38 +90,49 @@ Use summon's scaffold feature to create a data repository, which will become you
> Scaffolding is new in v0.1.0
```bash
gobin -run github.com/davidovich/summon/scaffold init [module name]
# go run package at a version requires go 1.17 and up
go run github.com/davidovich/summon/scaffold@latest init [module name]
```

> Be sure to change the [module name] part (usually you will use a module path compatible with where you will host the data repo on a code hosting site).
> Be sure to change the [module name] part (usually you will use a module path
> compatible with where you will host the data repo on a code hosting site).
You will then have something resembling this structure:

```bash
.
├── Makefile
├── README.md
├── assets
│ └── summon.config.yaml
├── go.mod
├── go.sum
└── summon
├── assets
│ └── summon.config.yaml
└── summon.go
```

There is an example setup at https://github.com/davidovich/summon-example-assets.

You just need to populate the `assets` directory with your own data.
You just need to populate the `summon/assets` directory with your own data.

The `summon/summon.go` file of the main module is the entry point to the summon
library, and creates the main command executable.

The `summon/` directory is the entry point to the summon library, and creates the main command executable. This directory will also host
[packr2](https://github.com/gobuffalo/packr/tree/master/v2) generated data files which encode asset data into go files.
#### Migration from versions prior to v0.13.0

The v0.13.0 version uses the embed.FS and the `//go:embed assets/*` directive.
Prior versions used to reference the `assets/` dir at the root of the repo.
This means that the data being embeded must now be a sibling of the source
file containing `package main`.

### Summon config File

The `assets/summon.config.yaml` is an (optional) configuration file to customize summon. You can define:
The `summon/assets/summon.config.yaml` is an (optional) configuration file to
customize summon. You can define:

* aliases
* default output-dir
* executables
- aliases
- default output-dir
- executables

> Breaking in v0.11.0: Handles now take an array of params
Expand Down Expand Up @@ -138,9 +163,8 @@ exec:
# ^ handle to script (must be unique). This is what you use
# to invoke the script: `summon run hello`.

gobin -run: # go gettable executables
gobin: [github.com/myitcv/[email protected]]
gohack: [github.com/rogppepe/gohack]
go run: # go gettable executables
gohack: [github.com/rogppepe/gohack@latest]

python -c:
hello-python: [print("hello from python!")]
Expand All @@ -161,7 +185,8 @@ You can invoke executables like so:
summon run gohack ...
```

This will install gohack using `gobin -run` and forward the arguments that you provide.
This will call and run gohack using `go run` and forward the arguments that you
provide.

> New in v0.10.0, summon now allows templating in the invocable section. See
> [Templating](#/templating).
Expand All @@ -170,35 +195,22 @@ This will install gohack using `gobin -run` and forward the arguments that you p

In an empty asset data repository directory:

* First (and once) invoke `go run github.com/davidovich/summon/scaffold init [repo host (module name)]`
- First (and once) invoke `go run github.com/davidovich/summon/scaffold@latest init [repo host (module name)]`
This will create code template similar as above

1. Add assets that need to be shared amongst consumers
2. Use the provided Makefile to invoke the packr2 process: `make`
3. Commit the resulting -packr files so clients can go get the data repo
2. Use the provided Makefile to create the asset executable: `make`
3. Commit the all the files so clients can go get the data repo
4. Tag the repo with semantic version (with the `v`) prefix.
5. Push to remote.
6. Install.
6. On a consumer machine, install.

## Install

Install (using gobin) the asset repo which will become the summon executable.
You have these alternatives:

* change to a directory that does not contain a go.mod. This installs globally:

```bash
cd /tmp
GO111MODULE=on go get [your-go-repo-import]/summon[@wanted-version-or-branch]
cd -
```

* use gobin to install summon in the consuming site:
Install (using `go install`) the asset repo which will become the summon executable.

```bash
GO111MODULE=off go get -u github.com/myitcv/gobin
# install the data repository as summon executable at the site
GOBIN=./ gobin [your-go-repo-import]/summon[@wanted-version-or-branch]
go install [your-go-repo-module]/summon@latest
```

## Use-cases
Expand All @@ -212,12 +224,13 @@ summon returns the path ot where the resource was instantiated:
include $(shell summon version.mk)
```

By default, summon will put summoned scripts at the `.summoned/` directory at root of the current directory.
By default, summon will put summoned scripts at the `.summoned/` directory at
the root of the current directory. This can be changed with the `-o` flag.

### Templating

Files in the asset directory can contain go templates. This allows applying
customization using json data.
customization using json data, just before rendering the file (and its contents).

> New in v0.3.0, summon now uses the [Sprig templating library](https://github.com/Masterminds/sprig), which provides many useful templating functions.
Expand All @@ -230,21 +243,23 @@ For example, consider this file in a summon asset provider:

With this content:

```bash
```txt
Hello {{ .Name }}!
```

`summon template.file --json '{ "Name": "David" }'`

You will get a summoned `template.file` file with this result:

```bash
```shell
Hello David!
```

> New in v0.2.0, you can summon a whole asset hierarchy by using a directory reference when summoning.
> New in v0.2.0, you can summon a whole asset hierarchy by using a directory
> reference when summoning.
Templates can also be used in the filenames given in the data hierarchy. This can be useful to scaffold simple projects.
Templates can also be used in the filenames given in the data hierarchy. This
can be useful to scaffold simple projects.

```bash
/assets
Expand Down
64 changes: 64 additions & 0 deletions assets/summon.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# this is a sample summon config file
# see https://github.com/davidovich/summon#configuration
version: 1
aliases: {"git-version": "bin/version.sh"}
# outputdir: "overridden_dir"
exec:
bash:
hello-bash: ['{{ summon "hello.sh" }}']

docker run -v {{ env "PWD" }}:/mounted-app alpine ls:
list: [/mounted-app]

go run:
gohack: [github.com/rogpeppe/[email protected]]

docker {{ lower "INFO" }}: # naive example of templating
docker-info:

? docker run -ti --rm -w /{{ env "PWD" | base }}
-v {{ env "PWD" }}:/{{ env "PWD" | base }}
hairyhenderson/figlet
:
figlet: ['hello {{ env "USER" }}']

# echo: # future implementation idea
# - handle: echo
# args: ['echoing: {{ .Message }}']
# env: []

python3 -c:
hello:
- |
import sys
print('pyhon version:'); print(sys.version)
if True:
print()
print(f"hello from python! args: {sys.argv}")
python -c:
hellopy2: [print('hello from python!')]

bash -c:
# small function to setup a temporary GOPATH compatible godoc server inside docker
# see https://github.com/golang/go/issues/26827. This allows serving documentation
# for a go modules enabled project.
godoc:
- |
function _godoc() {
[ ! -f "$(pwd)/go.mod" ] && echo "error: go.mod not found" ||
module=$(awk 'NR==1{print $2}' go.mod) &&
docker run --rm -ti -e "GOPATH=/tmp/go" -p 6060:6060 -v $(pwd):/tmp/go/src/$module golang:1.15 /bin/bash -c "GO111MODULE=on go get golang.org/x/tools/cmd/godoc && echo -e \"\nhttp://localhost:6060/pkg/$module\" && \$(go env GOPATH)/bin/godoc -http=:6060"
unset -f _godoc;
}
_godoc
# kmerge merges a the default kubeconfig with a kubeconfig file passed as argement
# https://github.com/kubernetes/kubernetes/issues/46381#issuecomment-461404505
kmerge:
- |
function kmerge() {
KUBECONFIG=~/.kube/config:$1 kubectl config view --flatten > ~/.kube/mergedkub && mv ~/.kube/mergedkub ~/.kube/config
}
kmerge
5 changes: 1 addition & 4 deletions cmd/completion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ import (
"testing"

"github.com/davidovich/summon/pkg/summon"
"github.com/gobuffalo/packr/v2"
"github.com/stretchr/testify/assert"
)

func TestCompletionCommand(t *testing.T) {
box := packr.New("testCompletion", "testdata/plain")

s, _ := summon.New(box)
s, _ := summon.New(runCmdTestFS)

cmd := newCompletionCmd(s)

Expand Down
Loading

0 comments on commit f5d6cb0

Please sign in to comment.