1 Introduction
ambient runs CI for a project in a VM.
2 Acceptance criteria for ambient
2.1 Smoke test
Want: The ambient tool can show it's runtime
configuration.
Why: If this doesn't work, there's no hope of anything else working, either.
Who: Lars
state: ambient_state executor: ambient-execute-plan image_store: image-store uefi: true
2.2 Reports its version
Want: ambient can be queried for its version.
Why: This is useful for diagnosing problems, and also acts as a smoke test: if this works, we know the adapter is installed and can be run.
2.3 Backwards compatible QEMU configuration
Want: The ambient tool understands its own older configuration
files, but warns about them.
Why: This make migration to the newer configuration format less harsh.
Who: Lars
cpus: 8 memory: "16 GB"
2.4 Allows specifying a configuration file
Want: The ambient tool allows the user to specify
which configuration file to use.
Why: This is very convenient when one wants to try things and temporarily not use the default configuration file. This happens both for experimentation and for testing.
Who: Lars
executor: xyzzy
artifacts_max_size: 1TB
2.5 Notices a source directory that is not a directory
Want: The ambient tool notices if a projects file
refers to a source directory that is not a directory.
Why: It's better to catch errors early than let tar notice them later.
Who: Lars
projects:
bad_source:
image: ambient.qcow2
source: /etc/passwd
plan:
- action: shell
shell: |
true
2.6 Obeys TMPDIR
Want: The default temporary directory is $TMPDIR, if set, or
/tmp otherwise.
Why: This is expected Unix behavior.
Who: Lars.
2.7 Sets environment variables
Want: Ambient sets specific environment variables when running actions in the VM. It may set others, but at least these.
Why: This is expected Unix behavior.
Who: Lars.
projects:
env:
image: ambient.qcow2
source: srcdir
plan:
- action: shell
shell: |
env
2.8 Configures Git user
Want: Ambient configures the Git user in the VM.
Why: This is common in test suites.
Who: Lars.
projects:
git:
image: ambient.qcow2
source: srcdir
plan:
- action: shell
shell: |
echo "GITUSER: $(git config --global user.name) //"
echo "GITEMAIL: $(git config --global user.email) //"
2.9 Allows setting environment variables
Want: Ambient allows setting environment variables for later actions.
Why: This is common in test suites.
Who: Lars.
projects:
setenv:
image: ambient.qcow2
source: srcdir
plan:
- action: setenv
set:
FOO: bar
- action: shell
shell: |
env
echo "foo=$FOO/"
2.10 Capture build log when running
Want: The stdout/stderr output of the commands executed by the CI run must be captured.
Why: This is the primary way for the user to know what happened during a run.
Who: Lars.
Note that we can't use . for the current directory as the source
field in the project file due to how Subplot sets up a temporary data
directory for each scenario, and sets TMPDIR to that directory.
This would mean that . as source would create a tar archive in the
temporary directory that tries to add itself, which creates an
infinitely large tar archive.
projects:
hello:
image: ambient.qcow2
source: srcdir
plan:
- action: shell
shell: |
echo well hello there, friend
2.11 Run fails if an action fails
Want: If an action fails, the whole CI run fails.
Why: This is fundemental to how a CI engine needs to work.
Who: Lars
projects:
hello:
image: ambient.qcow2
source: srcdir
plan:
- action: shell
shell: |
false
2.12 Store run log in project directory
Want: The run log should be stored persistently in the project state directory, and there is a way to retrieve it later.
Why: Run logs are often needed long after the run has happened.
Who: Lars.
2.13 Relative filenames in project files
Want: When a project file has a relative filename, it's relative to the directory containing the project file.
Why: The user can then run ambient run from
anywhere, not just the source directory.
Who: Lars.
2.14 Working directory in pre- and post-plan actions
Want: When a pre- or post-plan action is executed, the current working directory should be the source directory.
Why: Many actions can only usefully be executed in the source directory.
Who: Lars.
Note that we can't use . for the current directory as the source
field in the project file due to how Subplot sets up a temporary data
directory for each scenario, and sets TMPDIR to that directory.
This would mean that . as source would create a tar archive in the
temporary directory that tries to add itself, which creates an
infinitely large tar archive.
projects:
pwd:
image: ambient.qcow2
source: path/to/project/srcdir
pre_plan:
- action: pwd
post_plan:
- action: pwd
plan:
- action: shell
shell: |
pwd
2.15 Run CI only for some projects
Want: When the projects file has more than one project, user can choose only specific ones to run CI for.
Why: User may be only interested in one project right now.
Who: Lars
projects:
foo:
image: ambient.qcow2
source: foo
plan:
- action: shell
shell: |
echo foo project
bar:
image: ambient.qcow2
source: bar
plan:
- action: shell
shell: |
echo bar project
2.16 List names of projects
Want: The user can list names of projects in a projects file.
Why: This is handy for checking and scripting.
Who: Lars
2.17 List names of actions
Want: The user can list names of projects in a projects file.
Why: This is handy for checking and scripting.
Who: Lars
2.18 Cache persists between CI runs
Want: Cache data is persisted between CI runs.
Why: This allows incrementally building a project after changes.
Who: Lars
projects:
hello:
image: ambient.qcow2
source: srcdir
plan:
- action: shell
shell: |
cache=/workspace/cache
counter="$cache/counter"
if [ -e "$counter" ]; then
n="$(cat "$counter")"
n=$((n + 1))
echo "$n" > "$counter"
else
echo 1 > "$counter"
fi
echo "counter is now $(cat "$counter")."
find "$cache" -ls
2.19 Publish files via rsync
Want: Artifacts can be published via rsync to a server.
Why: This allows publishing many kinds of things.
Who: Lars
projects:
hello:
image: ambient.qcow2
source: srcdir
plan:
- action: shell
shell: |
echo hello, world > /workspace/artifacts/hello.txt
post_plan:
- action: rsync
2.20 Check that http_get doesn't allow duplicate filenames
Want: The http_get action should now allow duplicate filenames.
Why: It's helpful to catch errors early.
Who: Lars
projects:
hello:
image: ambient.qcow2
source: srcdir
pre_plan:
- action: http_get
items:
- url: http://example.com/foo
filename: xyzzy
- url: http://example.com/bar
filename: xyzzy
2.21 Allow bad plans by turning off linting
Want: The user should allow turning off the linter.
Why: If the linter is wrong for any reason, CI must still run.
Who: Lars
Note that this scenario relies on the http_get_duplicates.yaml embedded file
to trigger a lint.
lint: false
2.22 Verify an image is acceptable to Ambient
2.23 Manage VM images
Want: ambient has an image store and the user can manage
images in the image store via the tool.
Why: A user may need to have many images, perhaps with different operating systems or versions of thereof, or with different dependencies installed.
2.24 Handles symlinks in source tree
Want: When constructing the source tree for the VM, ambient does
not follow symbolic links.
Why: We don't want a project to create a link a file outside the source, but we do want to handle broken links. These are both best handled by not following symbolic links, when constructing the tar archive of the source tree.
projects:
hello:
image: ambient.qcow2
source: srcdir
plan:
- action: shell
shell: |
find . -ls
3 Acceptance criteria for ambient-execute-plan
ambient-execute-plan is the program that executes actions inside the
virtual machine, specifically actions in the "runnable plan". The
scenarios in this chapter verify that it work, without having to run a
full virtual machine to do so.
3.1 Default log level is trace
Want: The default log level of ambient-execute-plan is TRACE.
Why: This means we get the all the log output we can, which is useful for remote debugging.
3.2 Fails if an action fails
Want: If an action fails, ambient-execute-plan should fail and not
execute any later actions.
Why: Need this so that if something fails, a CI run will fail. This scenario
only verifies that the ambient-execute-plan program fails.
We use a shell and an mkdir action for this. One executes an other program (the
shell) and the other is implemented by ambient-execute-plan itself. If both work as
they should, we assume the rest of the actions are OK too.
steps:
- action: shell
shell: |
echo shell-action A
exit 1
- action: shell
shell: |
echo shell-action B
exit 1
source_dir: .
deps_dir: .
artifacts_dir: .
steps:
- action: mkdir
pathname: /not-allowed
- action: shell
shell: |
echo shell-action B
exit 1
source_dir: .
deps_dir: .
artifacts_dir: .
3.3 Executes shell action
Want: action-execute-plan can execute a shell action with a
shell script snippet.
steps:
- action: shell
shell: |
echo hello, world
source_dir: .
deps_dir: .
artifacts_dir: .
3.4 Executes pwd action
Want: action-execute-plan can execute a pwd action.
steps: - action: pwd source_dir: . deps_dir: . artifacts_dir: .
3.5 Executes mkdir action
Want: action-execute-plan can execute a mkdir action.
Why: This is needed to set up the VM environment for running CI.
steps:
- action: mkdir
pathname: xyzzy
- action: shell
shell: |
find -type d
source_dir: .
deps_dir: .
artifacts_dir: .
3.6 Executes tar_create and tar_extract actions
Want: action-execute-plan can execute a tar_create action and
its complement tar_extract.
Why: This is needed to set up the VM environment for running CI.
steps: - action: tar_create archive: tar.tar directory: data - action: tar_extract archive: tar.tar directory: data2 source_dir: . deps_dir: . artifacts_dir: .
3.7 Executes a custom action
Want: action-execute-plan can execute a custom action provided in
the source tree under test.
Why: This allows actions not built into Ambient.
steps:
- action: custom
name: hello
args:
greeting: hey
whom: there
source_dir: .
deps_dir: .
artifacts_dir: .
#!/bin/sh args="$(cat)" greeting="$(echo -n "$args" | jq -r .greeting)" whom="$(echo -n "$args" | jq -r .whom)" echo "$greeting $whom"
3.8 Fails if a custom action fails
Want: action-execute-plan fails if a script for the custom
action fails.
steps:
- action: custom
name: hello
args:
greeting: hey
whom: there
source_dir: .
deps_dir: .
artifacts_dir: .
#!/bin/sh exit 1 ~~