Skip to content

Commit

Permalink
Merge pull request #17 from josegonzalez/master
Browse files Browse the repository at this point in the history
Release 0.7.0
  • Loading branch information
josegonzalez authored Oct 3, 2019
2 parents e9aefd2 + e299eae commit 66afee7
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 97 deletions.
8 changes: 2 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,13 @@ jobs:
command: |
make build-in-docker
[[ -d build ]] && sudo chown -R circleci:circleci build
- run:
command: |
ls -lah
make store-artifacts
- run: make validate-in-docker
- store_artifacts:
path: /tmp/artifacts
path: build
destination: build
- run:
command: |
if [[ "$CIRCLE_BRANCH" == "release" ]]; then
make release-in-docker
fi
make release-packagecloud-in-docker
make release-packagecloud-in-docker || true
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ validation/*

# .env files
.env*

*Procfile
32 changes: 14 additions & 18 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ MAINTAINER_NAME = Jose Diaz-Gonzalez
REPOSITORY = go-procfile-util
HARDWARE = $(shell uname -m)
SYSTEM_NAME = $(shell uname -s | tr '[:upper:]' '[:lower:]')
BASE_VERSION ?= 0.6.0
BASE_VERSION ?= 0.7.0
IMAGE_NAME ?= $(MAINTAINER)/$(REPOSITORY)
PACKAGECLOUD_REPOSITORY ?= dokku/dokku-betafish

ifeq ($(CIRCLE_BRANCH),release)
VERSION ?= $(BASE_VERSION)
DOCKER_VERSION = $(VERSION)
DOCKER_IMAGE_VERSION = $(VERSION)
else
VERSION = $(shell echo "${BASE_VERSION}")build+$(shell git rev-parse --short HEAD)
DOCKER_VERSION = $(shell echo "${BASE_VERSION}")build-$(shell git rev-parse --short HEAD)
DOCKER_IMAGE_VERSION = $(shell echo "${BASE_VERSION}")build-$(shell git rev-parse --short HEAD)
endif

version:
Expand All @@ -39,7 +39,7 @@ targets = $(addsuffix -in-docker, $(LIST))
@echo "GITHUB_ACCESS_TOKEN=$(GITHUB_ACCESS_TOKEN)" >> .env.docker
@echo "IMAGE_NAME=$(IMAGE_NAME)" >> .env.docker
@echo "PACKAGECLOUD_REPOSITORY=$(PACKAGECLOUD_REPOSITORY)" >> .env.docker
@echo "PACKAGECLOUD_TOKEN=$(PACKAGECLOUD_API_TOKEN)" >> .env.docker
@echo "PACKAGECLOUD_TOKEN=$(PACKAGECLOUD_TOKEN)" >> .env.docker
@echo "VERSION=$(VERSION)" >> .env.docker

build:
Expand Down Expand Up @@ -83,7 +83,7 @@ build/deb/$(NAME)_$(VERSION)_amd64.deb: build/linux/$(NAME)
--input-type dir \
--license 'MIT License' \
--maintainer "$(MAINTAINER_NAME) <$(EMAIL)>" \
--name procfile-util \
--name $(NAME) \
--output-type deb \
--package build/deb/$(NAME)_$(VERSION)_amd64.deb \
--url "https://github.com/$(MAINTAINER)/$(REPOSITORY)" \
Expand All @@ -103,7 +103,7 @@ build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm: build/linux/$(NAME)
--input-type dir \
--license 'MIT License' \
--maintainer "$(MAINTAINER_NAME) <$(EMAIL)>" \
--name procfile-util \
--name $(NAME) \
--output-type rpm \
--package build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm \
--rpm-os linux \
Expand All @@ -122,21 +122,21 @@ circleci:
rm -f ~/.gitconfig

docker-image:
docker build --rm -q -f Dockerfile.hub -t $(IMAGE_NAME):$(DOCKER_VERSION) .
docker build --rm -q -f Dockerfile.hub -t $(IMAGE_NAME):$(DOCKER_IMAGE_VERSION) .

gh-release:
mkdir -p build
curl -o build/gh-release.tgz -sL https://github.com/progrium/gh-release/releases/download/v2.2.1/gh-release_2.2.1_$(SYSTEM_NAME)_$(HARDWARE).tgz
tar xf build/gh-release.tgz -C build
chmod +x build/gh-release
bin/gh-release:
mkdir -p bin
curl -o bin/gh-release.tgz -sL https://github.com/progrium/gh-release/releases/download/v2.2.1/gh-release_2.2.1_$(SYSTEM_NAME)_$(HARDWARE).tgz
tar xf bin/gh-release.tgz -C bin
chmod +x bin/gh-release

release: build gh-release
release: build bin/gh-release
rm -rf release && mkdir release
tar -zcf release/$(NAME)_$(VERSION)_linux_$(HARDWARE).tgz -C build/linux $(NAME)
tar -zcf release/$(NAME)_$(VERSION)_darwin_$(HARDWARE).tgz -C build/darwin $(NAME)
cp build/deb/$(NAME)_$(VERSION)_amd64.deb release/$(NAME)_$(VERSION)_amd64.deb
cp build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm release/$(NAME)-$(VERSION)-1.x86_64.rpm
build/gh-release create $(MAINTAINER)/$(REPOSITORY) $(VERSION) $(shell git rev-parse --abbrev-ref HEAD)
bin/gh-release create $(MAINTAINER)/$(REPOSITORY) $(VERSION) $(shell git rev-parse --abbrev-ref HEAD)

release-packagecloud:
@$(MAKE) release-packagecloud-deb
Expand All @@ -160,10 +160,6 @@ release-packagecloud-deb: build/deb/$(NAME)_$(VERSION)_amd64.deb
release-packagecloud-rpm: build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm
package_cloud push $(PACKAGECLOUD_REPOSITORY)/el/7 build/rpm/$(NAME)-$(VERSION)-1.x86_64.rpm

store-artifacts: build
mkdir -p /tmp/artifacts
cp -r build/* /tmp/artifacts

validate:
mkdir -p validation
lintian build/deb/$(NAME)_$(VERSION)_amd64.deb || true
Expand Down
5 changes: 0 additions & 5 deletions Procfile

This file was deleted.

35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ All commands take a `-P` or `--procfile` flag to specify an alternative `Procfil
procfile-util check
```

### delete

> delete a process type from a procfile
This command does not retain comments or extra newline characters. Specifying both the `write-path` and `stdout` flags will result in an error.

```shell
# delete the web process and write the file
procfile-util delete --process web

# delete the web process and write output to other.Procfile
procfile-util delete --process web --write-path other.Procfile

# delete the web process and write output to stdout
procfile-util delete --process web --stdout
```

### exists

> check if a process type exists
Expand Down Expand Up @@ -57,6 +74,7 @@ procfile-util expand --allow-getenv --env-file .env
# specify the default-port when performing variable expansion
procfile-util expand --allow-getenv --env-file .env --default-port 3000
```

### list

> list all process types in a procfile
Expand All @@ -65,6 +83,23 @@ procfile-util expand --allow-getenv --env-file .env --default-port 3000
procfile-util list
```

### set

> set the command for a process type in a procfile
This command does not retain comments or extra newline characters. Specifying both the `write-path` and `stdout` flags will result in an error.

```shell
# set the web process and write the file
procfile-util set --process web --command "python app.py -p $PORT"

# set the web process and write output to other.Procfile
procfile-util set --process web --command "python app.py -p $PORT" --write-path other.Procfile

# set the web process and write output to stdout
procfile-util set --process web --command "python app.py -p $PORT" --stdout
```

### show

> show the command for a specific process type
Expand Down
113 changes: 102 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"regexp"
"sort"
"strings"

"github.com/akamensky/argparse"
Expand Down Expand Up @@ -70,6 +71,50 @@ func getProcfile(path string) (string, error) {
return strings.Join(lines, "\n"), err
}

func outputProcfile(path string, writePath string, delimiter string, stdout bool, entries []procfileEntry) bool {
if writePath != "" && stdout {
fmt.Fprintf(os.Stderr, "cannot specify both --stdout and --write-path flags\n")
return false
}

sort.Slice(entries, func(i, j int) bool {
return entries[i].Name < entries[j].Name
})

if stdout {
for _, entry := range entries {
fmt.Printf("%v%v %v\n", entry.Name, delimiter, entry.Command)
}
return true
}

if writePath != "" {
path = writePath
}

if err := writeProcfile(path, delimiter, entries); err != nil {
fmt.Fprintf(os.Stderr, "error writing procfile: %s\n", err)
return false
}

return true
}

func writeProcfile(path string, delimiter string, entries []procfileEntry) error {
debugMessage(fmt.Sprintf("Attempting to write output to file: %v", path))
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()

w := bufio.NewWriter(file)
for _, entry := range entries {
fmt.Fprintln(w, fmt.Sprintf("%v%v %v", entry.Name, delimiter, entry.Command))
}
return w.Flush()
}

func parseProcfile(path string, delimiter string) ([]procfileEntry, error) {
var entries []procfileEntry
reCmd, _ := regexp.Compile(`^([A-Za-z0-9_-]+)` + delimiter + `\s*(.+)$`)
Expand Down Expand Up @@ -117,6 +162,10 @@ func parseProcfile(path string, delimiter string) ([]procfileEntry, error) {
return entries, fmt.Errorf("no entries found in Procfile")
}

sort.Slice(entries, func(i, j int) bool {
return entries[i].Name < entries[j].Name
})

return entries, nil
}

Expand Down Expand Up @@ -207,38 +256,65 @@ func existsCommand(entries []procfileEntry, processType string) bool {
return false
}

func expandCommand(entries []procfileEntry, envPath string, allowGetenv bool, processType string, defaultPort string) bool {
func expandCommand(entries []procfileEntry, envPath string, allowGetenv bool, processType string, defaultPort string, delimiter string) bool {
hasErrors := false
commands := make(map[string]string)
var expandedEntries []procfileEntry
for _, entry := range entries {
command, err := expandEnv(entry, envPath, allowGetenv, defaultPort)
if err != nil {
fmt.Fprintf(os.Stderr, "error processing command: %s\n", err)
hasErrors = true
}

commands[entry.Name] = command
entry.Command = command
expandedEntries = append(expandedEntries, entry)
}

if hasErrors {
return false
}

for k, v := range commands {
if processType == "" || processType == k {
fmt.Printf("%v: %v\n", k, v)
for _, entry := range expandedEntries {
if processType == "" || processType == entry.Name {
fmt.Printf("%v%v %v\n", entry.Name, delimiter, entry.Command)
}
}

return true
}

func deleteCommand(entries []procfileEntry, processType string, writePath string, stdout bool, delimiter string, path string) bool {
var validEntries []procfileEntry
for _, entry := range entries {
if processType == entry.Name {
continue
}
validEntries = append(validEntries, entry)
}

return outputProcfile(path, writePath, delimiter, stdout, validEntries)
}

func listCommand(entries []procfileEntry) bool {
for _, entry := range entries {
fmt.Printf("%v\n", entry.Name)
}
return true
}

func setCommand(entries []procfileEntry, processType string, command string, writePath string, stdout bool, delimiter string, path string) bool {
var validEntries []procfileEntry
validEntries = append(validEntries, procfileEntry{processType, command})
for _, entry := range entries {
if processType == entry.Name {
continue
}
validEntries = append(validEntries, entry)
}

return outputProcfile(path, writePath, delimiter, stdout, validEntries)
}

func showCommand(entries []procfileEntry, envPath string, allowGetenv bool, processType string, defaultPort string) bool {
var foundEntry procfileEntry
for _, entry := range entries {
Expand Down Expand Up @@ -268,25 +344,36 @@ func main() {
loglevelFlag := parser.Selector("l", "loglevel", []string{"info", "debug"}, &argparse.Options{Default: "info", Help: "loglevel to use"})
procfileFlag := parser.String("P", "procfile", &argparse.Options{Default: "Procfile", Help: "path to a procfile"})
delimiterFlag := parser.String("D", "delimiter", &argparse.Options{Default: ":", Help: "delimiter in use within procfile"})
versionFlag := parser.Flag("v", "version", &argparse.Options{Help: "show version"})
defaultPortFlag := parser.String("d", "default-port", &argparse.Options{Default: "5000", Help: "default port to use"})
versionFlag := parser.Flag("v", "version", &argparse.Options{Help: "show version"})

checkCmd := parser.NewCommand("check", "check that the specified procfile is valid")

deleteCmd := parser.NewCommand("delete", "delete a process type from a file")
processTypeDeleteFlag := deleteCmd.String("p", "process-type", &argparse.Options{Help: "name of process to delete", Required: true})
stdoutDeleteFlag := deleteCmd.Flag("s", "stdout", &argparse.Options{Help: "write output to stdout"})
writePathDeleteFlag := deleteCmd.String("w", "write-path", &argparse.Options{Help: "path to Procfile to write to"})

existsCmd := parser.NewCommand("exists", "check if a process type exists")
processTypeExistsFlag := existsCmd.String("p", "process-type", &argparse.Options{Help: "name of process to retrieve"})

expandCmd := parser.NewCommand("expand", "expands a procfile against a specific environment")
allowGetenvExpandFlag := expandCmd.Flag("a", "allow-getenv", &argparse.Options{Help: "allow the use of the existing env when expanding commands"})
envPathExpandFlag := expandCmd.String("e", "env-file", &argparse.Options{Help: "path to a dotenv file"})
processTypeExpandFlag := expandCmd.String("p", "process-type", &argparse.Options{Help: "name of process to retrieve"})
processTypeExpandFlag := expandCmd.String("p", "process-type", &argparse.Options{Help: "name of process to expand"})

listCmd := parser.NewCommand("list", "list all process types in a procfile")

checkCmd := parser.NewCommand("check", "check that the specified procfile is valid")
setCmd := parser.NewCommand("set", "set the command for a process type in a file")
processTypeSetFlag := setCmd.String("p", "process-type", &argparse.Options{Help: "name of process to set", Required: true})
commandSetFlag := setCmd.String("c", "command", &argparse.Options{Help: "command to set", Required: true})
stdoutSetFlag := setCmd.Flag("s", "stdout", &argparse.Options{Help: "write output to stdout"})
writePathSetFlag := setCmd.String("w", "write-path", &argparse.Options{Help: "path to Procfile to write to"})

showCmd := parser.NewCommand("show", "show the command for a specific process type")
allowGetenvShowFlag := showCmd.Flag("a", "allow-getenv", &argparse.Options{Help: "allow the use of the existing env when expanding commands"})
envPathShowFlag := showCmd.String("e", "env-file", &argparse.Options{Help: "path to a dotenv file"})
processTypeShowFlag := showCmd.String("p", "process-type", &argparse.Options{Help: "name of process to retrieve", Required: true})
processTypeShowFlag := showCmd.String("p", "process-type", &argparse.Options{Help: "name of process to show", Required: true})

err := parser.Parse(os.Args)
if err != nil {
Expand All @@ -313,12 +400,16 @@ func main() {
success := false
if checkCmd.Happened() {
success = checkCommand(entries)
} else if deleteCmd.Happened() {
success = deleteCommand(entries, *processTypeDeleteFlag, *writePathDeleteFlag, *stdoutDeleteFlag, *delimiterFlag, *procfileFlag)
} else if existsCmd.Happened() {
success = existsCommand(entries, *processTypeExistsFlag)
} else if expandCmd.Happened() {
success = expandCommand(entries, *envPathExpandFlag, *allowGetenvExpandFlag, *processTypeExpandFlag, *defaultPortFlag)
success = expandCommand(entries, *envPathExpandFlag, *allowGetenvExpandFlag, *processTypeExpandFlag, *defaultPortFlag, *delimiterFlag)
} else if listCmd.Happened() {
success = listCommand(entries)
} else if setCmd.Happened() {
success = setCommand(entries, *processTypeSetFlag, *commandSetFlag, *writePathSetFlag, *stdoutSetFlag, *delimiterFlag, *procfileFlag)
} else if showCmd.Happened() {
success = showCommand(entries, *envPathShowFlag, *allowGetenvShowFlag, *processTypeShowFlag, *defaultPortFlag)
} else {
Expand Down
Loading

0 comments on commit 66afee7

Please sign in to comment.