name: Deploy to cloud frontend stage on: workflow_dispatch: inputs: branch: description: 'Git branch to deploy (must start with "lts-", e.g., lts-3.6)' required: true jobs: deploy: runs-on: ubuntu-latest steps: - name: โœ… Check user authorization run: | allowed_user1=${{ secrets.ALLOWED_USER1_USERNAME }} allowed_user2=${{ secrets.ALLOWED_USER2_USERNAME }} allowed_user3=${{ secrets.ALLOWED_USER3_USERNAME }} if [[ "${{ github.actor }}" != "$allowed_user1" && \ "${{ github.actor }}" != "$allowed_user2" && \ "${{ github.actor }}" != "$allowed_user3" ]]; then echo "โŒ User '${{ github.actor }}' is not authorized to trigger this workflow." exit 1 else echo "โœ… User '${{ github.actor }}' is authorized." fi - name: ๐Ÿ“ฅ Manual Git checkout with submodules run: | set -e BRANCH="${{ github.event.inputs.branch }}" REPO="https://x-access-token:${{ secrets.CUSTOM_GITHUB_TOKEN }}@github.com/${{ github.repository }}" git config --global url."https://x-access-token:${{ secrets.CUSTOM_GITHUB_TOKEN }}@github.com/".insteadOf "https://github.com/" git config --global http.version HTTP/1.1 git config --global http.postBuffer 524288000 echo "๐Ÿ‘‰ Cloning $REPO (branch: $BRANCH)" git clone --recurse-submodules --depth=1 --branch "$BRANCH" "$REPO" repo cd repo echo "๐Ÿ”Ž Main repo: verifying checkout" MAIN_CURRENT=$(git rev-parse --abbrev-ref HEAD) echo "โœ… Main repo: successfully checked out branch $MAIN_CURRENT" echo "๐Ÿ“ Main repo: current commit $(git rev-parse --short HEAD): $(git log -1 --pretty=%s)" echo "๐Ÿ” Updating submodules" git submodule update --init --recursive echo "๐Ÿ”€ Attempting to checkout '$BRANCH' in each submodule and validating" BRANCH="$BRANCH" git submodule foreach --recursive bash -c ' name="$sm_path" echo "" echo "Entering '\''$name'\''" echo "โ†ช $name: trying to checkout branch '\''$BRANCH'\''" if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null; then git fetch origin "$BRANCH:$BRANCH" || { echo "โŒ $name: fetch failed for $BRANCH" exit 1 } PREV=$(git rev-parse --short HEAD || echo "unknown") git checkout "$BRANCH" || { echo "โŒ $name: checkout failed for $BRANCH" exit 1 } echo "Previous HEAD position was $PREV: $(git log -1 --pretty=%s || echo 'unknown')" echo "โœ… $name: checked out branch $BRANCH" else echo "โš ๏ธ $name: branch '$BRANCH' not found on origin. Falling back to 'lts-3.16'" PREV=$(git rev-parse --short HEAD || echo "unknown") git fetch origin lts-3.16:lts-3.16 || { echo "โŒ $name: fetch failed for lts-3.16" exit 1 } git checkout lts-3.16 || { echo "โŒ $name: fallback to lts-3.16 failed" exit 1 } echo "Previous HEAD position was $PREV: $(git log -1 --pretty=%s || echo 'unknown')" echo "โœ… $name: now on branch lts-3.16" fi CURRENT=$(git rev-parse --abbrev-ref HEAD) echo "๐Ÿ”Ž $name: current branch = $CURRENT" if [ "$CURRENT" != "$BRANCH" ] && [ "$CURRENT" != "lts-3.16" ]; then echo "โŒ $name: unexpected branch state โ€” wanted '$BRANCH' or fallback 'lts-3.16', got '$CURRENT'" exit 1 fi ' - name: ๐Ÿงฐ Setup Node.js uses: actions/setup-node@v2 with: node-version: 22.15.1 - name: ๐Ÿ“ฆ Install dependencies run: npm install working-directory: repo - name: ๐Ÿ› ๏ธ Build the project run: npm run build:plugins:prod && npm run build:frontend working-directory: repo env: GOOGLE_MAPS_API_KEY: ${{ secrets.CLOUD_GOOGLE_MAPS_API_KEY }} NODE_ENV: ${{ secrets.CLOUD_NODE_ENV }} NODE_OPTIONS: ${{ secrets.CLOUD_NODE_OPTIONS }} SENTRY_AUTH_TOKEN: ${{ secrets.CLOUD_SENTRY_AUTH_TOKEN }} SENTRY_ORG: ${{ secrets.CLOUD_SENTRY_ORG }} SENTRY_PROJECT: ${{ secrets.CLOUD_SENTRY_PROJECT }} SERVE_CLIENT: ${{ secrets.CLOUD_SERVE_CLIENT }} SERVER_IP: ${{ secrets.CLOUD_SERVER_IP }} TJDB_SQL_MODE_DISABLE: ${{ secrets.CLOUD_TJDB_SQL_MODE_DISABLE }} TOOLJET_SERVER_URL: ${{ secrets.CLOUD_TOOLJET_SERVER_URL }} TOOLJET_EDITION: cloud WEBSITE_SIGNUP_URL: https://website-stage.tooljet.ai/signup - name: ๐Ÿš€ Deploy to Netlify run: | npm install -g netlify-cli netlify deploy --prod --dir=frontend/build --auth=$NETLIFY_AUTH_TOKEN --site=${{ secrets.CLOUD_NETLIFY_SITE_ID }} working-directory: repo env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} GOOGLE_MAPS_API_KEY: ${{ secrets.CLOUD_GOOGLE_MAPS_API_KEY }} NODE_ENV: ${{ secrets.CLOUD_NODE_ENV }} NODE_OPTIONS: ${{ secrets.CLOUD_NODE_OPTIONS }} SENTRY_AUTH_TOKEN: ${{ secrets.CLOUD_SENTRY_AUTH_TOKEN }} SENTRY_ORG: ${{ secrets.CLOUD_SENTRY_ORG }} SENTRY_PROJECT: ${{ secrets.CLOUD_SENTRY_PROJECT }} SERVE_CLIENT: ${{ secrets.CLOUD_SERVE_CLIENT }} SERVER_IP: ${{ secrets.CLOUD_SERVER_IP }} TJDB_SQL_MODE_DISABLE: ${{ secrets.CLOUD_TJDB_SQL_MODE_DISABLE }} TOOLJET_SERVER_URL: ${{ secrets.CLOUD_TOOLJET_SERVER_URL }} WEBSITE_SIGNUP_URL: https://website-stage.tooljet.ai/signup TOOLJET_EDITION: cloud Purge_Cloudflare_Cache: needs: deploy runs-on: ubuntu-latest steps: - name: โœ… Check user authorization run: | allowed_user1=${{ secrets.ALLOWED_USER1_USERNAME }} allowed_user2=${{ secrets.ALLOWED_USER2_USERNAME }} allowed_user3=${{ secrets.ALLOWED_USER3_USERNAME }} if [[ "${{ github.actor }}" != "$allowed_user1" && \ "${{ github.actor }}" != "$allowed_user2" && \ "${{ github.actor }}" != "$allowed_user3" ]]; then echo "โŒ User '${{ github.actor }}' is not authorized to trigger this workflow." exit 1 else echo "โœ… User '${{ github.actor }}' is authorized." fi - name: ๐Ÿงน Purge Cloudflare Cache continue-on-error: true run: | echo "๐Ÿ”„ Purging Cloudflare cache for specific URLs..." response=$(curl -s -w "\n%{http_code}" -X POST \ "https://api.cloudflare.com/client/v4/zones/${{ secrets.CLOUDFLARE_ZONE_ID_PROD }}/purge_cache" \ -H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN_PROD }}" \ -H "Content-Type: application/json" \ --data '{ "files": [ "${{ secrets.CLOUDFLARE_CONFIG_URL_STAGE }}", "${{ secrets.CLOUDFLARE_METADATA_URL_STAGE }}" ] }') http_code=$(echo "$response" | tail -n1) body=$(echo "$response" | sed '$d') if [ "$http_code" = "200" ]; then echo "โœ… Cloudflare cache purged successfully for specified URLs" echo "$body" else echo "โš ๏ธ Cloudflare cache purge failed with status code: $http_code" echo "$body" exit 1 fi