Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
zekroTJA committed Dec 21, 2023
2 parents be91c64 + d760672 commit 98828a5
Show file tree
Hide file tree
Showing 47 changed files with 533 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: "^1.19"
go-version: "^1.20"
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Infuse Version
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: "^1.19"
go-version: "^1.20"
- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@latest
- name: Install mockgen
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: "^1.19"
go-version: "^1.20"
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Infuse Version
Expand Down
21 changes: 15 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
[VERSION]

# ⚠️ Breaking Changes

- The built-in template function `base64url` has been renamed to `base64Url` for better naming consistency. [#48]

- The built-in template functions `base64` and `base64Url` do now encode strings to Base64 **with leading padding**. If you want to encode without padding, use the new functions `base64Unpadded` and `base64UrlUnpadded`. [#48]

- The previously deprecated alias `headers` for the `header` request section has now been removed.

# New Features

- A new template function `json` has been added which encodes any passed object into a JSON string (e.g. `{{ json .myObject }}`).
-
- For each in-script logging function, a formatted equivalent has been added (e.g. `infof("Hello, %s!", "world")`).
- Requesting HTTPS endpoints with self-signed certificates is now possible. [#49, #51]
*That means, that the certificate validity is **not checked by default**. You can pass the `--secure` flag or set the `GOATARG_SECURE=true` environment variable to enable certificate validation.*

# Minor Changes and Bug Fixes

- Variables set in the `PreScript` section are now available for substitution in all other parts of the request like URL, options, header, body or script. [#43]
- Fixed a bug causing a panic when multiple Goatfiles are passed and one or more of these files do not exist. Now, a proper error message is returned.

- Fixed a bug which caused a panic when invalid key-value paris have been passed via the `--args` flag. [#49]

- Section log lines are now hidden when a Goatfile is executed via the `execute` instruction.
- When running with the `DEBUG` logging level, the parsed Goatfile is now only printed to log output if the `--dry` flag is passed.

- Some more debugging information has been added visible when using the `trace` log level.
- Some command line parameters now got respective environment variables to set them. These are prefixed with `GOATARG_` and can be viewed in the `--help` overview.
19 changes: 19 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM golang:alpine AS build
WORKDIR /build
COPY .git/ .git/
COPY cmd/ cmd/
COPY internal/ internal/
COPY pkg/ pkg/
COPY scripts/ scripts/
COPY go.mod .
COPY go.sum .
RUN ash scripts/version.sh
RUN go build -v -o bin/goat cmd/goat/main.go

FROM alpine
LABEL org.opencontainers.image.authors="B12-Touch GmbH (hello@b12-touch.de)" \
org.opencontainers.image.url="https://github.com/studio-b12/goat" \
org.opencontainers.image.source="https://github.com/studio-b12/goat" \
org.opencontainers.image.licenses="BSD-Clause-3"
COPY --from=build /build/bin/goat /bin/goat
ENTRYPOINT ["/bin/goat"]
31 changes: 21 additions & 10 deletions cmd/goat/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package main

import (
"bufio"
"crypto/tls"
"fmt"
"io/fs"
"net/http"
"os"
"path/filepath"
"runtime"
Expand All @@ -28,17 +30,18 @@ type Args struct {
Goatfile []string `arg:"positional" help:"Goatfile(s) location"`

Arg []string `arg:"-a,--args,separate" help:"Pass params as key value arguments into the execution (format: key=value)"`
Delay time.Duration `arg:"-d,--delay" help:"Delay requests by the given duration"`
Delay time.Duration `arg:"-d,--delay,env:GOATARG_DELAY" help:"Delay requests by the given duration"`
Dry bool `arg:"--dry" help:"Only parse the goatfile(s) without executing any requests"`
Gradual bool `arg:"-g,--gradual" help:"Advance the requests maually"`
Json bool `arg:"--json" help:"Use JSON format instead of pretty console format for logging"`
LogLevel string `arg:"-l,--loglevel" default:"info" help:"Logging level (see https://github.com/zekrotja/rogu#levels for reference)"`
Json bool `arg:"--json,env:GOATARG_JSON" help:"Use JSON format instead of pretty console format for logging"`
LogLevel string `arg:"-l,--loglevel,env:GOATARG_LOGLEVEL" default:"info" help:"Logging level (see https://github.com/zekrotja/rogu#levels for reference)"`
New bool `arg:"--new" help:"Create a new base Goatfile"`
NoAbort bool `arg:"--no-abort" help:"Do not abort batch execution on error"`
NoColor bool `arg:"--no-color" help:"Supress colored log output"`
Params []string `arg:"-p,--params,separate" help:"Params file location(s)"`
Silent bool `arg:"-s,--silent" help:"Disables all logging output"`
Skip []string `arg:"--skip,separate" help:"Section(s) to be skipped during execution"`
NoAbort bool `arg:"--no-abort,env:GOATARG_NOABORT" help:"Do not abort batch execution on error"`
NoColor bool `arg:"--no-color,env:GOATARG_NOCOLOR" help:"Supress colored log output"`
Params []string `arg:"-p,--params,separate,env:GOATARG_PARAMS" help:"Params file location(s)"`
Silent bool `arg:"-s,--silent,env:GOATARG_SILENT" help:"Disables all logging output"`
Skip []string `arg:"--skip,separate,env:GOATARG_SKIP" help:"Section(s) to be skipped during execution"`
Secure bool `arg:"--secure,env:GOATARG_SECURE" help:"Validate TLS certificates"`
}

func main() {
Expand Down Expand Up @@ -86,10 +89,18 @@ func main() {
return
}

config.ParseKVArgs(args.Arg, state)
err = config.ParseKVArgs(args.Arg, state)
if err != nil {
log.Fatal().Err(err).Msg("argument parsing failed")
return
}

engineMaker := engine.NewGoja
req := requester.NewHttpWithCookies()
req := requester.NewHttpWithCookies(func(client *http.Client) {
client.Transport = &http.Transport{TLSClientConfig: &tls.Config{
InsecureSkipVerify: !args.Secure,
}}
})

exec := executor.New(engineMaker, req)
exec.Dry = args.Dry
Expand Down
1 change: 1 addition & 0 deletions docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [Options](./goatfile/requests/options.md)
- [Headers](./goatfile/requests/header.md)
- [Query Parameters](./goatfile/requests/query-params.md)
- [Auth](./goatfile/requests/auth.md)
- [Body](./goatfile/requests/body.md)
- [PreScript](./goatfile/requests/prescript.md)
- [Script](./goatfile/requests/script.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/book/src/assets/simple-state.excalidraw.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions docs/book/src/command-line-tool/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ In the following, further information is provided about the various flags which
Section(s) to be skipped during execution.
*Example: `--skip teardown`*

- **`--secure`**
Enable TLS certificate validation.

- **`--help`, ` -h`**
Display the help message.

Expand Down
4 changes: 2 additions & 2 deletions docs/book/src/goatfile/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ GET https://api.github.com/repos/{{.repo}}
[Script]
assert(response.StatusCode === 200, `Invalid response code: ${response.StatusCode}`);
assert(response.BodyJson.language === "Go");
assert(response.Body.language === "Go");
---
GET https://api.github.com/repos/{{.repo}}/languages
[Script]
info('Languages:\n' + JSON.stringify(response.BodyJson, null, 2));
info('Languages:\n' + JSON.stringify(response.Body, null, 2));
assert(response.StatusCode === 200, `Invalid response code: ${response.StatusCode}`);
```

Expand Down
63 changes: 63 additions & 0 deletions docs/book/src/goatfile/requests/auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Auth

> *RequestOptions* :
> `[Auth]` `NL`+ *RequestAuthContent*
>
> *RequestAuthContent* :
> *TomlKeyValues*
## Example

```toml
[Auth]
username = "foo"
password = "{{.credentials.password}}"
```

## Explanation

Auth is a utility block for easily defining basic or token authorization. When defined, the `Authorization` header will
be set accordingly to the request.

## Basic Auth

If you want to add basic auth to your request, simply define a `username` and `password`. If **both** values are set,
the username and password are joined by a `:` and encoded using end-padded base64. The encoded value is then set to the
`Authorization` header using the `basic` auth type (as defined in
[RFC 7671](https://www.rfc-editor.org/rfc/rfc7617)).

> **Example**
> ```toml
> [Auth]
> username = "foo"
> password = "bar"
> ```
> his input will result in the following header.
> ```
> Authorization: basic Zm9vOmJhcg==
> ```
## Token Auth
You can also specify a `token` set as `Authorization` header. If defined, the token will be prefixed with
a token `type`.
> **Example**
> ```toml
> [Auth]
> type = "bearer"
> token = "foobarbaz"
> ```
> This input will result in the following header.
> ```
> Authorization: bearer foobarbaz
> ```
>
> ```toml
> [Auth]
> token = "foobarbaz"
> ```
> This input will result in the following header.
> ```
> Authorization: foobarbaz
> ```
7 changes: 7 additions & 0 deletions docs/book/src/goatfile/requests/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,10 @@ Defines if a request shall be executed or not. This is useful in combination wit
- **Default**: `0`

A duration formatted as a Go [time.ParseDuration](https://pkg.go.dev/time#ParseDuration) compatible string. Execution will pause for this duration before the request is executed.

### `responsetype`

- **Type**: `string`
- **Default**: `""`

Explicit type declaration for body parsing. Implicit body parsing (json/xml) can be prevented by setting this option to `raw`.
2 changes: 1 addition & 1 deletion docs/book/src/goatfile/requests/prescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ POST http://example.com/api/user
[Script]
assert(response.StatusCode === 201);
var user = response.BodyJson;
var user = response.Body;
---
Expand Down
10 changes: 6 additions & 4 deletions docs/book/src/goatfile/requests/script.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
[Script]
```
assert(response.StatusCode === 200, `Response status code was ${response.StatusCode}`);
assert(response.BodyJson.UserName === "Foo Bar");
assert(response.Body.UserName === "Foo Bar");
```
````

Expand All @@ -44,12 +44,14 @@ type Response struct {
ProtoMinor int
Header map[string][]string
ContentLength int64
Body string
BodyJson any
BodyRaw []byte
Body any
}
```

`BodyJson` is a special field containing the response body content as a JavaScript object which will be populated if the response body can be parsed as a JSON object.
`Body` is a special field containing the response body content as a JavaScript object which will be populated if the response body can be parsed.
Parsers are currently implemented for `json` and `xml` and are chosen depending on the `responsetype` option or the `Content-Type` header.
If neither are set, the raw response string gets set as `Body`. By setting the `responsetype` to `raw`, implicit body parsing can be prevented.

In any script section, a number of built-in functions like `assert` can be used, which are documented [here](../../scripting/builtins.md).

Expand Down
39 changes: 34 additions & 5 deletions docs/book/src/templating/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,57 @@ The following built-in functions are available in templates used in Goatfiles.
base64 <value: string> -> string
```

Returns the input `value` as base64 encoded string.
Returns the input `value` as base64 encoded string with padding.

**Example:**

```
{{ base64 "hello world" }}
```

## `base64url`
## `base64Url`

```
base64url <value: string> -> string
base64Url <value: string> -> string
```

Returns the input `value` as base64url encoded string.
Returns the input `value` as base64url encoded string with padding.

**Example:**

```
{{ base64url "hello world" }}
{{ base64Url "hello world" }}
```

## `base64Unpadded`

```
base64Unpadded <value: string> -> string
```

Returns the input `value` as base64 encoded string without padding.

**Example:**

```
{{ base64Unpadded "hello world" }}
```

## `base64UrlUnpadded`

```
base64UrlUnpadded <value: string> -> string
```

Returns the input `value` as base64url encoded string without padding.

**Example:**

```
{{ base64UrlUnpadded "hello world" }}
```


## `md5`

```
Expand Down
4 changes: 2 additions & 2 deletions docs/goatfile-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ The script parts is getting passed builtin functions as well as the response con
[Script]
assert(response.StatusCode == 200);
info(response.Body);
var uid = response.BodyJson.Uid;
var uid = response.Body.Uid;
```
It is also possible to import a file as script. Simply specify the path to the file with a leading `@` to import the file by a relative path from the current Goatfile or an absolute path. The past must be specified in Unix style. Template placeholders in imported body data **will** be infused on execution!
Expand Down Expand Up @@ -264,7 +264,7 @@ POST {{.instance}}/api/auth/token
[Script]
assert(response.StatusCode == 200);
var bearerToken = response.BodyJson.bearer_token;
var bearerToken = response.Body.bearer_token;
---
Expand Down
Loading

0 comments on commit 98828a5

Please sign in to comment.