Skip to content

Commit

Permalink
feat: Support env vars and app deletion (#3)
Browse files Browse the repository at this point in the history
- support env var translation
- support app deletion
- update doc
  • Loading branch information
josedev-union authored Nov 10, 2023
1 parent 97184ba commit 4d700bb
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 39 deletions.
91 changes: 59 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ As Caprover doesn't support docker-compose stil([link](https://caprover.com/docs

- First, in the compose context dir(configurable by `context` parameter), create one directory per one application. Directory name is used as the application name.
- In each application folder, create a `captain_definition` file. This will be used for application deployment.
- Also in the same folder, you can create `json` or `yml` files to configure the application. The file format should follow Caprover configuration file for consuming Caprover API([link](https://github.com/caprover/caprover-cli/tree/master#api)). These files are applied to the application in the order of their names using `caprover api` command.
- In each application folder, you can also create `json` or `yml` files to configure the application. The file format should follow Caprover configuration file for consuming Caprover API([link](https://github.com/caprover/caprover-cli/tree/master#api)). These files are applied to the application in the order of their names using `caprover api` command.
Note: If Caprover configuration file includes application name, please use `$APP` as application name because a unique application name is generated per a pull request.
For example, this is a Caprover configuration file to enable SSL.
```json
# 01_enable_ssl.json
{
"path": "/user/apps/appDefinitions/enablebasedomainssl",
"method": "POST",
Expand All @@ -17,6 +18,52 @@ For example, this is a Caprover configuration file to enable SSL.
}
}
```
- In each application folder, you can also create `.env` file to set environment variables for the app.
```txt
# .env
KEY1=VALUE1
KEY2=VALUE2
...
```

## Action parameters
This Github Action requires the following parameters;
- server

Captain server url. For example, https://captain.your-domain.com.
- password

Captain password.
- context

The path of definition and configuration files of applications. Optional. Default: `.caprover/`
- prefix

Prefix of Caprover app names. Optional. Default: `pr`
- keep

It specifies whether to keep or remove the Caprover applicationswhen the workflow is finished. Optional. Default: `true`

Example usage;
```yaml
name: Container image

on:
pull_request:
branches: ["main"]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout project
uses: actions/checkout@v3

- name: Deploy caprover
uses: josedev-union/caprover-compose-action@main
with:
server: https://captain.your-domain.com
```
## Example compose context
Here is the example directory structure of a system consisting of multiple microservices.
Expand Down Expand Up @@ -54,35 +101,15 @@ Example configuration file `01_enable_ssl.json`;
}
```

## Action parameters
This Github Action requires the following parameters;
- server

Captain server url. For example, https://captain.your-domain.com.
- password

Captain password.
- context

The path of definition and configuration files of applications. Optional. Default: `.caprover/`

Example usage;
```yaml
name: Container image

on:
pull_request:
branches: ["main"]
## Caprover Application name
Caprover deploys applications on Docker and container names are based on application names. So it requires application names to be unique. To make sure the application names are unique across all git repositories, this action generates application names as following;
`${PREFIX}-${REPOSITORY_ID}-${EVENT_ID}-${APP_CONTEXT_DIRECTORY_NAME}`.
- `PREFIX`: `prefix` action parameter
- `REPOSITORY_ID`: Git repository unique id
- `EVENT_ID`: Git event unique id. It varies depending on even types
- Pull requests: pull request number
- Push: branch name
- Tag: tag
- `APP_CONTEXT_DIRECTORY_NAME`: dir name for an application in `context` path

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout project
uses: actions/checkout@v3

- name: Deploy caprover
uses: josedev-union/caprover-compose-action@main
with:
server: https://captain.your-domain.com
```
For example, `pr-715000497-2-frontend`
10 changes: 8 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ inputs:
required: true
context:
description: 'The path of app config and def files'
required: true
default: '.caprover'
prefix:
description: 'The prefix of app name'
required: true
default: 'pr'
keep:
description: 'Specify whether to keep the deployment or not. If false, the deployment will be deleted.'
default: 'true'
options:
- 'true'
- 'false'

runs:
using: 'docker'
Expand Down
79 changes: 74 additions & 5 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

# TODO(joseb):
# 1. Convert to python. ref: https://github.com/ak4zh/Caprover-API
# 2. Exception handling. This will be much easier with python sdk.
# 3. Set output, like app url etc. This will be much easier with python sdk.
# 4. App name validation
# 5. Generate prefix based on the git ref automatically if not presented.
# 2. Set output, like app url etc. This will be much easier with python sdk.
# 3. App name validation


########################### Global var def
COMPOSE_CTX_PATH=${INPUT_CONTEXT:-.caprover}
APP_NAME_PREFIX=${INPUT_PREFIX:-pr}
EVENT_ID=$(echo "$GITHUB_REF" | awk -F / '{print $3}')
KEEP_APP=${INPUT_KEEP:-"true"}
## caprover cli config vars
export CAPROVER_URL=$INPUT_SERVER
export CAPROVER_PASSWORD=${INPUT_PASSWORD:-captain42}
Expand Down Expand Up @@ -69,6 +68,37 @@ createApp() {
--data "{\"appName\":\"${app_name}\",\"hasPersistentData\":false}"
}

renderConfigTemplate() {
app_name=${1}
tpl_path=${2}
sed -i "s/\$APP/$app_name/g" $tpl_path
}

# setAppEnvVars converts .env file to json and sets environment variables for a Caprover app.
#
# Arguments:
# $1: app name.
# $2: path to the environment variables file.
#
setAppEnvVars() {
app_name=${1}
env_file_path=${2}
# CRLF to LF
tmp_env_path=$(mktemp)
tr -d '\015' < $env_file_path > $tmp_env_path
env_data=$(echo $(
for i in $(cat $tmp_env_path|awk -F"=" '{print $1}'); do
val=$(awk -F"=" -v i="$i" '{ if ($1==i) print }' $tmp_env_path|sed "s/^$i=//");
echo '{"key":"'$i'","value":"'$val'"},';
done
) | sed 's/.$//')

caprover api \
--path "/user/apps/appDefinitions/update" \
--method "POST" \
--data "{\"appName\":\"${app_name}\",\"envVars\":[${env_data}]}"
}

# ensureSingleApp deploy and configure a single Caprover app.
#
# Arguments:
Expand Down Expand Up @@ -107,9 +137,36 @@ ensureSingleApp() {
echo "[app:$app_alias] configuration step!";
for f in $(find $app_ctx_path/ -type f | egrep -i 'yml|yaml|json' | sort); do
echo "[app:$app_alias] - processing $f config file...";
sed -i "s/\$APP/$app_name/g" $f
renderConfigTemplate $app_name $f
caprover api -c $f
done
if [ -f $app_ctx_path/.env ]; then
echo "[app:$app_alias] - seting env vars...";
setAppEnvVars $app_name $app_ctx_path/.env
fi

# Output app name
setOutput "$app_alias" "$(echo $CAPROVER_URL | sed -e "s/:\/\/captain./:\/\/$app_name./g")"
}

deleteSingleApp() {
app_alias=${1}
app_name=$(generateAppName ${2})
echo "[app:$app_alias] app name: $app_name";

# Scale down instance number to zero
echo "[app:$app_alias] scaling down instance number to zero...";
caprover api \
--path "/user/apps/appDefinitions/update" \
--method "POST" \
--data "{\"appName\":\"${app_name}\",\"instanceCount\":0}"

# Delete app
echo "[app:$app_alias] deleting app...";
caprover api \
--path "/user/apps/appDefinitions/delete" \
--method "POST" \
--data "{\"appName\":\"${app_name}\"}"
}

preValidate() {
Expand All @@ -126,8 +183,20 @@ generateAppName() {
}

########################### Main
# 1. validate the request
preValidate

# 2. Deploy
for app in $COMPOSE_CTX_PATH/*/; do
echo "Deploying $(basename "$app") app...";
ensureSingleApp "${app}" "$(basename $app)"
done

# 3. Destroy
if [ "$KEEP_APP" == "false" ]; then
for app in $COMPOSE_CTX_PATH/*/; do
echo "Removing $(basename "$app") app...";
# Ignore errors during the deletion
deleteSingleApp "${app}" "$(basename $app)" || true
done
fi

0 comments on commit 4d700bb

Please sign in to comment.