Merge pull request #1940 from grouville/particubes-doc
docs: Use Case - Go on Docker Swarm
This commit is contained in:
commit
d8fbbf5055
@ -0,0 +1,20 @@
|
||||
build: {
|
||||
luaDocs: docker.#Dockerfile & {
|
||||
source: client.filesystem."./lua-docs".read.contents
|
||||
}
|
||||
|
||||
_addGithubSHA: core.#WriteFile & {
|
||||
input: luaDocs.output.rootfs
|
||||
path: "/www/github_sha.yml"
|
||||
contents: #"""
|
||||
keywords: ["particubes", "game", "mobile", "scripting", "cube", "voxel", "world", "docs"]
|
||||
title: "Github SHA"
|
||||
blocks:
|
||||
- text: "\#(client.env.GITHUB_SHA)"
|
||||
"""#
|
||||
}
|
||||
image: docker.#Image & {
|
||||
rootfs: _addGithubSHA.output
|
||||
config: luaDocs.output.config
|
||||
}
|
||||
}
|
20
docs/tests/use-cases/go-docker-swarm/client-api.cue.fragment
Normal file
20
docs/tests/use-cases/go-docker-swarm/client-api.cue.fragment
Normal file
@ -0,0 +1,20 @@
|
||||
package docs
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
client: {
|
||||
// Locally, manual source of the .env or install https://direnv.net
|
||||
env: {
|
||||
GITHUB_SHA: string
|
||||
SSH_PRIVATE_KEY_DOCKER_SWARM: dagger.#Secret
|
||||
}
|
||||
filesystem: {
|
||||
"./": read: contents: dagger.#FS
|
||||
"./merge.output": write: contents: actions.build.image.rootfs // Creates a build artifact for debug
|
||||
}
|
||||
network: "unix:///var/run/docker.sock": connect: dagger.#Socket // Docker daemon socket
|
||||
}
|
||||
}
|
158
docs/tests/use-cases/go-docker-swarm/full/particubes.docs.cue
Normal file
158
docs/tests/use-cases/go-docker-swarm/full/particubes.docs.cue
Normal file
@ -0,0 +1,158 @@
|
||||
package docs
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"dagger.io/dagger/core"
|
||||
|
||||
"universe.dagger.io/alpine"
|
||||
"universe.dagger.io/bash"
|
||||
"universe.dagger.io/docker"
|
||||
"universe.dagger.io/docker/cli"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
client: {
|
||||
// Locally, manual source of the .env or install https://direnv.net
|
||||
env: {
|
||||
GITHUB_SHA: string
|
||||
SSH_PRIVATE_KEY_DOCKER_SWARM: dagger.#Secret
|
||||
}
|
||||
filesystem: {
|
||||
"./": read: contents: dagger.#FS
|
||||
"./merge.output": write: contents: actions.build.image.rootfs // Creates a build artifact for debug
|
||||
}
|
||||
network: "unix:///var/run/docker.sock": connect: dagger.#Socket // Docker daemon socket
|
||||
}
|
||||
|
||||
actions: {
|
||||
params: image: {
|
||||
ref: "registry.particubes.com/lua-docs"
|
||||
tag: "latest"
|
||||
localTag: "test-particubes" // name of the image when being run locally
|
||||
}
|
||||
|
||||
_dockerCLI: alpine.#Build & {
|
||||
packages: {
|
||||
bash: {}
|
||||
curl: {}
|
||||
"docker-cli": {}
|
||||
"openssh-client": {}
|
||||
}
|
||||
}
|
||||
|
||||
#_verifyGithubSHA: bash.#Run & {
|
||||
input: _dockerCLI.output
|
||||
env: GITHUB_SHA: client.env.GITHUB_SHA
|
||||
always: true
|
||||
script: contents: #"""
|
||||
TRIMMED_URL="$(echo $URL | cut -d '/' -f 1)"
|
||||
curl --verbose --fail --connect-timeout 5 --location "$URL" >"$TRIMMED_URL.curl.out" 2>&1
|
||||
|
||||
if ! grep "$GITHUB_SHA" "$TRIMMED_URL.curl.out"
|
||||
then
|
||||
echo "$GITHUB_SHA not present in the $TRIMMED_URL response:"
|
||||
cat "$TRIMMED_URL.curl.out"
|
||||
exit 1
|
||||
fi
|
||||
"""#
|
||||
}
|
||||
|
||||
build: {
|
||||
luaDocs: docker.#Dockerfile & {
|
||||
source: client.filesystem."./lua-docs".read.contents
|
||||
}
|
||||
|
||||
_addGithubSHA: core.#WriteFile & {
|
||||
input: luaDocs.output.rootfs
|
||||
path: "/www/github_sha.yml"
|
||||
contents: #"""
|
||||
keywords: ["particubes", "game", "mobile", "scripting", "cube", "voxel", "world", "docs"]
|
||||
title: "Github SHA"
|
||||
blocks:
|
||||
- text: "\#(client.env.GITHUB_SHA)"
|
||||
"""#
|
||||
}
|
||||
image: docker.#Image & {
|
||||
rootfs: _addGithubSHA.output
|
||||
config: luaDocs.output.config
|
||||
}
|
||||
}
|
||||
|
||||
clean: cli.#Run & {
|
||||
host: client.network."unix:///var/run/docker.sock".connect
|
||||
always: true
|
||||
env: IMAGE_NAME: params.image.localTag
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": #"""
|
||||
docker rm --force "$IMAGE_NAME"
|
||||
"""#
|
||||
}
|
||||
}
|
||||
|
||||
test: {
|
||||
preLoad: clean
|
||||
|
||||
load: cli.#Load & {
|
||||
image: build.image
|
||||
host: client.network."unix:///var/run/docker.sock".connect
|
||||
tag: params.image.localTag
|
||||
env: DEP: "\(preLoad.success)" // DEP created wth preLoad
|
||||
}
|
||||
|
||||
run: cli.#Run & {
|
||||
host: client.network."unix:///var/run/docker.sock".connect
|
||||
always: true
|
||||
env: {
|
||||
IMAGE_NAME: params.image.localTag
|
||||
PORTS: "80:80"
|
||||
DEP: "\(load.success)" // DEP created wth load
|
||||
}
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": #"""
|
||||
docker run -d --rm --name "$IMAGE_NAME" -p "$PORTS" "$IMAGE_NAME"
|
||||
"""#
|
||||
}
|
||||
}
|
||||
|
||||
verify: #_verifyGithubSHA & {
|
||||
env: {
|
||||
URL: "localhost/github_sha"
|
||||
DEP: "\(run.success)" // DEP created wth run
|
||||
}
|
||||
}
|
||||
|
||||
postVerify: clean & {
|
||||
env: DEP: "\(verify.success)" // DEP created wth verify
|
||||
}
|
||||
}
|
||||
|
||||
deploy: {
|
||||
publish: docker.#Push & {
|
||||
dest: "\(params.image.ref):\(params.image.tag)"
|
||||
image: build.image
|
||||
}
|
||||
|
||||
update: cli.#Run & {
|
||||
host: "ssh://ubuntu@3.139.83.217"
|
||||
always: true
|
||||
ssh: key: client.env.SSH_PRIVATE_KEY_DOCKER_SWARM
|
||||
env: DEP: "\(publish.result)" // DEP created wth publish
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": #"""
|
||||
docker service update --image registry.particubes.com/lua-docs:latest lua-docs
|
||||
"""#
|
||||
}
|
||||
}
|
||||
|
||||
verify: #_verifyGithubSHA & {
|
||||
env: {
|
||||
URL: "https://docs.particubes.com/github_sha"
|
||||
DEP: "\(update.success)" // DEP created wth run
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,116 +13,106 @@ They write primarily Go & Lua, push to GitHub and use GitHub Actions for automat
|
||||
The production setup is a multi-node Docker Swarm cluster running on AWS.
|
||||
|
||||
The Particubes team chose Dagger for continuous deployment because it was the easiest way of integrating GitHub with Docker Swarm.
|
||||
Every commit to the main branch goes straight to [docs.particubes.com](https://docs.particubes.com) via a Dagger pipeline that runs in GitHub Actions.
|
||||
`universe.dagger.io/docker` made building this pipeline trivial:
|
||||
Every commit to the main branch goes straight to [docs.particubes.com](https://docs.particubes.com) via a Dagger pipeline that runs in GitHub Actions. Let us see how the Particubes Dagger plan fits together.
|
||||
|
||||
:::danger
|
||||
TODO: this config is meta Europa, meaning that it was not tested. Next steps:
|
||||
### Actions API
|
||||
|
||||
- implement it in GitHub Actions and ensure that it all works as expected
|
||||
- update this meta config to the final version that we know works
|
||||
:::
|
||||
This is a high level overview of all actions in the Particubes docs Dagger plan:
|
||||
|
||||
```cue
|
||||
package particubes
|
||||
![particubes flat plan](/img/use-cases/particubes-actions.png)
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"dagger.io/dagger/core"
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
We can see all available actions in a Plan by running the following command:
|
||||
|
||||
dagger.#Plan & {
|
||||
inputs: {
|
||||
directories: src: path: "./lua-docs"
|
||||
secrets: docs: command: {
|
||||
name: "sops"
|
||||
args: ["-d", "../../lua-docs/sops_secrets.yaml"]
|
||||
}
|
||||
params: {
|
||||
image: ref: docker.#Ref | *"registry.particubes.com/lua-docs:latest"
|
||||
}
|
||||
}
|
||||
```bash
|
||||
$ dagger do
|
||||
Execute a dagger action.
|
||||
|
||||
actions: {
|
||||
docs: {
|
||||
// TODO: write GITHUB_SHA into a static /github_sha.txt
|
||||
build: docker.#Dockerfile & {
|
||||
source: inputs.directories.src.contents
|
||||
}
|
||||
|
||||
test: {
|
||||
// TODO:
|
||||
// - run container
|
||||
// - check http response code
|
||||
// - verify /github_sha.txt value matches GITHUB_SHA
|
||||
// - stop container
|
||||
}
|
||||
|
||||
push: docker.#Push & {
|
||||
dest: inputs.params.image.ref
|
||||
image: build.output
|
||||
}
|
||||
|
||||
docsSecrets: core.#DecodeSecret & {
|
||||
input: inputs.secrets.docs.contents
|
||||
format: "yaml"
|
||||
}
|
||||
deploy: {
|
||||
// TODO:
|
||||
// - run this command in the remote Docker Swarm
|
||||
// - secrests are ready in docsSecrets, e.g. docsSecrets.output.swarmKey.contents
|
||||
}
|
||||
|
||||
verifyDeploy: {
|
||||
// TODO:
|
||||
// - check http response code
|
||||
// - verify /github_sha.txt value matches GITHUB_SHA
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Available Actions:
|
||||
build Create a container image
|
||||
clean Remove a container image
|
||||
test Locally test a container image
|
||||
deploy Deploy a container image
|
||||
```
|
||||
|
||||
This is the GitHub Actions workflow config that invokes `dagger`, which in turn runs the above pipeline:
|
||||
### Client API
|
||||
|
||||
Dagger actions usually need to interact with the host environment where the Dagger client runs. The Particubes' plan uses environment variables and the filesystem.
|
||||
|
||||
This is an overview of all client interactions for this plan:
|
||||
|
||||
![Client API](/img/use-cases/client-api.png)
|
||||
|
||||
This is what the above looks like in the Dagger plan config:
|
||||
|
||||
```cue file=../tests/use-cases/go-docker-swarm/client-api.cue.fragment
|
||||
```
|
||||
|
||||
### The *build* Action
|
||||
|
||||
This is a more in-depth overview of the *build* action and how it interacts with the client in the Particubes docs Dagger plan:
|
||||
|
||||
![build action](/img/use-cases/build-action.png)
|
||||
|
||||
This is what the above looks like in the Dagger plan config:
|
||||
|
||||
```cue file=../tests/use-cases/go-docker-swarm/build-action.cue.fragment
|
||||
```
|
||||
|
||||
### Github Action integration
|
||||
|
||||
This is the GitHub Actions workflow config that invokes `dagger`, which in turn runs the full plan:
|
||||
|
||||
```yaml
|
||||
name: Dagger/docs.particubes.com
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GITHUB_SHA: ${{ github.sha }}
|
||||
SSH_PRIVATE_KEY_DOCKER_SWARM: ${{ secrets.SSH_PRIVATE_KEY_DOCKER_SWARM }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dagger
|
||||
uses: dagger/dagger-action@v2
|
||||
with:
|
||||
lfs: true
|
||||
// TODO: install sops
|
||||
- name: Dagger
|
||||
uses: dagger/dagger-action@v1
|
||||
with:
|
||||
age-key: ${{ secrets.DAGGER_AGE_KEY }}
|
||||
args: up
|
||||
install-only: true
|
||||
|
||||
- name: Dagger poject update
|
||||
run: dagger project update
|
||||
|
||||
- name: Dagger do test
|
||||
run: dagger do test --log-format plain
|
||||
|
||||
- name: Dagger do deploy
|
||||
run: dagger do deploy --log-format plain
|
||||
```
|
||||
|
||||
Since this is a Dagger pipeline, anyone on the team can run it locally with a single command:
|
||||
|
||||
```console
|
||||
dagger up
|
||||
dagger do
|
||||
```
|
||||
|
||||
This is the first step that enabled the Particubes team to have the same CI/CD experience everywhere.
|
||||
|
||||
We don't know what comes next for particubes.com, but we would like find out. Some ideas:
|
||||
### Full Particubes docs Dagger plan
|
||||
|
||||
- deploy particubes.com with Dagger
|
||||
- manage the Docker Swarm cluster with Dagger
|
||||
- contribute `universe.dagger.io/particubes` package
|
||||
This is the entire plan running on Particubes' CI:
|
||||
|
||||
```cue file=../tests/use-cases/go-docker-swarm/full/particubes.docs.cue
|
||||
```
|
||||
|
||||
### What comes next ?
|
||||
|
||||
Particubes' team suggested that we create a `dev` action with *hot reload*, that way Dagger would even asbtract away the ramp-up experience when developing the doc
|
||||
|
||||
:::tip
|
||||
The latest version of this pipeline can be found at [github.com/voxowl/particubes/lua-docs/docs.cue](https://github.com/voxowl/particubes/blob/b698777465c02462296de37087dd3c341c29df92/lua-docs/docs.cue)
|
||||
The latest version of this pipeline can be found at [github.com/voxowl/particubes/pull/144](https://github.com/voxowl/particubes/blob/2af173596729929cfb7a7a1f78f1ec0d8b685e5e/lua-docs/docs.cue)
|
||||
:::
|
||||
|
BIN
website/static/img/use-cases/build-action.png
Normal file
BIN
website/static/img/use-cases/build-action.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 442 KiB |
BIN
website/static/img/use-cases/client-api.png
Normal file
BIN
website/static/img/use-cases/client-api.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 254 KiB |
BIN
website/static/img/use-cases/particubes-actions.png
Normal file
BIN
website/static/img/use-cases/particubes-actions.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 188 KiB |
Reference in New Issue
Block a user