Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
28 changes: 13 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Examples:
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
test Test scenarios
test Run a smoke test
update Perform an update job

Flags:
Expand Down Expand Up @@ -189,11 +189,11 @@ such as when evaluating manifest files or executing install scripts.
### `dependabot test`

Run the `test` subcommand
with a scenario file specified by the `--file` / `-f` option
with a smoke test file specified by the `--file` / `-f` option
to test the expected behavior for a Dependabot update job.

```console
$ dependabot test -f scenario.yaml
$ dependabot test -f smoke-test.yaml
# ...
+------------------------------------------+
| Changes to Dependabot Pull Requests |
Expand All @@ -204,14 +204,12 @@ $ dependabot test -f scenario.yaml
time="2022-09-28T08:15:26Z" level=info msg="15/15 calls cached (100%)"
```

<a href="scenario-file"></a>
### Smoke test

### Scenario file

A scenario file describes the input and expected output of a Dependabot job.
A smoke test describes the input _and_ expected output of a Dependabot job.

```yaml
# scenario.yaml
# smoke-test.yaml
input:
job:
package-manager: docker
Expand Down Expand Up @@ -249,7 +247,7 @@ output:
version: "22.04"
```

This example scenario describes the expected behavior for Dependabot
This example smoke test describes the expected behavior for Dependabot
to update the base image of a Dockerfile from `ubuntu:17.04` to `ubuntu:22.04`.

* The `input` field consists of a `job` and any `credentials`.
Expand All @@ -260,24 +258,24 @@ to update the base image of a Dockerfile from `ubuntu:17.04` to `ubuntu:22.04`.

> **Note**
>
> The scenario file format isn't documented publicly,
> The smoke test format isn't documented publicly,
> but you can find examples in the [`smoke-tests` repo][smoke-tests]
> and check [the `Job` class in `dependabot-core`][dependabot-updater-job].

### Producing a test

To produce a scenario file that tests Dependabot behavior for a given repo,
To produce a smoke test that tests Dependabot behavior for a given repo,
run the `update` subcommand and set the `--output` / `-o` option to a file path.

```console
dependabot update go_modules dependabot/cli -o go-scenario.yml
dependabot update go_modules dependabot/cli -o go-smoke-test.yml
```

Run the `test` subcommand for the generated scenario file,
Run the `test` subcommand for the generated smoke test,
specifying a cache directory with the `--cache` option.

```console
dependabot test -f go-scenario.yml --cache ./tmp/cache
dependabot test -f go-smoke-test.yml --cache ./tmp/cache
```

While performing the update job,
Expand All @@ -288,7 +286,7 @@ and you should see a line that looks like this at the bottom of the output:

> time="2022-09-28T08:14:01Z" level=info msg="117/117 calls cached (100%)"

When the cache coverage for a scenario is 100%,
When the cache coverage for a smoke test is 100%,
subsequent runs of the `test` subcommand
are most likely to be fast and deterministic.
Any cache misses indicate an external request made by the updater,
Expand Down
34 changes: 17 additions & 17 deletions cmd/dependabot/internal/cmd/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,31 @@ func NewTestCommand() *cobra.Command {
var flags SharedFlags

cmd := &cobra.Command{
Use: "test -f <scenario.yml>",
Short: "Test scenarios",
Use: "test -f <smoke-test.yml>",
Short: "Run a smoke test",
RunE: func(cmd *cobra.Command, args []string) error {
if flags.file == "" {
return fmt.Errorf("requires a scenario file")
return fmt.Errorf("requires a smoke test file to run, use -f <file>")
}

scenario, inputRaw, err := readScenarioFile(flags.file)
smokeTest, inputRaw, err := readSmokeTest(flags.file)
if err != nil {
return err
}

processInput(&scenario.Input, nil)
processInput(&smokeTest.Input, nil)

if err := executeTestJob(infra.RunParams{
CacheDir: flags.cache,
CollectorConfigPath: flags.collectorConfigPath,
CollectorImage: collectorImage,
Creds: scenario.Input.Credentials,
Creds: smokeTest.Input.Credentials,
Debug: flags.debugging,
Expected: scenario.Output,
Expected: smokeTest.Output,
ExtraHosts: flags.extraHosts,
InputName: flags.file,
InputRaw: inputRaw,
Job: &scenario.Input.Job,
Job: &smokeTest.Input.Job,
LocalDir: flags.local,
Output: flags.output,
ProxyCertPath: flags.proxyCertPath,
Expand All @@ -62,9 +62,9 @@ func NewTestCommand() *cobra.Command {
},
}

cmd.Flags().StringVarP(&flags.file, "file", "f", "", "path to scenario file")
cmd.Flags().StringVarP(&flags.file, "file", "f", "", "path to the smoke test")

cmd.Flags().StringVarP(&flags.output, "output", "o", "", "write scenario to file")
cmd.Flags().StringVarP(&flags.output, "output", "o", "", "write a smoke test to file")
cmd.Flags().StringVar(&flags.cache, "cache", "", "cache import/export directory")
cmd.Flags().StringVar(&flags.local, "local", "", "local directory to use as fetched source")
cmd.Flags().StringVar(&flags.proxyCertPath, "proxy-cert", "", "path to a certificate the proxy will trust")
Expand All @@ -80,20 +80,20 @@ func NewTestCommand() *cobra.Command {

var testCmd = NewTestCommand()

func readScenarioFile(file string) (*model.Scenario, []byte, error) {
var scenario model.Scenario
func readSmokeTest(file string) (*model.SmokeTest, []byte, error) {
var smokeTest model.SmokeTest

data, err := os.ReadFile(file)
if err != nil {
return nil, nil, fmt.Errorf("failed to open scenario file: %w", err)
return nil, nil, fmt.Errorf("failed to open smoke test: %w", err)
}
if err = json.Unmarshal(data, &scenario); err != nil {
if err = yaml.Unmarshal(data, &scenario); err != nil {
return nil, nil, fmt.Errorf("failed to decode scenario file: %w", err)
if err = json.Unmarshal(data, &smokeTest); err != nil {
if err = yaml.Unmarshal(data, &smokeTest); err != nil {
return nil, nil, fmt.Errorf("failed to decode smoke test: %w", err)
}
}

return &scenario, data, nil
return &smokeTest, data, nil
}

func init() {
Expand Down
4 changes: 2 additions & 2 deletions cmd/dependabot/internal/cmd/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ func TestTestCommand(t *testing.T) {
executeTestJob = infra.Run
})

t.Run("Read a scenario file", func(t *testing.T) {
t.Run("Read a smoke test file", func(t *testing.T) {
var actualParams *infra.RunParams
executeTestJob = func(params infra.RunParams) error {
actualParams = &params
return nil
}
cmd := NewTestCommand()
err := cmd.ParseFlags([]string{"-f", "../../../../testdata/scenario.yml"})
err := cmd.ParseFlags([]string{"-f", "../../../../testdata/smoke-test.yml"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/dependabot/internal/cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func NewUpdateCommand() *cobra.Command {
cmd.Flags().StringVarP(&flags.commit, "commit", "", "", "commit to update")
cmd.Flags().StringArrayVarP(&flags.dependencies, "dep", "", nil, "dependencies to update")

cmd.Flags().StringVarP(&flags.output, "output", "o", "", "write scenario to file")
cmd.Flags().StringVarP(&flags.output, "output", "o", "", "write a smoke test file")
cmd.Flags().StringVar(&flags.cache, "cache", "", "cache import/export directory")
cmd.Flags().StringVar(&flags.local, "local", "", "local directory to use as fetched source")
cmd.Flags().StringVar(&flags.proxyCertPath, "proxy-cert", "", "path to a certificate the proxy will trust")
Expand Down
4 changes: 2 additions & 2 deletions internal/infra/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func Run(params RunParams) error {
}

// run the containers, but don't return the error until AFTER the output is generated.
// this ensures that the output is always written in the scenario where there are multiple outputs,
// this ensures that the output is always written in the smoke test where there are multiple outputs,
// some that succeed and some that fail; we still want to see the output of the successful ones.
runContainersErr := runContainers(ctx, params)

Expand Down Expand Up @@ -322,7 +322,7 @@ func expandEnvironmentVariables(api *server.API, params *RunParams) {
}
}

func generateIgnoreConditions(params *RunParams, actual *model.Scenario) error {
func generateIgnoreConditions(params *RunParams, actual *model.SmokeTest) error {
for _, out := range actual.Output {
if out.Type == "create_pull_request" {
createPR, ok := out.Expect.Data.(model.CreatePullRequest)
Expand Down
4 changes: 2 additions & 2 deletions internal/infra/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func Test_generateIgnoreConditions(t *testing.T) {
Output: outputFileName,
}
v := "1.0.0"
actual := &model.Scenario{
actual := &model.SmokeTest{
Output: []model.Output{{
Type: "create_pull_request",
Expect: model.UpdateWrapper{Data: model.CreatePullRequest{
Expand Down Expand Up @@ -140,7 +140,7 @@ func Test_generateIgnoreConditions(t *testing.T) {
runParams := &RunParams{
Output: outputFileName,
}
actual := &model.Scenario{
actual := &model.SmokeTest{
Output: []model.Output{{
Type: "create_pull_request",
Expect: model.UpdateWrapper{Data: model.CreatePullRequest{
Expand Down
4 changes: 2 additions & 2 deletions internal/model/scenario.go → internal/model/smoke.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package model

// Scenario is a way to test a job by asserting the outputs.
type Scenario struct {
// SmokeTest is a way to test a job by asserting the outputs.
type SmokeTest struct {
// Input is the input parameters
Input Input `yaml:"input"`
// Output is the list of expected outputs
Expand Down
4 changes: 2 additions & 2 deletions internal/server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ type API struct {
Expectations []model.Output
// Errors is the error list populated by doing a Dependabot run
Errors []error
// Actual will contain the scenario output that actually happened after the run is Complete
Actual model.Scenario
// Actual will contain the smoke test output that actually happened after the run is Complete
Actual model.SmokeTest

server *http.Server
cursor int
Expand Down
6 changes: 6 additions & 0 deletions testdata/basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ job:
provider: github
repo: dependabot/cli
directory: /
credentials:
- type: git_source
host: github.com
username: x-access-token
password: $LOCAL_GITHUB_ACCESS_TOKEN

File renamed without changes.
Loading