universe.dagger.io/examples/changelog.com: cleanup and fixes

Signed-off-by: Solomon Hykes <solomon@dagger.io>
This commit is contained in:
Solomon Hykes 2022-02-09 01:51:57 +00:00
parent 80f9a65ca7
commit 5a1ce0acac
10 changed files with 282 additions and 252 deletions

View File

@ -40,7 +40,7 @@ test_db_container_name: "changelog_test_postgres"
// - caching is buildkit layers // - caching is buildkit layers
// //
// 3. Open Telemetry integration out-of-the-box // 3. Open Telemetry integration out-of-the-box
// - visualize all steps in Jaeger UI // - visualise all steps in Jaeger UI
// PIPELINE OVERVIEW ########################################################### // PIPELINE OVERVIEW ###########################################################
// //

View File

@ -0,0 +1,101 @@
package changelog
actions: {
// Reuse in all mix commands
// prod: assets: docker.#Build & {
// steps: [
// // 1. Start from dev assets :)
// dev.assets,
// // 2. Mix magical command
// mix.#Run & {
// script: "mix phx.digest"
// mix: {
// env: "prod"
// app: _appName
// depsCache: "private"
// buildCache: "private"
// }
// workdir: _
// // FIXME: remove copy-pasta
// mounts: nodeModules: {
// contents: engine.#CacheDir & {
// // FIXME: do we need an ID here?
// id: "\(mix.app)_assets_node_modules"
// // FIXME: does this command need write access to node_modules cache?
// concurrency: "private"
// }
// dest: "\(workdir)/node_modules"
// }
// },
// ]
// }
// dev: {
// compile: mix.#Compile & {
// env: "dev"
// app: "thechangelog"
// base: inputs.params.runtimeImage
// source: inputs.directories.app.contents
// }
// assets: docker.#Build & {
// steps: [
// // 1. Start from dev runtime build
// {
// output: build.output
// },
// // 2. Build web assets
// mix.#Run & {
// mix: {
// env: "dev"
// app: _appName
// depsCache: "private"
// buildCache: "private"
// }
// // FIXME: move this to a reusable def (yarn package? or private?)
// mounts: nodeModules: {
// contents: engine.#CacheDir & {
// // FIXME: do we need an ID here?
// id: "\(mix.app)_assets_node_modules"
// // FIXME: will there be multiple writers?
// concurrency: "locked"
// }
// dest: "\(workdir)/node_modules"
// }
// // FIXME: run 'yarn install' and 'yarn run compile' separately, with different caching?
// // FIXME: can we reuse universe.dagger.io/yarn ???? 0:-)
// script: "yarn install --frozen-lockfile && yarn run compile"
// workdir: "/app/assets"
// },
// ]
// }
// }
// test: {
// build: mix.#Build & {
// env: "test"
// app: _appName
// base: inputs.params.runtimeImage
// source: inputs.directories.app.contents
// }
// // Run tests
// run: docker.#Run & {
// image: build.output
// script: "mix test"
// }
// db: {
// // Pull test DB image
// pull: docker.#Pull & {
// source: inputs.params.test_db_image
// }
// // Run test DB
// // FIXME: kill once no longer needed (when tests are done running)
// run: docker.#Run & {
// image: pull.output
// }
// }
// }
}

View File

@ -0,0 +1,88 @@
package mix
import (
"dagger.io/dagger"
"dagger.io/dagger/engine"
"universe.dagger.io/docker"
)
#Get: #Run & {
// Applies to all environments
env: null
cache: {
build: null
deps: "locked"
}
container: command: {
name: "sh"
flags: "-c": "mix do deps.compile, compile"
}
}
// Compile Elixir dependencies, including the app
#Compile: #Run & {
cache: {
build: "locked"
deps: "locked"
}
container: command: {
name: "sh"
flags: "-c": "mix do deps.compile, compile"
}
}
// Run mix task with all necessary mounts so compiled artefacts get cached
// FIXME: add default image to hexpm/elixir:1.13.2-erlang-23.3.4.11-debian-bullseye-20210902
#Run: {
app: {
// Application name
name: string
// Application source code
source: dagger.#FS
}
// Mix environment
env: string | null
// Configure mix caching
// FIXME: simpler interface, eg. "ro" | "rw"
cache: {
// Dependencies cache
deps: null | "locked"
// Build cache
build: null | "locked"
}
// Run mix in a docker container
container: docker.#Run & {
if env != null {
"env": MIX_ENV: env
}
workdir: mounts.app.dest
mounts: "app": {
contents: app.source
dest: "/mix/app"
}
if cache.deps != null {
mounts: deps: {
contents: engine.#CacheDir & {
id: "\(app.name)_deps"
concurrency: cache.deps
}
dest: "\(mounts.app.dest)/deps"
}
}
if cache.build != null {
mounts: buildCache: {
contents: engine.#CacheDir & {
id: "\(app.name)_build_\(env)"
concurrency: cache.build
}
dest: "\(mounts.app.dest)/_build/\(env)"
}
}
}
}

View File

@ -0,0 +1,9 @@
package changelog
import (
"dagger.io/dagger"
)
dagger.#Plan & {
inputs: directories: app: path: "/Users/gerhard/github.com/thechangelog/changelog.com/"
}

View File

@ -1,147 +0,0 @@
package ci
import (
"dagger.io/dagger"
"dagger.io/dagger/engine"
"universe.dagger.io/docker"
"universe.dagger.io/examples/changelog.com/highlevel/elixir/mix"
)
dagger.#Plan & {
// Receive things from client
inputs: {
directories: {
// App source code
app: _
}
secrets: {
// Docker ID password
docker: _
}
params: {
// Which Elixir base image to download
runtime_image: docker.#Ref | *"thechangelog/runtime:2021-05-29T10.17.12Z"
// Which test DB image to download
test_db_image: docker.#Ref | *"circleci/postgres:12.6"
}
}
// Do things
actions: {
// Reuse in all mix commands
_appName: "changelog"
prod: assets: docker.#Build & {
steps: [
// 1. Start from dev assets :)
dev.assets,
// 2. Mix magical command
mix.#Run & {
command: {
name: "mix"
args: ["phx.digest"]
}
mix: {
env: "prod"
app: _appName
depsCache: "private"
buildCache: "private"
}
workdir: _
// FIXME: remove copy-pasta
mounts: nodeModules: {
contents: engine.#CacheDir & {
// FIXME: do we need an ID here?
id: "\(mix.app)_assets_node_modules"
// FIXME: does this command need write access to node_modules cache?
concurrency: "private"
}
dest: "\(workdir)/node_modules"
}
},
]
}
dev: {
build: mix.#Build & {
env: "dev"
app: "thechangelog"
base: inputs.params.runtime_image
source: inputs.directories.app.contents
}
assets: docker.#Build & {
steps: [
// 1. Start from dev runtime build
{
output: build.output
},
// 2. Build web assets
mix.#Run & {
mix: {
env: "dev"
app: _appName
depsCache: "private"
buildCache: "private"
}
// FIXME: move this to a reusable def (yarn package? or private?)
mounts: nodeModules: {
contents: engine.#CacheDir & {
// FIXME: do we need an ID here?
id: "\(mix.app)_assets_node_modules"
// FIXME: will there be multiple writers?
concurrency: "locked"
}
dest: "\(workdir)/node_modules"
}
// FIXME: run 'yarn install' and 'yarn run compile' separately, with different caching?
// FIXME: can we reuse universe.dagger.io/yarn ???? 0:-)
command: {
name: "sh"
flags: "-c": """
yarn install --frozen-lockfile && yarn run compile"
"""
}
workdir: "/app/assets"
},
]
}
}
test: {
build: mix.#Build & {
env: "test"
app: _appName
base: inputs.params.runtime_image
source: inputs.directories.app.contents
}
// Run tests
run: docker.#Run & {
image: build.output
command: {
name: "mix"
args: ["test"]
}
// Don't cache running tests
// Just because we've tested a version before, doesn't mean we don't
// want to test it again.
// FIXME: make this configurable
always: true
}
db: {
// Pull test DB image
pull: docker.#Pull & {
source: inputs.params.test_db_image
}
// Run test DB
// FIXME: kill once no longer needed (when tests are done running)
run: docker.#Run & {
image: pull.output
}
}
}
}
}

View File

@ -1,101 +0,0 @@
package mix
import (
"dagger.io/dagger"
"dagger.io/dagger/engine"
"universe.dagger.io/docker"
)
// Build an Elixir application with Mix
#Build: {
// Ref to base image
// FIXME: spin out docker.#Build for max flexibility
// Perhaps implement as a custom docker.#Build step?
base: docker.#Ref
// App name (for cache scoping)
app: string
// Mix environment
env: string
// Application source code
source: dagger.#FS
docker.#Build & {
steps: [
// 1. Pull base image
docker.#Pull & {
source: base
},
// 2. Copy app source
docker.#Copy & {
contents: source
dest: "/app"
},
// 3. Download dependencies into deps cache
#Run & {
mix: {
"env": env
"app": app
depsCache: "locked"
}
workdir: "/app"
command: {
name: "mix"
args: ["deps.get"]
}
},
// 4. Build!
// FIXME: step 5 is to add image data, see issue 1339
#Run & {
mix: {
"env": env
"app": app
depsCache: "private"
buildCache: "locked"
}
workdir: "/app"
command: {
name: "mix"
args: ["do", "deps.compile,compile"]
}
},
]
}
}
// Run mix correctly in a container
#Run: {
mix: {
app: string
env: string
// FIXME: "ro" | "rw"
depsCache?: "private" | "locked"
buildCache?: "private" | "locked"
}
docker.#Run
env: MIX_ENV: mix.env
workdir: string
{
mix: depsCache: string
mounts: depsCache: {
contents: engine.#CacheDir & {
id: "\(mix.app)_deps"
concurrency: mix.depsCache
}
dest: "\(workdir)/deps"
}
} | {}
{
mix: buildCache: string
mounts: buildCache: {
contents: engine.#CacheDir & {
id: "\(mix.app)_deps"
concurrency: mix.buildCache
}
dest: "\(workdir)/deps"
}
} | {}
}

View File

@ -1,3 +0,0 @@
package ci
inputs: directories: app: path: "/Users/gerhard/github.com/thechangelog/changelog.com/"

View File

@ -0,0 +1,83 @@
package changelog
import (
"dagger.io/dagger"
"universe.dagger.io/docker"
"universe.dagger.io/git"
"universe.dagger.io/examples/changelog.com/elixir/mix"
)
dagger.#Plan & {
// Receive things from client
inputs: {
directories: {
// App source code
app?: _
}
secrets: {
// Docker ID password
docker: _
}
params: {
app: {
// App name
name: string | *"changelog"
// Address of app base image
image: docker.#Ref | *"thechangelog/runtime:2021-05-29T10.17.12Z"
}
test: {
// Address of test db image
db: image: docker.#Ref | *"circleci/postgres:12.6"
}
}
}
// Do things
actions: {
app: {
name: inputs.params.app.name
// changelog.com source code
source: dagger.#FS
if inputs.directories.app != _|_ {
source: inputs.directories.app.contents
}
if inputs.directories.app == _|_ {
fetch: git.#Pull & {
remote: "https://github.com/thechangelog/changelog.com"
ref: "master"
}
source: fetch.output
}
// Assemble base image
_pull: docker.#Pull & {
source: inputs.params.app.image
}
image: _pull.output
// Download Elixir dependencies
deps: mix.#Get & {
app: {
"name": name
"source": source
}
container: "image": image
}
// Compile dev environment
dev: mix.#Compile & {
env: "dev"
app: {
"name": name
"source": source
}
container: "image": image
}
}
}
}