Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: turn entrypoint into gateway-conformance CLI #15

Merged
merged 6 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/actions/extract-fixtures/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ inputs:
description: 'The path where the fixtures will be saved'
required: true
default: 'fixtures'
merged:
description: 'Whether the fixtures should be merged into a single file'
required: false
default: 'false'
runs:
using: 'composite'
steps:
Expand All @@ -15,8 +19,9 @@ runs:
uses: pl-strflt/docker-container-action@v1
env:
OUTPUT: ${{ inputs.output }}
MERGED: ${{ inputs.merged }}
with:
repository: ${{ steps.github.outputs.action_repository }}
ref: ${{ steps.github.outputs.action_ref }}
dockerfile: Dockerfile
args: extract-fixtures "$OUTPUT"
args: extract-fixtures --directory="$OUTPUT" --merged="$MERGED"
26 changes: 9 additions & 17 deletions .github/actions/test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,30 @@ inputs:
markdown:
description: "The path where the Markdown report will be saved"
required: false
is-subdomain:
description: "Enable the test suite for subdomain gateways"
specs:
description: "A comma-separated list of specs to test"
required: false
default: ""
args:
description: "The arguments to pass to the test command"
required: false
runs:
using: "composite"
steps:
- id: github
uses: pl-strflt/docker-container-action/.github/actions/github@v1
- id: generate-args
name: Generate additional arguments
shell: bash
env:
IS_SUBDOMAIN: ${{ inputs.is-subdomain }}
run: |
ARGS=""
if [ "$IS_SUBDOMAIN" = "true" ]; then
ARGS="$ARGS --is-subdomain"
fi

echo "args=${ARGS}" >> "$GITHUB_OUTPUT"
- name: Run the test
uses: pl-strflt/docker-container-action@v1
env:
GATEWAY_URL: ${{ inputs.gateway-url }}
URL: ${{ inputs.gateway-url }}
JSON: ${{ inputs.json }}
ADDITIONAL_ARGS: ${{ steps.generate-args.outputs.args }}
SPECS: ${{ inputs.specs }}
with:
repository: ${{ steps.github.outputs.action_repository }}
ref: ${{ steps.github.outputs.action_ref }}
dockerfile: Dockerfile
opts: --network=host
args: test --gateway-url "$GATEWAY_URL" --json-output "$JSON" ${ADDITIONAL_ARGS}
args: test --url="$URL" --json="$JSON" --specs="$SPECS" -- ${{ inputs.args }}
- name: Create the XML
if: (inputs.xml || inputs.html || inputs.markdown) && (failure() || success())
uses: pl-strflt/gotest-json-to-junit-xml@v1
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ jobs:
xml: output.xml
html: output.html
markdown: output.md
is-subdomain: false
specs: -subdomain-gateway
args: -skip TestGatewayCar
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabled it by test name here. I think it's still useful in a case like this. Kubo does support CARs so it wouldn't make sense to disable testing CAR spec altogether. All we want is to disable this single test because Kubo's implementation is wrong at the moment.

- name: Set summary
if: (failure() || success())
run: cat ./output.md >> $GITHUB_STEP_SUMMARY
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/fixtures.car
/merge-fixtures
/entrypoint
/gateway-conformance

# Logs
logs
Expand Down
10 changes: 4 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
FROM golang:1.19.1-buster
FROM golang:1.20-alpine
WORKDIR /app
ENV TEST_PATH=/app

RUN go install gotest.tools/gotestsum@v1.9.0
ENV GATEWAY_CONFORMANCE_HOME=/app

COPY ./go.mod ./go.sum ./
RUN go mod download

COPY . .
RUN go build -o /entrypoint ./entrypoint.go
RUN go build -o ./gateway-conformance ./cmd/gateway-conformance

ENTRYPOINT ["/entrypoint"]
ENTRYPOINT ["/app/gateway-conformance"]
23 changes: 10 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,19 @@ provision-kubo:
test-kubo: provision-kubo
GATEWAY_URL=http://127.0.0.1:8080 make _test

merge-fixtures:
go build -o merge-fixtures ./tooling/cmd/merge_fixtures.go

# tools
fixtures.car: entrypoint
./entrypoint merge-fixtures ./fixtures.car
fixtures.car: gateway-conformance
./gateway-conformance extract-fixtures --merged=true --dir=.

entrypoint:
go build -o ./entrypoint ./entrypoint.go
gateway-conformance:
go build -o ./gateway-conformance ./cmd/gateway-conformance

_test: fixtures.car entrypoint
./entrypoint test --json-output output.json --gateway-url ${GATEWAY_URL} --is-subdomain
_test: fixtures.car gateway-conformance
./gateway-conformance test --json output.json --gateway-url ${GATEWAY_URL}

test-docker: fixtures.car entrypoint
docker build -t gway-test .
docker run --rm -v "${PWD}:/workspace" -w "/workspace" --network=host gway-test test
test-docker: fixtures.car gateway-conformance
docker build -t gateway-conformance .
docker run --rm -v "${PWD}:/workspace" -w "/workspace" --network=host gateway-conformance test

output.xml: test-kubo
docker run --rm -v "${PWD}:/workspace" -w "/workspace" --entrypoint "/bin/bash" ghcr.io/pl-strflt/saxon:v1 -c """
Expand All @@ -37,4 +34,4 @@ output.html: output.xml
docker run --rm -v "${PWD}:/workspace" -w "/workspace" ghcr.io/pl-strflt/saxon:v1 -s:output.xml -xsl:/etc/junit-noframes-saxon.xsl -o:output.html
open ./output.html

.PHONY: entrypoint
.PHONY: gateway-conformance
191 changes: 191 additions & 0 deletions cmd/gateway-conformance/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package main

import (
"bytes"
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/ipfs/gateway-conformance/tooling"
"github.com/ipfs/gateway-conformance/tooling/car"
"github.com/ipfs/gateway-conformance/tooling/fixtures"
"github.com/urfave/cli/v2"
)

type event struct {
Action string
Test string `json:",omitempty"`
}

type out struct {
Writer io.Writer
}

func (o out) Write(p []byte) (n int, err error) {
os.Stdout.Write(p)
return o.Writer.Write(p)
}

func copyFiles(inputPaths []string, outputDirectoryPath string) error {
err := os.MkdirAll(outputDirectoryPath, 0755)
if err != nil {
return err
}
for _, inputPath := range inputPaths {
outputPath := filepath.Join(outputDirectoryPath, filepath.Base(inputPath))
src, err := os.Open(inputPath)
if err != nil {
return err
}
defer src.Close()
dst, err := os.Create(outputPath)
if err != nil {
return err
}
defer dst.Close()
_, err = io.Copy(dst, src)
if err != nil {
return err
}
}
return nil
}

func main() {
var gatewayURL string
var jsonOutput string
var specs string
var directory string
var merged bool

app := &cli.App{
Name: "gateway-conformance",
Usage: "Tooling for the gateway test suite",
Commands: []*cli.Command{
{
Name: "test",
Aliases: []string{"t"},
Usage: "Run the conformance test suite against your gateway",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "gateway-url",
Aliases: []string{"url", "g"},
Usage: "The URL of the gateway to test",
Value: "http://localhost:8080",
Destination: &gatewayURL,
},
&cli.StringFlag{
Name: "json-output",
Aliases: []string{"json", "j"},
Usage: "The path to the JSON output file",
Value: "",
Destination: &jsonOutput,
},
&cli.StringFlag{
Name: "specs",
Usage: "A comma-separated list of specs to test",
Value: "",
Destination: &specs,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it and I think I'd prefer an interface that people can get used to. If we have separate flag for each spec (as it was here before), then we'd have to change that interface every time a new spec is added to the tests. I think it'd become quite overwhelming with the amount of different specs we might want to support. Also, it'd be harder to maintain as we'd have to remember to update the lists in all these places. In my opinion a single (or three) flags that take a list of specs will be easier to manage in a long run.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful to add a command for listing all the specs!

},
},
Action: func(cCtx *cli.Context) error {
args := []string{"test", "./tests", "-test.v=test2json"}

if specs != "" {
args = append(args, fmt.Sprintf("-specs=%s", specs))
}

args = append(args, cCtx.Args().Slice()...)

fmt.Println("go " + strings.Join(args, " "))

output := &bytes.Buffer{}
cmd := exec.Command("go", args...)
cmd.Dir = tooling.Home()
cmd.Env = append(os.Environ(), fmt.Sprintf("GATEWAY_URL=%s", gatewayURL))
cmd.Stdout = out{output}
cmd.Stderr = os.Stderr
testErr := cmd.Run()

if jsonOutput != "" {
json := &bytes.Buffer{}
cmd = exec.Command("go", "tool", "test2json", "-p", "Gateway Tests", "-t")
cmd.Stdin = output
cmd.Stdout = json
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return err
}
// write jsonOutput to json file
f, err := os.Create(jsonOutput)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(json.Bytes())
if err != nil {
return err
}
}

return testErr
},
},
{
Name: "extract-fixtures",
Aliases: []string{"e"},
Usage: "Extract gateway testing fixtures that are used by the conformance test suite",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "directory",
Aliases: []string{"dir"},
Usage: "The directory to extract the fixtures to",
Required: true,
Destination: &directory,
},
&cli.BoolFlag{
Name: "merged",
Usage: "Merge the fixtures into a single CAR file",
Value: false,
Destination: &merged,
},
},
Action: func(cCtx *cli.Context) error {
err := os.MkdirAll(directory, 0755)
if err != nil {
return err
}

files, err := fixtures.List()
if err != nil {
return err
}

merged := cCtx.Bool("merged")
if merged {
err = car.Merge(files, filepath.Join(directory, "fixtures.car"))
if err != nil {
return err
}
} else {
err = copyFiles(files, directory)
if err != nil {
return err
}
}

return nil
},
},
},
}

if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
Loading