docs(website): restructure documentation and move content to dedicated pages
- Split README.md into usage.md and library.md for better organization - Move library section to its own page and update references - Rename "Usage" section to "Examples" in README.md - Update navigation links in base layout to reflect new structure - Fix typo in function definition in image/README.md - Add frontmatter to AGENTS.md for proper layout rendering - Update footer link from GitHub to Codeberg
This commit is contained in:
5 files changed
+340
-328
No files matched your search
@@ -20,31 +20,31 @@ It is to be understood as a software development pattern to standardize the inst
|
||||
|
||||
The specification is a short guide to set up a task file for a Python project.
|
||||
|
||||
- Create a file `task` in your project.
|
||||
Create a file `task` in your project.
|
||||
|
||||
```bash
|
||||
touch task
|
||||
```
|
||||
|
||||
- Ensure it is executable.
|
||||
Ensure it is executable.
|
||||
|
||||
```bash
|
||||
chmod +x task
|
||||
```
|
||||
|
||||
- First add the bash shebang.
|
||||
First add the bash shebang.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
```
|
||||
|
||||
- Then append the abort on error setting.
|
||||
Then append the abort on error setting.
|
||||
|
||||
```bash
|
||||
set -e
|
||||
```
|
||||
|
||||
- Load environment variables from the `.env` file.
|
||||
Load environment variables from the `.env` file.
|
||||
|
||||
```bash
|
||||
if [[ -a ".env" ]]; then
|
||||
@@ -52,7 +52,7 @@ if [[ -a ".env" ]]; then
|
||||
fi
|
||||
```
|
||||
|
||||
- Add a help function.
|
||||
Add a help function.
|
||||
|
||||
```bash
|
||||
help-table() {
|
||||
@@ -83,7 +83,7 @@ help() {
|
||||
}
|
||||
```
|
||||
|
||||
- Setup the command functions.
|
||||
Setup the command functions.
|
||||
|
||||
```bash
|
||||
version() {
|
||||
@@ -105,7 +105,7 @@ lint() {
|
||||
}
|
||||
```
|
||||
|
||||
- Finish the task file with command switch cases.
|
||||
Finish the task file with command switch cases.
|
||||
|
||||
```bash
|
||||
if declare -f "$1" > /dev/null; then
|
||||
@@ -127,17 +127,25 @@ fi
|
||||
|
||||
These are the main parts of every task file script.
|
||||
|
||||
## Examples
|
||||
Now see [usage](/usage) on how to use the task file.
|
||||
|
||||
Checkout these implementations of the task file standard:
|
||||
## Naming
|
||||
|
||||
- [janikvonrotz/dotfiles](https://codeberg.org/janikvonrotz/dotfiles/src/main/task)
|
||||
- [janikvonrotz/python.casa](https://codeberg.org/janikvonrotz/python.casa/src/main/task)
|
||||
- [Mint-System/Ansible-Build](https://github.com/Mint-System/Ansible-Build/blob/main/task)
|
||||
- [Mint-System/Kubernetes-Build](https://github.com/Mint-System/Kubernetes-Build/blob/main/task)
|
||||
- [Mint-System/Odoo-Build](https://github.com/Mint-System/Odoo-Build/blob/main/task)
|
||||
- [Mint-System/Odoo-Wiki](https://github.com/Mint-Wiki/Odoo-Build/blob/main/task)
|
||||
- [Mint-System/Website](https://github.com/Mint-System/Website/blob/main/task)
|
||||
- [Mint-System/Wiki](https://github.com/Mint-System/Wiki/blob/main/task)
|
||||
The naming of functions is important. There are basically two styles:
|
||||
|
||||
This website is built with a `task` file. Here is the source: [janikvonrotz/taskfile.build](https://codeberg.org/janikvonrotz/taskfile.build/src/branch/main/task)
|
||||
1. Action + Object
|
||||
2. Object + Action
|
||||
|
||||
The task file functions use the first style. The name of the function starts with an action followed by an object. The object name can be singular or plural.
|
||||
|
||||
**Examples for actions**: <span id="actions">activate, install, dev, develop, init, build, start, update, remove, delete, enable, disable, template, convert, create, edit, change, get, set, patch, fetch, generate, push, pull, import, export, list, publish, release, test, setup, prepare, restart, stop, store, restore, translate, upgrade, zip, visualize, sync, switch, run, reset, load, dump, checkout, commit, drop, deploy, handle, trigger, render, lint, uninstall, split, parse, fix, refactor, transform, cat, ls, rm, serve, help, show, filter, login, logout, encrypt, decrypt, upload, download, analyse, transpile, compile, minify, copy</span>
|
||||
|
||||
**Examples for objects**: <span id="objects">env, venv, submodule, container, database, snippet, model, module, repo, mail, doc, dependency, view, user, vault, file, host, node, log, password, hash, script, requirement, part, component, system, workspace, image, process, state, platform, dir, folder, readme, overview, lang, level, request, response, result, worker, server, proxy, workflow, volume, network, package, field, value, secret, chart, node, edge, function, method, firewall, html, css, image, svg, style, query, native, group, notebook</span>
|
||||
|
||||
**Objects can be tools**: <span id="object-tools">odoo, vupress, nodejs, zsh, bash, fish, podman, kind, minikube, helm, nvim, docker, podman, rust, python, tmux, vim, helix, system, git, pass, llm, sql, dotenv, javascript, vue, vite, astro, typescript, turbo, pnpm, eslint, jenkins, k8s, nextcloud, postgres, metabase, ansible, prometheus, grafana, hugo, deno, bun, babel, panda, gulp, grunt, electron, react, express, mongodb, angular, ionic, meteor, webpack, bower, jupyter</span>
|
||||
|
||||
<button id="generate-function-names">Generate Function Names</button> <ul id="function-names"> <!-- Random function names will be inserted here by JS --> </ul>
|
||||
|
||||
## Style
|
||||
|
||||
The bash scripts follow the [Bash Style Guide | ysap.sh](https://style.ysap.sh/). Have a look at the [AGENTS.md](/AGENTS) for details on the applied styling.
|
||||
@@ -28,11 +28,10 @@
|
||||
<li><strong><a class="contrast" href="/"><img width="50px" src="/img/logo.png" /> taskfile.build</a></strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a class="contrast" href="/#specification">Specification</a></li>
|
||||
<li><a class="contrast" href="/">Specification</a></li>
|
||||
<li><a class="contrast" href="/usage/">Usage</a></li>
|
||||
<li><a class="contrast" href="/usage/#naming">Naming</a></li>
|
||||
<li><a class="contrast" href="/usage/#patterns">Patterns</a></li>
|
||||
<li><a class="contrast" href="/#examples">Examples</a></li>
|
||||
<li><a class="contrast" href="/patterns">Patterns</a></li>
|
||||
<li><a class="contrast" href="/examples">Examples</a></li>
|
||||
<li><a class="contrast" href="/library">Library</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
---
|
||||
layout: layouts/base.njk
|
||||
---
|
||||
|
||||
# Examples
|
||||
|
||||
Checkout these implementations of the task file standard:
|
||||
|
||||
- [janikvonrotz/dotfiles](https://codeberg.org/janikvonrotz/dotfiles/src/main/task)
|
||||
- [janikvonrotz/python.casa](https://codeberg.org/janikvonrotz/python.casa/src/main/task)
|
||||
- [Mint-System/Ansible-Build](https://github.com/Mint-System/Ansible-Build/blob/main/task)
|
||||
- [Mint-System/Kubernetes-Build](https://github.com/Mint-System/Kubernetes-Build/blob/main/task)
|
||||
- [Mint-System/Odoo-Build](https://github.com/Mint-System/Odoo-Build/blob/main/task)
|
||||
- [Mint-System/Odoo-Wiki](https://github.com/Mint-Wiki/Odoo-Build/blob/main/task)
|
||||
- [Mint-System/Website](https://github.com/Mint-System/Website/blob/main/task)
|
||||
- [Mint-System/Wiki](https://github.com/Mint-System/Wiki/blob/main/task)
|
||||
|
||||
This website is built with a `task` file. Here is the source: [janikvonrotz/taskfile.build](https://codeberg.org/janikvonrotz/taskfile.build/src/branch/main/task)
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
---
|
||||
layout: layouts/base.njk
|
||||
---
|
||||
|
||||
# Patterns
|
||||
|
||||
The task file from the specification is very basic. Commands can also have parameters and call each other.
|
||||
|
||||
The following is a collection of more complex task file patterns.
|
||||
|
||||
## Set default parameter
|
||||
|
||||
Fallback to a default value for a parameter.
|
||||
|
||||
```bash
|
||||
build() {
|
||||
local platform="amd64"
|
||||
if [[ -n "$1" ]]; then
|
||||
platform="$1"
|
||||
fi
|
||||
```
|
||||
|
||||
## Ensure parameter is not empty
|
||||
|
||||
Check the first param and exit if it is empty.
|
||||
|
||||
```bash
|
||||
deploy() {
|
||||
if [[ -z "$1" ]]; then echo "\$1 is empty."; exit; fi
|
||||
```
|
||||
|
||||
## Prompt for input
|
||||
|
||||
Use `read` to ask for inputs.
|
||||
|
||||
```bash
|
||||
if [[ -z "$2" ]]; then
|
||||
read -p "Enter the task description: " task_description
|
||||
else
|
||||
task_description="$2"
|
||||
fi
|
||||
```
|
||||
|
||||
## Setup local env vars
|
||||
|
||||
Define env vars at the beginning of the task file.
|
||||
|
||||
```bash
|
||||
CONFIGURATION_FILE="file.conf"
|
||||
GIT_BRANCH=$(git symbolic-ref --short -q HEAD)
|
||||
```
|
||||
|
||||
## Template with env vars
|
||||
|
||||
Create a parameterized file from a template. Requires `envsubst`.
|
||||
|
||||
```bash
|
||||
template-with-env() {
|
||||
echo "Template $CONFIGURATION_FILE"
|
||||
|
||||
export CONFIGURATION_1
|
||||
export CONFIGURATION_2=${CONFIGURATION_2:="value"}
|
||||
|
||||
envsubst < "file.conf.template" > "$CONFIGURATION_FILE"
|
||||
}
|
||||
```
|
||||
|
||||
## Create Python virtual env
|
||||
|
||||
Initialize Python virtual env with uv.
|
||||
|
||||
```bash
|
||||
init-venv() {
|
||||
if [[ ! -d "venv$GIT_BRANCH" ]]; then
|
||||
echo "Init venv$GIT_BRANCH with $(uv --version)."
|
||||
uv venv "venv$GIT_BRANCH"
|
||||
fi
|
||||
}
|
||||
```
|
||||
|
||||
## Activate Python virtual env
|
||||
|
||||
```bash
|
||||
activate-venv() {
|
||||
echo "Source virtualenv venv$GIT_BRANCH."
|
||||
source "venv$GIT_BRANCH/bin/activate"
|
||||
echo "$(python --version) is active."
|
||||
}
|
||||
```
|
||||
|
||||
## Call a Python script
|
||||
|
||||
Run a Python script.
|
||||
|
||||
```bash
|
||||
generate-password-hash() {
|
||||
activate-venv
|
||||
if [[ -z "$1" ]]; then echo "\$1 is empty."; exit; fi
|
||||
export PASSWORD_PLAIN="$1"
|
||||
bin/password-hash
|
||||
}
|
||||
```
|
||||
|
||||
The Python script: `bin/password-hash`
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
from passlib.context import CryptContext
|
||||
crypt_context = CryptContext(schemes=['pbkdf2_sha512', 'plaintext'], deprecated=['plaintext'])
|
||||
|
||||
password = os.environ.get('PASSWORD_PLAIN')
|
||||
print(crypt_context.hash(password))
|
||||
```
|
||||
|
||||
## Command with named parameters
|
||||
|
||||
Assuming you have a `docker-compose.yml` and would like to start selected or all containers.
|
||||
|
||||
```bash
|
||||
start() {
|
||||
if [[ "$1" =~ "db" ]]; then
|
||||
docker compose up -d db
|
||||
fi
|
||||
|
||||
if [[ "$1" =~ "admin" ]]; then
|
||||
docker compose up -d admin
|
||||
echo "Open http://localhost:8000 url in your browser."
|
||||
fi
|
||||
|
||||
if [[ "$1" =~ "odoo" ]]; then
|
||||
docker compose up -d odoo
|
||||
echo "Open http://localhost:8069 url in your browser."
|
||||
fi
|
||||
|
||||
if [[ "$1" =~ "mail" ]]; then
|
||||
docker compose up -d mail
|
||||
echo "Open http://localhost:8025 url in your browser."
|
||||
fi
|
||||
}
|
||||
```
|
||||
|
||||
Start all containers with `task start` and selected with `task start db,admin`.
|
||||
|
||||
## Run commands in container
|
||||
|
||||
Use `docker exec -i` to run commands in a container.
|
||||
|
||||
```bash
|
||||
drop-db() {
|
||||
local database="$1"
|
||||
if [[ -z "$database" ]]; then
|
||||
database="example"
|
||||
fi
|
||||
|
||||
docker exec -i db psql "postgres://odoo:odoo@localhost:5432/postgres" -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$database';"
|
||||
docker exec -i db psql "postgres://odoo:odoo@localhost:5432/postgres" -c "DROP DATABASE \"$database\";"
|
||||
}
|
||||
```
|
||||
|
||||
## Loop over files and folders
|
||||
|
||||
Use `for` to loop over file, folders or arrays.
|
||||
|
||||
```bash
|
||||
render() {
|
||||
echo "Update index.html for all folders"
|
||||
for folder in ./*; do
|
||||
if [[ -f "$folder/README.md" ]]; then
|
||||
cd "$folder" || exit
|
||||
md2html README.md _site/index.html
|
||||
cd .. || exit
|
||||
fi
|
||||
done
|
||||
}
|
||||
```
|
||||
|
||||
## Parse and convert a file
|
||||
|
||||
With this function you can split a file into multiple parts whenever a specific keyword is matching. In this example the keyword is `!vault`.
|
||||
|
||||
```bash
|
||||
convert-vault-file() {
|
||||
local file_path="$1"
|
||||
local temp_file=$(mktemp)
|
||||
local temp_part_file=$(mktemp)
|
||||
local write_finished=false
|
||||
local current_key=""
|
||||
|
||||
while IFS= read -r line; do
|
||||
# Check for keyword
|
||||
if [[ "$line" =~ "!vault" ]]; then
|
||||
# Process previous vault entry if it exists
|
||||
if [[ "$write_finished" = true ]] && [[ -n "$current_key" ]] && [[ -s "$temp_part_file" ]]; then
|
||||
# Decrypt part file and write to assemble file
|
||||
ansible-vault decrypt "$temp_part_file"
|
||||
local value=$(cat "$temp_part_file")
|
||||
echo "$current_key: $value" >> "$temp_file"
|
||||
fi
|
||||
|
||||
# Set up for new vault entry
|
||||
current_key=$(echo "$line" | cut -d':' -f1)
|
||||
# Clear the file
|
||||
: > "$temp_part_file"
|
||||
# Flag as ready to write
|
||||
write_finished=true
|
||||
else
|
||||
if [[ "$write_finished" = true ]]; then
|
||||
# Pipe into part file
|
||||
echo "$line" >> "$temp_part_file"
|
||||
fi
|
||||
done
|
||||
done < "$file_path"
|
||||
|
||||
# Process the final vault entry
|
||||
if [[ "$write_finished" = true ]] && [[ -n "$current_key" ]] && [[ -s "$temp_part_file" ]]; then
|
||||
ansible-vault decrypt "$temp_part_file"
|
||||
local value=$(cat "$temp_part_file")
|
||||
echo "$current_key: $value" >> "$temp_file"
|
||||
fi
|
||||
|
||||
# Output assembled file
|
||||
cat "$temp_file"
|
||||
# Cleanup temp files
|
||||
rm -f "$temp_file"
|
||||
rm -f "$temp_part_file"
|
||||
}
|
||||
```
|
||||
|
||||
## Process data
|
||||
|
||||
This pattern tries to match the worklow of a jupyter notebook. Create a folder with the data processing scripts:
|
||||
|
||||
```
|
||||
scripts
|
||||
├── 01_import-mail-data
|
||||
├── 02_transform-mail-data
|
||||
└── 03_export-mail-data
|
||||
```
|
||||
|
||||
The following function lists the scripts and asks for the number of scripts to run. Every script until the entered number is concatenated and executed.
|
||||
|
||||
```bash
|
||||
process-data() {
|
||||
while true; do
|
||||
local scripts=($(ls scripts))
|
||||
|
||||
echo -e "Available scripts:\n"
|
||||
for index in "${!scripts[@]}"; do
|
||||
echo "$((index+1)): ${scripts[$index]}"
|
||||
done
|
||||
echo ""
|
||||
read -p "Enter the number of scripts to run (or 'q' to quit): " user_input
|
||||
if [[ "$user_input" = "q" ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
local temp_file=$(mktemp)
|
||||
for index in "${!scripts[@]}"; do
|
||||
if (( $user_input >= $((index+1)) )); then
|
||||
cat "scripts/${scripts[$index]}" >> "$temp_file"
|
||||
echo >> "$temp_file"
|
||||
fi
|
||||
done
|
||||
|
||||
clear
|
||||
echo -e "\nPython Output:\n\n---"
|
||||
python "$temp_file"
|
||||
local exit_code=$?
|
||||
echo -e "---\n"
|
||||
echo -e "Exit code: $exit_code\n"
|
||||
rm "$temp_file"
|
||||
done
|
||||
}
|
||||
```
|
||||
@@ -4,312 +4,15 @@ layout: layouts/base.njk
|
||||
|
||||
# Usage
|
||||
|
||||
Running the task file requires a shell alias: `alias task='./task'`\
|
||||
Show the available commands with `task help`.\
|
||||
From the specification the project can be installed with `task install`.\
|
||||
Running the task file requires a shell alias: `alias task='./task'`
|
||||
|
||||
Show the available commands with `task help`.
|
||||
|
||||
From the specification the project can be installed with `task install`.
|
||||
|
||||
Execute all commands with `task all`.
|
||||
|
||||
## Image
|
||||
|
||||
See [taskfile.build/image](/image) for details.
|
||||
|
||||
## Naming
|
||||
|
||||
The naming of functions is important. There are basically two styles:
|
||||
|
||||
1. Action + Object
|
||||
2. Object + Action
|
||||
|
||||
The task file functions use the first style. The name of the function starts with an action followed by an object. The object name can be singular or plural.
|
||||
|
||||
**Examples for actions**: <span id="actions">activate, install, dev, develop, init, build, start, update, remove, delete, enable, disable, template, convert, create, edit, change, get, set, patch, fetch, generate, push, pull, import, export, list, publish, release, test, setup, prepare, restart, stop, store, restore, translate, upgrade, zip, visualize, sync, switch, run, reset, load, dump, checkout, commit, drop, deploy, handle, trigger, render, lint, uninstall, split, parse, fix, refactor, transform, cat, ls, rm, serve, help, show, filter, login, logout, encrypt, decrypt, upload, download, analyse, transpile, compile, minify, copy</span>
|
||||
|
||||
**Examples for objects**: <span id="objects">env, venv, submodule, container, database, snippet, model, module, repo, mail, doc, dependency, view, user, vault, file, host, node, log, password, hash, script, requirement, part, component, system, workspace, image, process, state, platform, dir, folder, readme, overview, lang, level, request, response, result, worker, server, proxy, workflow, volume, network, package, field, value, secret, chart, node, edge, function, method, firewall, html, css, image, svg, style, query, native, group, notebook</span>
|
||||
|
||||
**Objects can be tools**: <span id="object-tools">odoo, vupress, nodejs, zsh, bash, fish, podman, kind, minikube, helm, nvim, docker, podman, rust, python, tmux, vim, helix, system, git, pass, llm, sql, dotenv, javascript, vue, vite, astro, typescript, turbo, pnpm, eslint, jenkins, k8s, nextcloud, postgres, metabase, ansible, prometheus, grafana, hugo, deno, bun, babel, panda, gulp, grunt, electron, react, express, mongodb, angular, ionic, meteor, webpack, bower, jupyter</span>
|
||||
|
||||
<button id="generate-function-names">Generate Function Names</button> <ul id="function-names"> <!-- Random function names will be inserted here by JS --> </ul>
|
||||
|
||||
## Style
|
||||
|
||||
The bash scripts follow the [Bash Style Guide | ysap.sh](https://style.ysap.sh/). Have a look at the [AGENTS.md](/AGENTS) for details on the applied styling.
|
||||
|
||||
## Patterns
|
||||
|
||||
The task file showed above is very basic. Commands can have parameters and call each other. The following is a collection of more complex task file patterns.
|
||||
|
||||
### Set default parameter
|
||||
|
||||
Fallback to a default value for a parameter.
|
||||
|
||||
```bash
|
||||
build() {
|
||||
local platform="amd64"
|
||||
if [[ -n "$1" ]]; then
|
||||
platform="$1"
|
||||
fi
|
||||
```
|
||||
|
||||
### Ensure parameter is not empty
|
||||
|
||||
Check the first param and exit if it is empty.
|
||||
|
||||
```bash
|
||||
deploy() {
|
||||
if [[ -z "$1" ]]; then echo "\$1 is empty."; exit; fi
|
||||
```
|
||||
|
||||
### Prompt for input
|
||||
|
||||
Use `read` to ask for inputs.
|
||||
|
||||
```bash
|
||||
if [[ -z "$2" ]]; then
|
||||
read -p "Enter the task description: " task_description
|
||||
else
|
||||
task_description="$2"
|
||||
fi
|
||||
```
|
||||
|
||||
### Setup local env vars
|
||||
|
||||
Define env vars at the beginning of the task file.
|
||||
|
||||
```bash
|
||||
CONFIGURATION_FILE="file.conf"
|
||||
GIT_BRANCH=$(git symbolic-ref --short -q HEAD)
|
||||
```
|
||||
|
||||
### Template with env vars
|
||||
|
||||
Create a parameterized file from a template. Requires `envsubst`.
|
||||
|
||||
```bash
|
||||
template-with-env() {
|
||||
echo "Template $CONFIGURATION_FILE"
|
||||
|
||||
export CONFIGURATION_1
|
||||
export CONFIGURATION_2=${CONFIGURATION_2:="value"}
|
||||
|
||||
envsubst < "file.conf.template" > "$CONFIGURATION_FILE"
|
||||
}
|
||||
```
|
||||
|
||||
### Create Python virtual env
|
||||
|
||||
Initialize Python virtual env with uv.
|
||||
|
||||
```bash
|
||||
init-venv() {
|
||||
if [[ ! -d "venv$GIT_BRANCH" ]]; then
|
||||
echo "Init venv$GIT_BRANCH with $(uv --version)."
|
||||
uv venv "venv$GIT_BRANCH"
|
||||
fi
|
||||
}
|
||||
```
|
||||
|
||||
### Activate Python virtual env
|
||||
|
||||
```bash
|
||||
activate-venv() {
|
||||
echo "Source virtualenv venv$GIT_BRANCH."
|
||||
source "venv$GIT_BRANCH/bin/activate"
|
||||
echo "$(python --version) is active."
|
||||
}
|
||||
```
|
||||
|
||||
### Call a Python script
|
||||
|
||||
Run a Python script.
|
||||
|
||||
```bash
|
||||
generate-password-hash() {
|
||||
activate-venv
|
||||
if [[ -z "$1" ]]; then echo "\$1 is empty."; exit; fi
|
||||
export PASSWORD_PLAIN="$1"
|
||||
bin/password-hash
|
||||
}
|
||||
```
|
||||
|
||||
The Python script: `bin/password-hash`
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
from passlib.context import CryptContext
|
||||
crypt_context = CryptContext(schemes=['pbkdf2_sha512', 'plaintext'], deprecated=['plaintext'])
|
||||
|
||||
password = os.environ.get('PASSWORD_PLAIN')
|
||||
print(crypt_context.hash(password))
|
||||
```
|
||||
|
||||
### Command with named parameters
|
||||
|
||||
Assuming you have a `docker-compose.yml` and would like to start selected or all containers.
|
||||
|
||||
```bash
|
||||
start() {
|
||||
if [[ "$1" =~ "db" ]]; then
|
||||
docker compose up -d db
|
||||
fi
|
||||
|
||||
if [[ "$1" =~ "admin" ]]; then
|
||||
docker compose up -d admin
|
||||
echo "Open http://localhost:8000 url in your browser."
|
||||
fi
|
||||
|
||||
if [[ "$1" =~ "odoo" ]]; then
|
||||
docker compose up -d odoo
|
||||
echo "Open http://localhost:8069 url in your browser."
|
||||
fi
|
||||
|
||||
if [[ "$1" =~ "mail" ]]; then
|
||||
docker compose up -d mail
|
||||
echo "Open http://localhost:8025 url in your browser."
|
||||
fi
|
||||
}
|
||||
```
|
||||
|
||||
Start all containers with `task start` and selected with `task start db,admin`.
|
||||
|
||||
### Run commands in container
|
||||
|
||||
Use `docker exec -i` to run commands in a container.
|
||||
|
||||
```bash
|
||||
drop-db() {
|
||||
local database="$1"
|
||||
if [[ -z "$database" ]]; then
|
||||
database="example"
|
||||
fi
|
||||
|
||||
docker exec -i db psql "postgres://odoo:odoo@localhost:5432/postgres" -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$database';"
|
||||
docker exec -i db psql "postgres://odoo:odoo@localhost:5432/postgres" -c "DROP DATABASE \"$database\";"
|
||||
}
|
||||
```
|
||||
|
||||
### Loop over files and folders
|
||||
|
||||
Use `for` to loop over file, folders or arrays.
|
||||
|
||||
```bash
|
||||
render() {
|
||||
echo "Update index.html for all folders"
|
||||
for folder in ./*; do
|
||||
if [[ -f "$folder/README.md" ]]; then
|
||||
cd "$folder" || exit
|
||||
md2html README.md _site/index.html
|
||||
cd .. || exit
|
||||
fi
|
||||
done
|
||||
}
|
||||
```
|
||||
|
||||
### Parse and convert a file
|
||||
|
||||
With this function you can split a file into multiple parts whenever a specific keyword is matching. In this example the keyword is `!vault`.
|
||||
|
||||
```bash
|
||||
convert-vault-file() {
|
||||
local file_path="$1"
|
||||
local temp_file=$(mktemp)
|
||||
local temp_part_file=$(mktemp)
|
||||
local write_finished=false
|
||||
local current_key=""
|
||||
|
||||
while IFS= read -r line; do
|
||||
# Check for keyword
|
||||
if [[ "$line" =~ "!vault" ]]; then
|
||||
# Process previous vault entry if it exists
|
||||
if [[ "$write_finished" = true ]] && [[ -n "$current_key" ]] && [[ -s "$temp_part_file" ]]; then
|
||||
# Decrypt part file and write to assemble file
|
||||
ansible-vault decrypt "$temp_part_file"
|
||||
local value=$(cat "$temp_part_file")
|
||||
echo "$current_key: $value" >> "$temp_file"
|
||||
fi
|
||||
|
||||
# Set up for new vault entry
|
||||
current_key=$(echo "$line" | cut -d':' -f1)
|
||||
# Clear the file
|
||||
: > "$temp_part_file"
|
||||
# Flag as ready to write
|
||||
write_finished=true
|
||||
else
|
||||
if [[ "$write_finished" = true ]]; then
|
||||
# Pipe into part file
|
||||
echo "$line" >> "$temp_part_file"
|
||||
fi
|
||||
done
|
||||
done < "$file_path"
|
||||
|
||||
# Process the final vault entry
|
||||
if [[ "$write_finished" = true ]] && [[ -n "$current_key" ]] && [[ -s "$temp_part_file" ]]; then
|
||||
ansible-vault decrypt "$temp_part_file"
|
||||
local value=$(cat "$temp_part_file")
|
||||
echo "$current_key: $value" >> "$temp_file"
|
||||
fi
|
||||
|
||||
# Output assembled file
|
||||
cat "$temp_file"
|
||||
# Cleanup temp files
|
||||
rm -f "$temp_file"
|
||||
rm -f "$temp_part_file"
|
||||
}
|
||||
```
|
||||
|
||||
### Process data
|
||||
|
||||
This pattern tries to match the worklow of a jupyter notebook. Create a folder with the data processing scripts:
|
||||
|
||||
```
|
||||
scripts
|
||||
├── 01_import-mail-data
|
||||
├── 02_transform-mail-data
|
||||
└── 03_export-mail-data
|
||||
```
|
||||
|
||||
The following function lists the scripts and asks for the number of scripts to run. Every script until the entered number is concatenated and executed.
|
||||
|
||||
```bash
|
||||
process-data() {
|
||||
while true; do
|
||||
local scripts=($(ls scripts))
|
||||
|
||||
echo -e "Available scripts:\n"
|
||||
for index in "${!scripts[@]}"; do
|
||||
echo "$((index+1)): ${scripts[$index]}"
|
||||
done
|
||||
echo ""
|
||||
read -p "Enter the number of scripts to run (or 'q' to quit): " user_input
|
||||
if [[ "$user_input" = "q" ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
local temp_file=$(mktemp)
|
||||
for index in "${!scripts[@]}"; do
|
||||
if (( $user_input >= $((index+1)) )); then
|
||||
cat "scripts/${scripts[$index]}" >> "$temp_file"
|
||||
echo >> "$temp_file"
|
||||
fi
|
||||
done
|
||||
|
||||
clear
|
||||
echo -e "\nPython Output:\n\n---"
|
||||
python "$temp_file"
|
||||
local exit_code=$?
|
||||
echo -e "---\n"
|
||||
echo -e "Exit code: $exit_code\n"
|
||||
rm "$temp_file"
|
||||
done
|
||||
}
|
||||
```
|
||||
|
||||
## Integration
|
||||
|
||||
The task file is intended to be integrated into the shell setup. Where applications provides a domain specific language (DSL) ensure that the DSL only calls the task file.
|
||||
|
||||
### Completion
|
||||
## Completion
|
||||
|
||||
With the output of `task help` the task commands can be completed.
|
||||
|
||||
@@ -356,6 +59,14 @@ esac
|
||||
|
||||
The completion also works for task alias `alias t='./task'`.
|
||||
|
||||
## Image
|
||||
|
||||
See [taskfile.build/image](/image) for details.
|
||||
|
||||
## Integration
|
||||
|
||||
The task file is intended to be integrated into the shell setup. Whenever an applicatio uses a domain specific language (DSL) ensure that the DSL calls the task file. Most you'll see DSLs to describe build pipelines.
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
Running task file commands in GitHub Actions is highly recommended. This way you can run the same CI/CD procedures in the GitHub runner as you do on your localhost.
|
||||
@@ -417,4 +128,4 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}%
|
||||
```
|
||||
```
|
||||
Reference in new issue
Block a user