e2e: jobs scenarios — scheduled rejection, manual run, env_file, job chain

Scenario-DSL coverage for the jobs entry points:
- up refuses a project declaring an active scheduled job before creating
  any resource;
- run executes a manual job like a service, starting its depends_on
  services first, and refuses a schedule-only job;
- a job's own env_file feeds its environment through run — the
  materialization happens before environment resolution;
- a job depending on another job runs the dependency to completion
  first, through the exact machinery a service dependency uses.

Co-Authored-By: Claude Fable 5 <[email protected]>
Signed-off-by: Nicolas De Loof <[email protected]>
This commit is contained in:
Nicolas De Loof
2026-09-21 16:35:20 +02:00
committed by Nicolas De loof
co-authored by Claude Fable 5
parent ef277d266b
commit 135fb0ed3a
6 changed files with 129 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
//go:build e2e
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package e2e
import (
"testing"
)
// Scheduled jobs cannot run in this version: silently not scheduling them
// would break the user's expectations, so up must refuse the whole project.
func TestUpRejectsScheduledJobs(t *testing.T) {
NewScenario(t, "up must reject a project declaring active scheduled jobs, before creating anything").
Step("up fails naming the scheduled job",
ComposeCmd("up", "-d").MayFail(),
StderrContains("scheduled jobs are not supported in this version: backup"),
ServiceNotCreated("web"))
}
// A manual-trigger job runs through `compose run` exactly like a service
// would: its declared dependencies start first, its output and exit flow
// back. A schedule-only job stays out of reach.
func TestRunManualJob(t *testing.T) {
NewScenario(t, "run must execute a manual job like a service, starting its depends_on services first").
Step("run executes the job after starting its dependency",
ComposeCmd("run", "--rm", "migrate"),
OutputContains("migration done"),
ServiceState("db", "running")).
Step("a schedule-only job cannot be run",
ComposeCmd("run", "--rm", "backup").MayFail(),
StderrContains(`job "backup" has no manual trigger`))
}
// A job's own env_file resolves exactly like a selected service's would: the
// materialization happens before environment resolution, not after.
func TestRunJobEnvFile(t *testing.T) {
NewScenario(t, "a job's env_file must feed its environment through run").
Step("the job sees the env_file variable",
ComposeCmd("run", "--rm", "migrate"),
OutputContains("DB_URL=postgres://db:5432/app"))
}
// A job may depend on another job: the dependency job runs to completion
// first — through the exact machinery a service dependency does — then the
// target runs.
func TestRunJobDependsOnJob(t *testing.T) {
NewScenario(t, "a job depending on a job must run the dependency to completion first").
Step("the dependency job completes before the target runs",
ComposeCmd("run", "--rm", "deploy"),
OutputContains("deploy done"),
ServiceState("db", "running"))
}
+22
View File
@@ -0,0 +1,22 @@
services:
db:
image: alpine
init: true
command: sleep infinity
jobs:
prep:
image: alpine
command: sh -c 'echo "prep done"'
triggers:
manual: true
depends_on:
db:
condition: service_started
deploy:
image: alpine
command: sh -c 'echo "deploy done"'
triggers:
manual: true
depends_on:
prep:
condition: service_completed_successfully
+7
View File
@@ -0,0 +1,7 @@
jobs:
migrate:
image: alpine
command: sh -c 'echo "DB_URL=$$DB_URL"'
env_file: db.env
triggers:
manual: true
+1
View File
@@ -0,0 +1 @@
DB_URL=postgres://db:5432/app
+20
View File
@@ -0,0 +1,20 @@
services:
db:
image: alpine
init: true
command: sleep infinity
jobs:
migrate:
image: alpine
command: sh -c 'echo "migration done"'
triggers:
manual: true
depends_on:
db:
condition: service_started
backup:
image: alpine
command: echo backup
triggers:
schedule:
- cron: "0 3 * * *"
@@ -0,0 +1,12 @@
services:
web:
image: alpine
init: true
command: sleep infinity
jobs:
backup:
image: alpine
command: echo backup
triggers:
schedule:
- cron: "0 3 * * *"