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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: provide a tool to generate examples from code #618
Merged
Merged
Changes from 37 commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
0fcd7bd
chore: convert pulsar example in executable code
mdelapenya 9d5fbfe
chore: convert nginx example in executable code
mdelapenya 30171e2
fix: handle error in tests
mdelapenya 51a0690
chore: convert redis example in executable code
mdelapenya 9cd249f
chore: convert cockroachDB example in executable code
mdelapenya 9be5620
chore: simplify including the entire file as example
mdelapenya 1f396e5
chore: bump dependencies in the e2e module
mdelapenya 44434df
chore: add a common Make goal for running Go tests
mdelapenya 2e37ff3
chore: push go mod goals to the common file
mdelapenya d8bf2e8
chore: add gotestsum as tools to the examples
mdelapenya 7c48ee0
chore: support running the example files with Make
mdelapenya f6272d4
chore: use new goal in CI pipelines
mdelapenya 5f0fcc2
feat: add a tool to bootstrap an example
mdelapenya f110af4
chore: extract code generation to a function
mdelapenya bfa9581
chore: pass the examples dir to the generate function
mdelapenya 2328361
chore: pass the examples docs dir to the generate function
mdelapenya f32d9bb
fix: prepend examples dir when creating the examples files
mdelapenya b3ab1b9
chore: extract templates to a constant
mdelapenya e66df3f
chore: save toolsgo under its own package
mdelapenya 7ab47d5
chore: add unit tests for the code generation tool
mdelapenya 9eba684
chore: run unit tests for the examples
mdelapenya 70e2ed5
chore: simplify how to compare tasks
mdelapenya d801fde
fix: remove useless assertion
mdelapenya ed0121e
Merge branch 'main' into examples
mdelapenya f55c0fb
chore: support setting the Docker image for the example
mdelapenya 6305f98
docs: document the command line flags
mdelapenya 47f2a43
fix: simplify path generation for examples
mdelapenya a618362
fix: remove unused package in template
mdelapenya fead327
fix: use a title for the example in functions
mdelapenya e07d6c6
chore: add comments to functions
mdelapenya df051de
chore: simplify passing the example to the generator
mdelapenya e06ab17
Merge branch 'main' into examples-work
mdelapenya 4210a10
chore: standardize how the container is cleaned in tests
mdelapenya 853375f
fix: use a timeout in pulsar example
mdelapenya aa4529f
Revert "fix: use a timeout in pulsar example"
mdelapenya f4c4ce9
fix: do not termiante pulsar container, as it's controlled by the Reaper
mdelapenya bc0ec00
Merge branch 'main' into examples-work
mdelapenya 7f06d72
chore: add tests to verify that the examples are added to the docs
mdelapenya cce7f35
chore: automatically add examples to mkdocs
mdelapenya c4add3c
docs: update docs
mdelapenya 58c00fa
Merge branch 'main' into examples-work
mdelapenya bf5f4f0
Merge branch 'main' into examples-work
mdelapenya 7f975ef
chore: run examples in dedicated pipelines each
mdelapenya f62f646
chore: add CI pipelines for the examples
mdelapenya c270aa1
docs: move new tool docs to the website
mdelapenya f9ee2f8
docs: link to the examples dir on Github
mdelapenya 9489fef
fix: update tests
mdelapenya 0ea14c0
chore: include generator tests in the main pipeline
mdelapenya 53fd6ef
chore: simplify example pipeline removing go build
mdelapenya File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,14 @@ | ||
include ./commons-test.mk | ||
|
||
.PHONY: test-all | ||
test-all: tools test-unit test-e2e | ||
|
||
.PHONY: test-unit | ||
test-unit: | ||
@echo "Running unit tests..." | ||
go run gotest.tools/gotestsum \ | ||
--format short-verbose \ | ||
--rerun-fails=5 \ | ||
--packages="./..." \ | ||
--junitfile TEST-unit.xml | ||
|
||
.PHONY: test-e2e | ||
test-e2e: | ||
@echo "Running end-to-end tests..." | ||
make -C e2e test | ||
|
||
.PHONY: tools | ||
tools: | ||
go mod download | ||
.PHONY: test-examples | ||
test-examples: | ||
@echo "Running example tests..." | ||
make -C examples test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
.PHONY: test-% | ||
test-%: | ||
@echo "Running $* tests..." | ||
go run gotest.tools/gotestsum \ | ||
--format short-verbose \ | ||
--rerun-fails=5 \ | ||
--packages="./..." \ | ||
--junitfile TEST-$*.xml | ||
|
||
.PHONY: tools | ||
tools: | ||
go mod download | ||
|
||
.PHONY: tools-tidy | ||
tools-tidy: | ||
go mod tidy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,148 +1,9 @@ | ||
# CockroachDB | ||
|
||
```go | ||
package main | ||
<!--codeinclude--> | ||
[Creating a CockroachDB container](../../examples/cockroachdb/cockroachdb.go) | ||
<!--/codeinclude--> | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"fmt" | ||
"testing" | ||
"time" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/google/uuid" | ||
_ "github.com/jackc/pgx/v4/stdlib" | ||
"github.com/testcontainers/testcontainers-go" | ||
"github.com/testcontainers/testcontainers-go/wait" | ||
) | ||
|
||
// Task represents a unit of work to complete. We're going to be using this in | ||
// our example as a way to organize data that is being manipulated in | ||
// the database. | ||
type task struct { | ||
ID string `json:"id"` | ||
Description string `json:"description"` | ||
DateDue *time.Time `json:"date_due,string"` | ||
DateCreated time.Time `json:"date_created,string"` | ||
DateUpdated time.Time `json:"date_updated"` | ||
} | ||
|
||
type cockroachDBContainer struct { | ||
testcontainers.Container | ||
URI string | ||
} | ||
|
||
func setupCockroachDB(ctx context.Context) (*cockroachDBContainer, error) { | ||
req := testcontainers.ContainerRequest{ | ||
Image: "cockroachdb/cockroach:latest-v21.1", | ||
ExposedPorts: []string{"26257/tcp", "8080/tcp"}, | ||
WaitingFor: wait.ForHTTP("/health").WithPort("8080"), | ||
Cmd: []string{"start-single-node", "--insecure"}, | ||
} | ||
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||
ContainerRequest: req, | ||
Started: true, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
mappedPort, err := container.MappedPort(ctx, "26257") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
hostIP, err := container.Host(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
uri := fmt.Sprintf("postgres://root@%s:%s", hostIP, mappedPort.Port()) | ||
|
||
return &cockroachDBContainer{Container: container, URI: uri}, nil | ||
} | ||
|
||
func initCockroachDB(ctx context.Context, db sql.DB) error { | ||
// Actual SQL for initializing the database should probably live elsewhere | ||
const query = `CREATE DATABASE projectmanagement; | ||
CREATE TABLE projectmanagement.task( | ||
id uuid primary key not null, | ||
description varchar(255) not null, | ||
date_due timestamp with time zone, | ||
date_created timestamp with time zone not null, | ||
date_updated timestamp with time zone not null);` | ||
_, err := db.ExecContext(ctx, query) | ||
|
||
return err | ||
} | ||
|
||
func truncateCockroachDB(ctx context.Context, db sql.DB) error { | ||
const query = `TRUNCATE projectmanagement.task` | ||
_, err := db.ExecContext(ctx, query) | ||
return err | ||
} | ||
|
||
func TestIntegrationDBInsertSelect(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip("Skipping integration test") | ||
} | ||
|
||
ctx := context.Background() | ||
|
||
cdbContainer, err := setupCockroachDB(ctx) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
t.Cleanup(func() { | ||
if err := cdbContainer.Terminate(ctx); err != nil { | ||
t.Fatalf("failed to terminate container: %s", err) | ||
} | ||
}) | ||
|
||
db, err := sql.Open("pgx", cdbContainer.URI+"/projectmanagement") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer db.Close() | ||
|
||
err = initCockroachDB(ctx, *db) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer truncateCockroachDB(ctx, *db) | ||
|
||
now := time.Now() | ||
|
||
// Insert data | ||
tsk := task{ID: uuid.NewString(), Description: "Update resum茅", DateCreated: now, DateUpdated: now} | ||
const insertQuery = `insert into "task" (id, description, date_due, date_created, date_updated) | ||
values ($1, $2, $3, $4, $5)` | ||
_, err = db.ExecContext( | ||
ctx, | ||
insertQuery, | ||
tsk.ID, | ||
tsk.Description, | ||
tsk.DateDue, | ||
tsk.DateCreated, | ||
tsk.DateUpdated) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Select data | ||
savedTsk := task{ID: tsk.ID} | ||
const findQuery = `select description, date_due, date_created, date_updated | ||
from task | ||
where id = $1` | ||
row := db.QueryRowContext(ctx, findQuery, tsk.ID) | ||
err = row.Scan(&savedTsk.Description, &savedTsk.DateDue, &savedTsk.DateCreated, &savedTsk.DateUpdated) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if !cmp.Equal(tsk, savedTsk) { | ||
t.Fatalf("Saved task is not the same:\n%s", cmp.Diff(tsk, savedTsk)) | ||
} | ||
} | ||
``` | ||
<!--codeinclude--> | ||
[Test for a CockroachDB container](../../examples/cockroachdb/cockroachdb_test.go) | ||
<!--/codeinclude--> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,9 @@ | ||
# NGINX | ||
# Nginx | ||
|
||
```go | ||
package main | ||
<!--codeinclude--> | ||
[Creating a Nginx container](../../examples/nginx/nginx.go) | ||
<!--/codeinclude--> | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/testcontainers/testcontainers-go" | ||
"github.com/testcontainers/testcontainers-go/wait" | ||
) | ||
|
||
type nginxContainer struct { | ||
testcontainers.Container | ||
URI string | ||
} | ||
|
||
func setupNginx(ctx context.Context) (*nginxContainer, error) { | ||
req := testcontainers.ContainerRequest{ | ||
Image: "nginx", | ||
ExposedPorts: []string{"80/tcp"}, | ||
WaitingFor: wait.ForHTTP("/"), | ||
} | ||
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||
ContainerRequest: req, | ||
Started: true, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ip, err := container.Host(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
mappedPort, err := container.MappedPort(ctx, "80") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
uri := fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) | ||
|
||
return &nginxContainer{Container: container, URI: uri}, nil | ||
} | ||
|
||
func TestIntegrationNginxLatestReturn(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip("skipping integration test") | ||
} | ||
|
||
ctx := context.Background() | ||
|
||
nginxC, err := setupNginx(ctx) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Clean up the container after the test is complete | ||
t.Cleanup(func() { | ||
t.Log("terminating container") | ||
if err := nginxC.Terminate(ctx); err != nil { | ||
t.Errorf("failed to terminate container: :%w", err) | ||
} | ||
}) | ||
|
||
resp, err := http.Get(nginxC.URI) | ||
if resp.StatusCode != http.StatusOK { | ||
t.Fatalf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) | ||
} | ||
} | ||
``` | ||
<!--codeinclude--> | ||
[Test for a Nginx container](../../examples/nginx/nginx_test.go) | ||
<!--/codeinclude--> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm tempted to have a dedicated pipeline for each example, instead of adding build time to the main one. Wdyt? If that's the case, should the checks be mandatory for the review?