Skip to content

Commit

Permalink
feat: Unique app name (#2)
Browse files Browse the repository at this point in the history
Generate unique app name based on the repo infor
Add pre-validation step
Replace app name placeholder in configfiles automatically
  • Loading branch information
josedev-union authored Nov 8, 2023
1 parent 9ca2779 commit 97184ba
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM node:16.16.0-alpine3.16

LABEL org.opencontainers.image.source = "https://github.com/josedev-union/caprover-compose-action"

RUN apk add --no-cache git bash \
RUN apk add --no-cache curl git bash jq \
&& npm i -g caprover \
&& npm cache clean --force

Expand Down
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ 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.
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
{
"path": "/user/apps/appDefinitions/enablebasedomainssl",
"method": "POST",
"data": {
"appName": "$APP"
}
}
```

## Example compose context
Here is the example directory structure of a system consisting of multiple microservices.
Expand Down Expand Up @@ -54,11 +65,6 @@ This Github Action requires the following parameters;
- context

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

The name prefix for all applications in the compose.
Note: Some Caprover APIs require app name as a request parameter so when you prepare app configuration files, keep in mind that you have to set the app name correctly. `${prefix}-${app_directory_name}`
For example, you set `prefix` as `ci`, then the applications' names in the above example directory structure are `ci-frontend`, `ci-auth_api`, etc.

Example usage;
```yaml
Expand All @@ -79,5 +85,4 @@ jobs:
uses: josedev-union/caprover-compose-action@main
with:
server: https://captain.your-domain.com
prefix: ci
```
91 changes: 77 additions & 14 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,57 @@
#!/bin/bash
set -e
#!/bin/bash -e

# 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.

compose_ctx_path=${INPUT_CONTEXT:-.caprover}

########################### Global var def
COMPOSE_CTX_PATH=${INPUT_CONTEXT:-.caprover}
APP_NAME_PREFIX=${INPUT_PREFIX:-pr}
EVENT_ID=$(echo "$GITHUB_REF" | awk -F / '{print $3}')
## caprover cli config vars
export CAPROVER_URL=$INPUT_SERVER
export CAPROVER_PASSWORD=${INPUT_PASSWORD:-captain42}
export CAPROVER_NAME=default
# caprover login
## caprover api request vars
NS="x-namespace: captain"
CTYPE="Content-Type: application/json"
# getToken gets the token from Caprover API.
getToken() {
res=$(curl -sSf "$CAPROVER_URL/api/v2/login" -X POST -d '{"password":"'$CAPROVER_PASSWORD'"}' -H "$CTYPE" -H "$NS")
token=$(echo "$res"|awk -F'"token":"' '{print $2}'|awk -F'"' '{print $1}'|grep .)
echo $token
}
AUTH="x-captain-auth: $(getToken)"

########################### Function def

# waitApp waits until the app is ready.
#
# Arguments:
# $1: app name.
#
waitApp() {
app_name=$1
for i in $(seq 10); do
res=$(curl -sSf "$CAPROVER_URL/api/v2/user/apps/appData/$app_name" -H "$CTYPE" -H "$NS" -H "$AUTH")
echo $res|jq '.description' -r && echo "$res"|grep '"status":100,' >/dev/null
is_building=$(echo $res|jq '.data.isAppBuilding')
echo "App building: $is_building"
if [ "$is_building" == "false" ]; then
echo "App is ready now!"
break
else
echo "Waiting until ready (try: $i)"
sleep 10
fi
done
}

# setOutput does action output
setOutput() {
echo "${1}=${2}" >> "${GITHUB_OUTPUT}"
}
Expand All @@ -38,33 +77,57 @@ createApp() {
#
ensureSingleApp() {
app_ctx_path=${1}
app_name=${2}
echo "[app:$app_name] deployment step!";
app_alias=${2}
app_name=$(generateAppName ${2})
echo "[app:$app_alias] app name: $app_name";

# Deploy app
echo "[app:$app_alias] deployment step!";
set +e
res=$(caprover deploy --appName $app_name -c $app_ctx_path/captain-definition)
if [ $? -eq 0 ]; then
set -e
echo "[app:$app_name] successfully deployed! $res";
echo "$res";
echo "[app:$app_alias] successfully deployed!";
else
set -e
if [[ "$res" == *"not exist"* ]]; then
echo "[app:$app_name] create a new app!";
echo "[app:$app_alias] create a new app as it doesn't exist!";
createApp $app_name;
echo "[app:$app_name] deployment step!";
waitApp $app_name;
echo "[app:$app_alias] deployment step!";
caprover deploy --appName $app_name -c $app_ctx_path/captain-definition;
else
echo "::error::[app:$app_name]Caprover deploy failed."
echo "::error::[app:$app_alias]Caprover deploy failed."
exit 1;
fi
fi
echo "[app:$app_name] configuration step!";

# Configure app
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_name] - processing $f config file...";
echo "[app:$app_alias] - processing $f config file...";
sed -i "s/\$APP/$app_name/g" $f
caprover api -c $f
done
}

for app in $compose_ctx_path/*/; do
preValidate() {
# Allow only pull requests
if [ "${GITHUB_EVENT_NAME}" != "pull_request" ]
then
echo "This action only works in pull requests."
exit 0
fi
}

generateAppName() {
echo "${APP_NAME_PREFIX}-${GITHUB_REPOSITORY_ID}-${EVENT_ID}-${1}"
}

########################### Main
preValidate
for app in $COMPOSE_CTX_PATH/*/; do
echo "Deploying $(basename "$app") app...";
ensureSingleApp "${app}" "${INPUT_PREFIX}-$(basename $app)"
ensureSingleApp "${app}" "$(basename $app)"
done

0 comments on commit 97184ba

Please sign in to comment.