ToolJet/.github/workflows/render-preview-deploy.yml

1442 lines
52 KiB
YAML

name: Render review deploy
on:
pull_request_target:
types: [labeled, unlabeled, closed, synchronize, opened]
issue_comment:
types: [created, edited, deleted]
env:
PR_NUMBER: ${{ github.event.number }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
permissions:
pull-requests: write
issues: write
jobs:
# Community Edition CE
create-ce-review-app:
if: ${{ github.event.action == 'labeled' && (github.event.label.name == 'create-ce-review-app' || github.event.label.name == 'review-app') }}
runs-on: ubuntu-latest
steps:
- name: Sync repo
uses: actions/checkout@v3
- name: Check if Forked Repository
id: check_repo
run: |
if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then
echo "is_fork=true" >> $GITHUB_ENV
echo "FORKED_OWNER=${{ github.event.pull_request.head.repo.owner.login }}" >> $GITHUB_ENV
else
echo "is_fork=false" >> $GITHUB_ENV
fi
- name: Set Repository URL
run: |
if [[ "$is_fork" == "true" ]]; then
echo "REPO_URL=https://github.com/${FORKED_OWNER}/ToolJet" >> $GITHUB_ENV
else
echo "REPO_URL=https://github.com/ToolJet/ToolJet" >> $GITHUB_ENV
fi
- name: Fetch and Checkout Forked Branch
if: env.is_fork == 'true'
run: |
git fetch origin pull/${{ github.event.number }}/head:${{ env.BRANCH_NAME }}
git checkout ${{ env.BRANCH_NAME }}
- name: Checkout Default Branch
if: env.is_fork == 'false'
uses: actions/checkout@v3
- name: Creating deployment for CE
id: create-ce-deployment
run: |
export RESPONSE=$(curl --request POST \
--url https://api.render.com/v1/services \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Authorization: Bearer ${{ secrets.RENDER_API_KEY }}' \
--data '
{
"autoDeploy": "yes",
"branch": "${{ env.BRANCH_NAME }}",
"name": "ToolJet CE PR #${{ env.PR_NUMBER }}",
"notifyOnFail": "default",
"ownerId": "tea-caeo4bj19n072h3dddc0",
"repo": "'"$REPO_URL"'",
"slug": "tooljet-ce-pr-${{ env.PR_NUMBER }}",
"suspended": "not_suspended",
"suspenders": [],
"type": "web_service",
"envVars": [
{
"key": "PG_HOST",
"value": "localhost"
},
{
"key": "PG_PORT",
"value": "5432"
},
{
"key": "PG_USER",
"value": "postgres"
},
{
"key": "PG_PASS",
"value": "postgres"
},
{
"key": "PG_DB",
"value": "${{ env.PR_NUMBER }}-ce"
},
{
"key": "TOOLJET_DB",
"value": "${{ env.PR_NUMBER }}-ce-tjdb"
},
{
"key": "TOOLJET_DB_HOST",
"value": "localhost"
},
{
"key": "TOOLJET_DB_USER",
"value": "postgres"
},
{
"key": "TOOLJET_DB_PASS",
"value": "postgres"
},
{
"key": "TOOLJET_DB_PORT",
"value": "5432"
},
{
"key": "PGRST_DB_PRE_CONFIG",
"value": "postgrest.pre_config"
},
{
"key": "PGRST_DB_URI",
"value": "postgres://postgres:postgres@localhost/${{ env.PR_NUMBER }}-ce-tjdb"
},
{
"key": "PGRST_HOST",
"value": "127.0.0.1:3000"
},
{
"key": "PGRST_JWT_SECRET",
"value": "r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj"
},
{
"key": "PGRST_LOG_LEVEL",
"value": "info"
},
{
"key": "PORT",
"value": "80"
},
{
"key": "TOOLJET_HOST",
"value": "https://tooljet-ce-pr-${{ env.PR_NUMBER }}.onrender.com"
},
{
"key": "DISABLE_TOOLJET_TELEMETRY",
"value": "true"
},
{
"key": "SMTP_ADDRESS",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_DOMAIN",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_PORT",
"value": "2525"
},
{
"key": "SMTP_USERNAME",
"value": "${{ secrets.RENDER_SMTP_USERNAME }}"
},
{
"key": "SMTP_PASSWORD",
"value": "${{ secrets.RENDER_SMTP_PASSWORD }}"
},
{
"key": "TOOLJET_MARKETPLACE_URL",
"value": "${{ secrets.MARKETPLACE_BUCKET }}"
}
],
"serviceDetails": {
"disk": {
"name": "tooljet-ce-pr-${{ env.PR_NUMBER }}-postgresql",
"mountPath": "/var/lib/postgresql/13/main",
"sizeGB": 10
},
"env": "docker",
"envSpecificDetails": {
"dockerCommand": "",
"dockerContext": "./",
"dockerfilePath": "./docker/ce-preview.Dockerfile"
},
"healthCheckPath": "/api/health",
"numInstances": 1,
"openPorts": [{
"port": 80,
"protocol": "TCP"
}],
"plan": "standard",
"pullRequestPreviewsEnabled": "no",
"region": "oregon",
"url": "https://tooljet-ce-pr-${{ env.PR_NUMBER }}.onrender.com"
}
}')
echo "response: $RESPONSE"
export SERVICE_ID=$(echo $RESPONSE | jq -r '.service.id')
echo "SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
- name: Comment deployment URL
uses: actions/github-script@v5
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Community Edition:- \n Deployment: https://tooljet-ce-pr-${{ env.PR_NUMBER }}.onrender.com \n Dashboard: https://dashboard.render.com/web/${{ env.SERVICE_ID }}'
})
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'create-ce-review-app'
})
} catch (e) {
console.log(e)
}
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-ce-review-app']
})
destroy-ce-review-app:
if: ${{ (github.event.action == 'labeled' && github.event.label.name == 'destroy-ce-review-app') || github.event.action == 'closed' }}
runs-on: ubuntu-latest
steps:
- name: Delete service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request DELETE \
--url https://api.render.com/v1/services/$SERVICE_ID \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'destroy-ce-review-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-ce-review-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-ce-review-app'
})
} catch (e) {
console.log(e)
}
# - name: Install PostgreSQL client
# run: |
# sudo apt update
# sudo apt install postgresql-client -y
# - name: Wait after installing PostgreSQL
# run: sleep 25
# - name: Drop PostgreSQL PR databases
# env:
# PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
# PGPORT: 5432
# PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
# PGDATABASE: ${{ env.PR_NUMBER }}-ce
# PGTJBDATABASE: ${{ env.PR_NUMBER }}-ce-tjdb
# run: |
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
# echo "Database $PGDATABASE exists, deleting..."
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
# else
# echo "Database $PGDATABASE does not exist."
# fi
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
# echo "Database $PGTJBDATABASE exists, deleting..."
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
# else
# echo "Database $PGTJBDATABASE does not exist."
# fi
suspend-ce-review-app:
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ce-review-app' }}
runs-on: ubuntu-latest
steps:
- name: Suspend service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/suspend \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-ce-review-app'
})
} catch (e) {
console.log(e)
}
resume-ce-review-app:
if: ${{ github.event.action == 'unlabeled' && github.event.label.name == 'suspend-ce-review-app' }}
runs-on: ubuntu-latest
steps:
- name: Resume service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/resume \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-ce-review-app']
})
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-ce-review-app'
})
} catch (e) {
console.log(e)
}
# Enterprise Edition
create-ee-review-app:
if: ${{ github.event.action == 'labeled' && (github.event.label.name == 'create-ee-review-app' || github.event.label.name == 'review-app') }}
runs-on: ubuntu-latest
steps:
- name: Sync repo
uses: actions/checkout@v3
- name: Check if Forked Repository
id: check_repo
run: |
if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then
echo "is_fork=true" >> $GITHUB_ENV
echo "FORKED_OWNER=${{ github.event.pull_request.head.repo.owner.login }}" >> $GITHUB_ENV
else
echo "is_fork=false" >> $GITHUB_ENV
fi
- name: Set Repository URL
run: |
if [[ "$is_fork" == "true" ]]; then
echo "REPO_URL=https://github.com/${FORKED_OWNER}/ToolJet" >> $GITHUB_ENV
else
echo "REPO_URL=https://github.com/ToolJet/ToolJet" >> $GITHUB_ENV
fi
- name: Fetch and Checkout Forked Branch
if: env.is_fork == 'true'
run: |
git fetch origin pull/${{ github.event.number }}/head:${{ env.BRANCH_NAME }}
git checkout ${{ env.BRANCH_NAME }}
- name: Checkout Default Branch
if: env.is_fork == 'false'
uses: actions/checkout@v3
- name: Detect base branch and set Dockerfile path
run: |
BASE_BRANCH="${{ github.event.pull_request.base.ref }}"
echo "Base branch: $BASE_BRANCH"
if [[ "$BASE_BRANCH" == "main" || "$BASE_BRANCH" == release/* ]]; then
DOCKERFILE="./docker/pre-release/ee/ee-preview.Dockerfile"
echo "Using pre-release track"
elif [[ "$BASE_BRANCH" == "lts-3.16" || "$BASE_BRANCH" == release-lts/* ]]; then
DOCKERFILE="./docker/LTS/ee/ee-preview.Dockerfile"
echo "Using LTS track"
else
echo "Error: Unsupported base branch '$BASE_BRANCH'"
echo "Supported branches: main, release/*, lts-3.16, release-lts/*"
exit 1
fi
echo "Selected Dockerfile: $DOCKERFILE"
echo "DOCKERFILE=$DOCKERFILE" >> $GITHUB_ENV
- name: Creating deployment for Enterprise Edition
id: create-ee-deployment
run: |
export RESPONSE=$(curl --request POST \
--url https://api.render.com/v1/services \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Authorization: Bearer ${{ secrets.RENDER_API_KEY }}' \
--data '
{
"autoDeploy": "yes",
"branch": "${{ env.BRANCH_NAME }}",
"name": "ToolJet EE PR #${{ env.PR_NUMBER }}",
"notifyOnFail": "default",
"ownerId": "tea-caeo4bj19n072h3dddc0",
"repo": "'"$REPO_URL"'",
"slug": "tooljet-ee-pr-${{ env.PR_NUMBER }}",
"suspended": "not_suspended",
"suspenders": [],
"type": "web_service",
"envVars": [
{
"key": "PG_HOST",
"value": "localhost"
},
{
"key": "PG_PORT",
"value": "5432"
},
{
"key": "PG_USER",
"value": "postgres"
},
{
"key": "PG_PASS",
"value": "postgres"
},
{
"key": "PG_DB",
"value": "${{ env.PR_NUMBER }}-ee"
},
{
"key": "TOOLJET_DB",
"value": "${{ env.PR_NUMBER }}-ee-tjdb"
},
{
"key": "TOOLJET_DB_HOST",
"value": "localhost"
},
{
"key": "TOOLJET_DB_USER",
"value": "postgres"
},
{
"key": "TOOLJET_DB_PASS",
"value": "postgres"
},
{
"key": "TOOLJET_DB_PORT",
"value": "5432"
},
{
"key": "PGRST_DB_PRE_CONFIG",
"value": "postgrest.pre_config"
},
{
"key": "PGRST_DB_URI",
"value": "postgres://postgres:postgres@localhost/${{ env.PR_NUMBER }}-ee-tjdb"
},
{
"key": "PGRST_HOST",
"value": "127.0.0.1:3000"
},
{
"key": "PGRST_JWT_SECRET",
"value": "r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj"
},
{
"key": "PGRST_LOG_LEVEL",
"value": "info"
},
{
"key": "PORT",
"value": "80"
},
{
"key": "TOOLJET_HOST",
"value": "https://tooljet-ee-pr-${{ env.PR_NUMBER }}.onrender.com"
},
{
"key": "DISABLE_TOOLJET_TELEMETRY",
"value": "true"
},
{
"key": "SMTP_ADDRESS",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_DOMAIN",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_PORT",
"value": "2525"
},
{
"key": "SMTP_USERNAME",
"value": "${{ secrets.RENDER_SMTP_USERNAME }}"
},
{
"key": "SMTP_PASSWORD",
"value": "${{ secrets.RENDER_SMTP_PASSWORD }}"
},
{
"key": "REDIS_HOST",
"value": "${{ secrets.RENDER_REDIS_HOST }}"
},
{
"key": "REDIS_PORT",
"value": "${{ secrets.RENDER_REDIS_PORT }}"
},
{
"key": "TEMPORAL_SERVER_ADDRESS",
"value": "https://auto-setup-1-25-1.onrender.com"
},
{
"key": "TEMPORAL_TASK_QUEUE_NAME_FOR_WORKFLOWS",
"value": "tooljet-ee-pr-${{ env.PR_NUMBER }}"
},
{
"key": "TOOLJET_WORKFLOWS_TEMPORAL_NAMESPACE",
"value": "default"
},
{
"key": "TOOLJET_MARKETPLACE_URL",
"value": "${{ secrets.MARKETPLACE_BUCKET }}"
},
{
"key": "BRANCH_NAME",
"value": "${{ env.BRANCH_NAME }}"
},
{
"key": "REPO_URL",
"value": "${{ env.REPO_URL }}"
},
{
"key": "CUSTOM_GITHUB_TOKEN",
"value": "${{ secrets.CUSTOM_GITHUB_TOKEN }}"
}
],
"serviceDetails": {
"disk": {
"name": "tooljet-ee-pr-${{ env.PR_NUMBER }}-postgresql",
"mountPath": "/var/lib/postgresql/13/main",
"sizeGB": 10
},
"env": "docker",
"envSpecificDetails": {
"dockerCommand": "",
"dockerContext": "./",
"dockerfilePath": "'"$DOCKERFILE"'"
},
"healthCheckPath": "/api/health",
"numInstances": 1,
"openPorts": [{
"port": 80,
"protocol": "TCP"
}],
"plan": "pro",
"pullRequestPreviewsEnabled": "no",
"region": "oregon",
"url": "https://tooljet-ee-pr-${{ env.PR_NUMBER }}.onrender.com"
}
}')
echo "response: $RESPONSE"
export SERVICE_ID=$(echo $RESPONSE | jq -r '.service.id')
echo "SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
- name: Comment deployment URL
uses: actions/github-script@v5
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Enterpise Edition: \n Deployment: https://tooljet-ee-pr-${{ env.PR_NUMBER }}.onrender.com \n Dashboard: https://dashboard.render.com/web/${{ env.SERVICE_ID }}'
})
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'create-ee-review-app'
})
} catch (e) {
console.log(e)
}
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-ee-review-app']
})
destroy-ee-review-app:
if: ${{ (github.event.action == 'labeled' && github.event.label.name == 'destroy-ee-review-app') || github.event.action == 'closed' }}
runs-on: ubuntu-latest
steps:
- name: Delete service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request DELETE \
--url https://api.render.com/v1/services/$SERVICE_ID \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'destroy-ee-review-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-ee-review-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-ee-review-app'
})
} catch (e) {
console.log(e)
}
# - name: Install PostgreSQL client
# run: |
# sudo apt update
# sudo apt install postgresql-client -y
# - name: Wait after installing PostgreSQL
# run: sleep 25
# - name: Drop PostgreSQL PR databases
# env:
# PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
# PGPORT: 5432
# PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
# PGDATABASE: ${{ env.PR_NUMBER }}-ee
# PGTJBDATABASE: ${{ env.PR_NUMBER }}-ee-tjdb
# run: |
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
# echo "Database $PGDATABASE exists, deleting..."
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
# else
# echo "Database $PGDATABASE does not exist."
# fi
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
# echo "Database $PGTJBDATABASE exists, deleting..."
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
# else
# echo "Database $PGTJBDATABASE does not exist."
# fi
suspend-ee-review-app:
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ee-review-app' }}
runs-on: ubuntu-latest
steps:
- name: Suspend service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/suspend \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-ee-review-app'
})
} catch (e) {
console.log(e)
}
resume-ee-review-app:
if: ${{ github.event.action == 'unlabeled' && github.event.label.name == 'suspend-ee-review-app' }}
runs-on: ubuntu-latest
steps:
- name: Resume service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/resume \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-ee-review-app']
})
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-ee-review-app'
})
} catch (e) {
console.log(e)
}
# Cloud Edition
create-cloud-review-app:
if: ${{ github.event.action == 'labeled' && (github.event.label.name == 'create-cloud-review-app' || github.event.label.name == 'review-app') }}
runs-on: ubuntu-latest
steps:
- name: Sync repo
uses: actions/checkout@v3
- name: Check if Forked Repository
id: check_repo
run: |
if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then
echo "is_fork=true" >> $GITHUB_ENV
echo "FORKED_OWNER=${{ github.event.pull_request.head.repo.owner.login }}" >> $GITHUB_ENV
else
echo "is_fork=false" >> $GITHUB_ENV
fi
- name: Set Repository URL
run: |
if [[ "$is_fork" == "true" ]]; then
echo "REPO_URL=https://github.com/${FORKED_OWNER}/ToolJet" >> $GITHUB_ENV
else
echo "REPO_URL=https://github.com/ToolJet/ToolJet" >> $GITHUB_ENV
fi
- name: Fetch and Checkout Forked Branch
if: env.is_fork == 'true'
run: |
git fetch origin pull/${{ github.event.number }}/head:${{ env.BRANCH_NAME }}
git checkout ${{ env.BRANCH_NAME }}
- name: Checkout Default Branch
if: env.is_fork == 'false'
uses: actions/checkout@v3
- name: Creating deployment for Cloud Edition
id: create-cloud-deployment
run: |
export RESPONSE=$(curl --request POST \
--url https://api.render.com/v1/services \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Authorization: Bearer ${{ secrets.RENDER_API_KEY }}' \
--data '
{
"autoDeploy": "yes",
"branch": "${{ env.BRANCH_NAME }}",
"name": "ToolJet Cloud PR #${{ env.PR_NUMBER }}",
"notifyOnFail": "default",
"ownerId": "tea-caeo4bj19n072h3dddc0",
"repo": "'"$REPO_URL"'",
"slug": "tooljet-cloud-pr-${{ env.PR_NUMBER }}",
"suspended": "not_suspended",
"suspenders": [],
"type": "web_service",
"envVars": [
{
"key": "PG_HOST",
"value": "${{ secrets.RENDER_PG_HOST }}"
},
{
"key": "PG_PORT",
"value": "5432"
},
{
"key": "PG_USER",
"value": "${{ secrets.RENDER_PG_USER }}"
},
{
"key": "PG_PASS",
"value": "${{ secrets.RENDER_PG_PASS }}"
},
{
"key": "PG_DB",
"value": "${{ env.PR_NUMBER }}-cloud"
},
{
"key": "TOOLJET_DB",
"value": "${{ env.PR_NUMBER }}-cloud-tjdb"
},
{
"key": "TOOLJET_DB_HOST",
"value": "${{ secrets.RENDER_PG_HOST }}"
},
{
"key": "TOOLJET_DB_USER",
"value": "${{ secrets.RENDER_PG_USER }}"
},
{
"key": "TOOLJET_DB_PASS",
"value": "${{ secrets.RENDER_PG_PASS }}"
},
{
"key": "TOOLJET_DB_PORT",
"value": "5432"
},
{
"key": "PGRST_DB_PRE_CONFIG",
"value": "postgrest.pre_config"
},
{
"key": "PGRST_DB_URI",
"value": "postgres://${{ secrets.RENDER_PG_USER }}:${{ secrets.RENDER_PG_PASS }}@${{ secrets.RENDER_PG_HOST }}/${{ env.PR_NUMBER }}-cloud-tjdb"
},
{
"key": "PGRST_HOST",
"value": "127.0.0.1:3000"
},
{
"key": "PGRST_JWT_SECRET",
"value": "r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj"
},
{
"key": "PGRST_LOG_LEVEL",
"value": "info"
},
{
"key": "PORT",
"value": "80"
},
{
"key": "TOOLJET_HOST",
"value": "https://tooljet-cloud-pr-${{ env.PR_NUMBER }}.onrender.com"
},
{
"key": "DISABLE_TOOLJET_TELEMETRY",
"value": "true"
},
{
"key": "SMTP_ADDRESS",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_DOMAIN",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_PORT",
"value": "2525"
},
{
"key": "SMTP_USERNAME",
"value": "${{ secrets.RENDER_SMTP_USERNAME }}"
},
{
"key": "SMTP_PASSWORD",
"value": "${{ secrets.RENDER_SMTP_PASSWORD }}"
},
{
"key": "REDIS_HOST",
"value": "${{ secrets.RENDER_REDIS_HOST }}"
},
{
"key": "REDIS_PORT",
"value": "${{ secrets.RENDER_REDIS_PORT }}"
},
{
"key": "TEMPORAL_SERVER_ADDRESS",
"value": "https://auto-setup-1-25-1.onrender.com"
},
{
"key": "TEMPORAL_TASK_QUEUE_NAME_FOR_WORKFLOWS",
"value": "tooljet-cloud-pr-${{ env.PR_NUMBER }}"
},
{
"key": "TOOLJET_WORKFLOWS_TEMPORAL_NAMESPACE",
"value": "default"
},
{
"key": "TOOLJET_MARKETPLACE_URL",
"value": "${{ secrets.MARKETPLACE_BUCKET }}"
},
{
"key": "CUSTOM_GITHUB_TOKEN",
"value": "${{ secrets.CUSTOM_GITHUB_TOKEN }}"
}
],
"serviceDetails": {
"disk": null,
"env": "docker",
"envSpecificDetails": {
"dockerCommand": "",
"dockerContext": "./",
"dockerfilePath": "./docker/LTS/cloud/cloud-preview.Dockerfile"
},
"healthCheckPath": "/api/health",
"numInstances": 1,
"openPorts": [{
"port": 80,
"protocol": "TCP"
}],
"plan": "starter",
"pullRequestPreviewsEnabled": "no",
"region": "oregon",
"url": "https://tooljet-cloud-pr-${{ env.PR_NUMBER }}.onrender.com"
}
}')
echo "response: $RESPONSE"
export SERVICE_ID=$(echo $RESPONSE | jq -r '.service.id')
echo "SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
- name: Comment deployment URL
uses: actions/github-script@v5
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Cloud Edition: \n Deployment: https://tooljet-cloud-pr-${{ env.PR_NUMBER }}.onrender.com \n Dashboard: https://dashboard.render.com/web/${{ env.SERVICE_ID }}'
})
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'create-cloud-review-app'
})
} catch (e) {
console.log(e)
}
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-cloud-review-app']
})
destroy-cloud-review-app:
if: ${{ (github.event.action == 'labeled' && github.event.label.name == 'destroy-cloud-review-app') || github.event.action == 'closed' }}
runs-on: ubuntu-latest
steps:
- name: Delete service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request DELETE \
--url https://api.render.com/v1/services/$SERVICE_ID \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'destroy-cloud-review-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-cloud-review-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-cloud-review-app'
})
} catch (e) {
console.log(e)
}
# - name: Install PostgreSQL client
# run: |
# sudo apt update
# sudo apt install postgresql-client -y
# - name: Wait after installing PostgreSQL
# run: sleep 25
# - name: Drop PostgreSQL PR databases
# env:
# PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
# PGPORT: 5432
# PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
# PGDATABASE: ${{ env.PR_NUMBER }}-cloud
# PGTJBDATABASE: ${{ env.PR_NUMBER }}-cloud-tjdb
# run: |
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
# echo "Database $PGDATABASE exists, deleting..."
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
# else
# echo "Database $PGDATABASE does not exist."
# fi
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
# echo "Database $PGTJBDATABASE exists, deleting..."
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
# else
# echo "Database $PGTJBDATABASE does not exist."
# fi
suspend-cloud-review-app:
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-cloud-review-app' }}
runs-on: ubuntu-latest
steps:
- name: Suspend service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/suspend \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-cloud-review-app'
})
} catch (e) {
console.log(e)
}
resume-cloud-review-app:
if: ${{ github.event.action == 'unlabeled' && github.event.label.name == 'suspend-cloud-review-app' }}
runs-on: ubuntu-latest
steps:
- name: Resume service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/resume \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-cloud-review-app']
})
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-cloud-review-app'
})
} catch (e) {
console.log(e)
}
redeploy-review-app:
if: ${{ github.event.action == 'synchronize' || github.event.action == 'opened' }}
runs-on: ubuntu-latest
steps:
- name: Get PR labels
id: get_labels
uses: actions/github-script@v6
with:
script: |
const labels = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
return labels.data.map(l => l.name);
- name: Redeploy CE review app if active
if: contains(steps.get_labels.outputs.result, 'active-ce-review-app')
id: redeploy_ce
env:
RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
PR_NUMBER: ${{ github.event.number }}
run: |
SERVICE_ID=$(curl --request GET \
--url "https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${PR_NUMBER}&limit=1" \
--header 'accept: application/json' \
--header "authorization: Bearer $RENDER_API_KEY" | jq -r '.[0].service.id')
DEPLOY_RESPONSE=$(curl --request POST \
--url "https://api.render.com/v1/services/$SERVICE_ID/deploys" \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header "authorization: Bearer $RENDER_API_KEY" \
--data '{"clearCache":"clear"}')
DEPLOY_ID=$(echo $DEPLOY_RESPONSE | jq -r '.id')
echo "SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
echo "DEPLOY_ID=$DEPLOY_ID" >> $GITHUB_ENV
- name: Redeploy EE review app if active
if: contains(steps.get_labels.outputs.result, 'active-ee-review-app')
id: redeploy_ee
env:
RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
PR_NUMBER: ${{ github.event.number }}
run: |
SERVICE_ID=$(curl --request GET \
--url "https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${PR_NUMBER}&limit=1" \
--header 'accept: application/json' \
--header "authorization: Bearer $RENDER_API_KEY" | jq -r '.[0].service.id')
DEPLOY_RESPONSE=$(curl --request POST \
--url "https://api.render.com/v1/services/$SERVICE_ID/deploys" \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header "authorization: Bearer $RENDER_API_KEY" \
--data '{"clearCache":"clear"}')
DEPLOY_ID=$(echo $DEPLOY_RESPONSE | jq -r '.id')
echo "SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
echo "DEPLOY_ID=$DEPLOY_ID" >> $GITHUB_ENV
render-bot-check-deployment:
runs-on: ubuntu-latest
if: github.event.action == 'labeled' && github.event.label.name == 'render-check-deployment'
steps:
- name: Get PR labels
id: get_labels
uses: actions/github-script@v6
with:
script: |
const labels = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
return labels.data.map(l => l.name);
- name: Fetch CE service and deploy ID
run: |
response=$(curl --silent --request GET \
--url "https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${PR_NUMBER}&limit=1" \
--header 'accept: application/json' \
--header "authorization: Bearer $RENDER_API_KEY")
SERVICE_ID=$(echo "$response" | jq -r 'if type=="array" and length > 0 then .[0].service.id else empty end')
if [[ -z "$SERVICE_ID" ]]; then
echo "No CE service found for PR #$PR_NUMBER. Skipping deployment ID fetch."
exit 0
fi
response_deploy=$(curl --silent --request GET \
--url "https://api.render.com/v1/services/$SERVICE_ID/deploys?limit=1" \
--header 'accept: application/json' \
--header "authorization: Bearer $RENDER_API_KEY")
DEPLOY_ID=$(echo "$response_deploy" | jq -r 'if type=="array" and length > 0 then .[0].deploy.id else empty end')
echo "CE_SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
echo "CE_DEPLOY_ID=$DEPLOY_ID" >> $GITHUB_ENV
env:
PR_NUMBER: ${{ env.PR_NUMBER }}
RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
- name: Comment CE deployment details
uses: actions/github-script@v6
env:
PR_NUMBER: ${{ env.PR_NUMBER }}
RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = process.env.PR_NUMBER;
const apiKey = process.env.RENDER_API_KEY;
const ceServiceRes = await fetch(`https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${prNumber}&limit=1`, {
headers: {
'accept': 'application/json',
'authorization': `Bearer ${apiKey}`
}
});
const ceServices = await ceServiceRes.json();
const ceServiceId = ceServices[0]?.service?.id || null;
let ceInfo = 'No active CE review app deployment found.';
if (ceServiceId) {
const deployRes = await fetch(`https://api.render.com/v1/services/${ceServiceId}/deploys?limit=1`, {
headers: {
'accept': 'application/json',
'authorization': `Bearer ${apiKey}`
}
});
const deployData = await deployRes.json();
const deploy = deployData[0]?.deploy || {};
const ceCommit = deploy.commit || {};
const status = deploy.status || 'unknown';
ceInfo = `### Community Edition\n- App: https://tooljet-ce-pr-${prNumber}.onrender.com\n- Dashboard: https://dashboard.render.com/web/${ceServiceId}\n- Commit: ${ceCommit.id || ''}\n- Message: ${ceCommit.message || ''}\n- Status: ${status}`;
}
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: ceInfo
});
- name: Fetch EE service and deploy ID
run: |
response=$(curl --silent --request GET \
--url "https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${PR_NUMBER}&limit=1" \
--header 'accept: application/json' \
--header "authorization: Bearer $RENDER_API_KEY")
SERVICE_ID=$(echo "$response" | jq -r 'if type=="array" and length > 0 then .[0].service.id else empty end')
if [[ -z "$SERVICE_ID" ]]; then
echo "No EE service found for PR #$PR_NUMBER. Skipping deployment ID fetch."
exit 0
fi
response_deploy=$(curl --silent --request GET \
--url "https://api.render.com/v1/services/$SERVICE_ID/deploys?limit=1" \
--header 'accept: application/json' \
--header "authorization: Bearer $RENDER_API_KEY")
DEPLOY_ID=$(echo "$response_deploy" | jq -r 'if type=="array" and length > 0 then .[0].deploy.id else empty end')
echo "EE_SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
echo "EE_DEPLOY_ID=$DEPLOY_ID" >> $GITHUB_ENV
env:
PR_NUMBER: ${{ env.PR_NUMBER }}
RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
- name: Comment EE deployment details
uses: actions/github-script@v6
env:
PR_NUMBER: ${{ env.PR_NUMBER }}
RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = process.env.PR_NUMBER;
const apiKey = process.env.RENDER_API_KEY;
const eeServiceRes = await fetch(`https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${prNumber}&limit=1`, {
headers: {
'accept': 'application/json',
'authorization': `Bearer ${apiKey}`
}
});
const eeServices = await eeServiceRes.json();
const eeServiceId = eeServices[0]?.service?.id || null;
let eeInfo = 'No active EE review app deployment found.';
if (eeServiceId) {
const deployRes = await fetch(`https://api.render.com/v1/services/${eeServiceId}/deploys?limit=1`, {
headers: {
'accept': 'application/json',
'authorization': `Bearer ${apiKey}`
}
});
const deployData = await deployRes.json();
const deploy = deployData[0]?.deploy || {};
const eeCommit = deploy.commit || {};
const status = deploy.status || 'unknown';
eeInfo = `### Enterprise Edition\n- App: https://tooljet-ee-pr-${prNumber}.onrender.com\n- Dashboard: https://dashboard.render.com/web/${eeServiceId}\n- Commit: ${eeCommit.id || ''}\n- Message: ${eeCommit.message || ''}\n- Status: ${status}`;
}
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: eeInfo
});
- name: Remove label
if: contains(steps.get_labels.outputs.result, 'render-check-deployment')
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'render-check-deployment'
})
} catch (e) {
console.log(e)
}