diff --git a/.github/actions/setup-nodejs/action.yml b/.github/actions/setup-nodejs/action.yml new file mode 100644 index 000000000..452b2b557 --- /dev/null +++ b/.github/actions/setup-nodejs/action.yml @@ -0,0 +1,10 @@ +name: πŸ€– Setup Nodejs + +runs: + using: 'composite' + steps: + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' diff --git a/.github/workflows/fleek-deploy-common.yml b/.github/workflows/fleek-deploy-common.yml new file mode 100644 index 000000000..1fa447d11 --- /dev/null +++ b/.github/workflows/fleek-deploy-common.yml @@ -0,0 +1,115 @@ +name: ⚑️ Deploy site (Common) + +on: + workflow_dispatch: + workflow_call: + inputs: + environment: + required: true + type: string + +jobs: + deploy-to-fleek: + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + env: + DASHBOARD_UNARCHIVED_PATH: "temp/dashboard" + FLEEK_PROJECT_ID: ${{ env.FLEEK_PROJECT_ID }} + FLEEK_SLUG: ${{ env.FLEEK_SLUG }} + FLEEK_TOKEN: ${{ secrets.FLEEK_TOKEN }} + GITHUB_SOURCE_REPO: ${{ github.repository }} + DOPPLER_CONFIG: ${{ env.DOPPLER_CONFIG }} + DOPPLER_PROJECT: ${{ env.DOPPLER_PROJECT }} + DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }} + TARGET_ENVIRONMENT: ${{ inputs.environment }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - uses: ./.github/actions/setup-nodejs + + - name: Install Doppler CLI + uses: dopplerhq/cli-action@v3 + + - name: Setup Doppler + run: | + doppler configure set token "$DOPPLER_TOKEN" + doppler configure set project "$DOPPLER_PROJECT" + doppler configure set config "$DOPPLER_CONFIG" + + - name: Env vars health check + run: | + if ! doppler run -- printenv | grep -q 'NEXT_PUBLIC_SDK__AUTHENTICATION_URL'; then + echo "πŸ‘Ή Oops! Missing required environment variable during health check..." + exit 1 + fi + + echo "πŸš‘ Doppler envVars seem healthy!" + + - name: Setup dotenv + run: | + scripts/setup-ci-dotenv + + - name: Install Fleek CLI + run: npm i -g @fleek-platform/cli + + # TODO: Maybe separate into three steps: + # - Site build + # - Dashboard + # - Deploy + - name: Install Packages + run: npm install + + #Β TODO: It might be wiser to use a regular + # NPM package deployment and copy distribution + # to the local path + - name: Download Dashboard artifact + id: download_dashboard_artifact + run: | + github_token="$GITHUB_TOKEN" + source_repo="$GITHUB_SOURCE_REPO" + dashboard_build_output_filename="build-output-fleek-xyz-$TARGET_ENVIRONMENT" + latest_artifact_file="$dashboard_build_output_filename.zip" + + .scripts/download_artifact \ + "$github_token" \ + "$source_repo" \ + "$dashboard_build_output_filename" \ + "$latest_artifact_file" + + echo "latest_dashboard_artifact=$latest_artifact_file" >> "$GITHUB_OUTPUT" + + - name: Prepare Dashboard files + env: + ARTIFACT: ${{ steps.download_dashboard_artifact.outputs.latest_dashboard_artifact }} + OUTPUT_PATH: ${{ env.DASHBOARD_UNARCHIVED_PATH }} + run: | + if ! scripts/unarchive_dashboard_files "$ARTIFACT" "$OUTPUT_PATH"; then + echo "πŸ‘Ή Oops! Failed to unarchive the dashboard files for some reason..." + exit 1 + fi + + echo "βœ… Unarchived the archive file $ARTIFACT, to $OUTPUT_PATH. It's contents are listed below:" + ls -la "$OUTPUT_PATH" + + - name: Setup fleek.config.json + run: | + DIST="dist" + BUILD="npm run build && cp -r $DASHBOARD_UNARCHIVED_PATH $DIST" + + ./scripts/setup-fleek-config \ + "$FLEEK_SLUG" \ + "$DIST" \ + "$BUILD" + + - name: Build & deploy + run: | + fleek sites deploy + + - name: Clear + run: | + rm .env diff --git a/.github/workflows/fleek-deploy-production.yml b/.github/workflows/fleek-deploy-production.yml new file mode 100644 index 000000000..59ea490f2 --- /dev/null +++ b/.github/workflows/fleek-deploy-production.yml @@ -0,0 +1,19 @@ +# TODO: Once satisfied with staging setup uncomment the following workflow + +# name: ⚑️ Deploy Dashboard (Production) + +# on: +# workflow_dispatch: +# push: +# branches: +# - main +# # The workflow's dispatched on Release by develop hash +# repository_dispatch: +# types: [Release] + +# jobs: +# deploy-to-staging: +# uses: ./.github/workflows/fleek-deploy-common.yml +# with: +# environment: production +# secrets: inherit diff --git a/.github/workflows/fleek-deploy-staging.yml b/.github/workflows/fleek-deploy-staging.yml new file mode 100644 index 000000000..d30fa115a --- /dev/null +++ b/.github/workflows/fleek-deploy-staging.yml @@ -0,0 +1,17 @@ +name: ⚑️ Deploy Dashboard (Staging) + +on: + workflow_dispatch: + push: + branches: + - develop + # The workflow's dispatched on Release by develop hash + repository_dispatch: + types: [Release] + +jobs: + deploy-to-staging: + uses: ./.github/workflows/fleek-deploy-common.yml + with: + environment: staging + secrets: inherit diff --git a/.github/workflows/release-by-develop-hash.yml b/.github/workflows/release-by-develop-hash.yml index 9697b5d88..e2cb46b27 100644 --- a/.github/workflows/release-by-develop-hash.yml +++ b/.github/workflows/release-by-develop-hash.yml @@ -118,7 +118,7 @@ jobs: - name: Dispatch Event env: PAT: ${{ secrets.GITHUB_TOKEN }} - ENDPOINT: 'https://api.github.com/repos/fleek-platform/website/dispatches' + ENDPOINT: 'https://api.github.com/repos/${{ github.repository }}/dispatches' EVENT_NAME: 'Release' run: | if ! curl -H "Accept: application/vnd.github+json" \ diff --git a/.gitignore b/.gitignore index 233ce0747..3f60893c5 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ fleek.*.config.json #lock files pnpm-lock.yaml + +# dev +dev_* diff --git a/README.md b/README.md index 5f30e043b..7761853c0 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,12 @@ npm run build Tweak environment settings (src/settings.json), such as the site URL. Declare the `NODE_ENV` with value `prod` or `production` to switch environment target settings. +Alternatively, you can skip build checkups and build assets only: + +``` +npm run build:static_assets +``` + ## πŸ™ˆ Preview locally You can preview the distribution build locally by starting the preview HTTP server: diff --git a/package.json b/package.json index 036068a71..f608df751 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "scripts": { "dev": "astro dev", "start": "astro dev", - "build": "rm -rf dist && npm run check:strict && npm run check:json && astro build && ./scripts/build/copy-video-content-src-to-dist", + "build": "rm -rf dist && npm run check:strict && npm run check:json && npm run build:static_assets", + "build:static_assets": "astro build && ./scripts/build/copy-video-content-src-to-dist && cp ./public/_redirects ./dist", "preview": "astro preview", "astro": "astro", "clean": "rm -rf .astro node_modules/.vite", diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 000000000..277117e72 --- /dev/null +++ b/public/_redirects @@ -0,0 +1 @@ +/dashboard/* /dashboard/index.html 200 diff --git a/scripts/download_artifact b/scripts/download_artifact new file mode 100755 index 000000000..6f6ba786f --- /dev/null +++ b/scripts/download_artifact @@ -0,0 +1,67 @@ +#!/bin/bash + +ghToken="$1" +orgRepo="$2" +targetArtifactFilename="$3" +outputFilename="$4" + +if [[ -z "$1" || -z "$2" || -z "$3" || -z "$4" ]]; then + echo "πŸ‘Ή Oops! Missing arguments, e.g. github token, organisation repository, artifact name, etc" + exit 1 +fi + +result=$(curl -sL \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $ghToken" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/$orgRepo/actions/artifacts") + +if [[ -z "$result" ]]; then + echo "πŸ‘Ή Oops! The request for artifacts API has an unexpected response $result" + exit 1 +fi + +countMatchingFilename=$(echo "$result" | jq "[.artifacts[] | select(.name == \"$targetArtifactFilename\")] | length") + +if [[ "$countMatchingFilename" -eq 0 ]]; then + echo "πŸ‘Ή Oops! Didn't find any artifacts of name $targetArtifactFilename" + exit 1 +fi + +echo "βœ… Found $countMatchingFilename artifact matches for name $targetArtifactFilename" + +filteredByFilename=$(echo "$result" | jq "[.artifacts[] | select(.name == \"$targetArtifactFilename\")]") + +if [[ -z "$filteredByFilename" ]]; then + echo "πŸ‘Ή Oops! Failed to get the latest artifact from response $result" + exit 1 +fi + +latestArtifact=$(echo "$filteredByFilename" | jq 'sort_by(.created_at) | reverse | .[0]') + +if [[ -z "$latestArtifact" ]]; then + echo "πŸ‘Ή Oops! Failed to get the latest artifact from response $result" + exit 1 +fi + +latestArtifactId=$(echo "$latestArtifact" | jq '.id') +latestArtifactName=$(echo "$latestArtifact" | jq '.name') + +if [[ -z "$latestArtifactId" ]]; then + echo "πŸ‘Ή Oops! Failed to get the latest artifact id from response $latestArtifact" + exit 1 +fi + +echo "βœ… Got artifact id $latestArtifactId of name $latestArtifactName" + +if ! curl -sL \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $ghToken" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/$orgRepo/actions/artifacts/$latestArtifactId/zip" \ + --output "$outputFilename"; then + echo "πŸ‘Ή Oops! Failed download the artifact id $latestArtifactId" + exit 1 +fi + +echo "βœ… Downloaded artifact $outputFilename" diff --git a/scripts/setup-ci-dotenv b/scripts/setup-ci-dotenv new file mode 100755 index 000000000..086609c47 --- /dev/null +++ b/scripts/setup-ci-dotenv @@ -0,0 +1,31 @@ +#!/bin/bash + +targetEnvPath=".env" +# Using dotenv due to `fleek sites deploy` +# failing to authenticate via the host or declared +# fleek env vars for some reason +doppler secrets download \ + --no-file \ + --format env > "$targetEnvPath" + +# The Fleek CLI supports envVars overrides +# for this reason, we should exclude some vars +# originated from doppler +EXCLUDE_CSV=( "UI__APP_URL" "SDK__GRAPHQL_API_URL" "SDK__AUTH_APPS_URL" "SDK__IPFS__STORAGE_API_URL" "SDK__UPLOAD_PROXY_API_URL" "SITE_SLUG_DOMAIN" ) + +for item in "${EXCLUDE_CSV[@]}"; do + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "/^${item}=/d" "$targetEnvPath" + else + sed -i "/^${item}=/d" "$targetEnvPath" + fi +done + +for item in "${EXCLUDE_CSV[@]}"; do + if grep -q "^${item}=" "$targetEnvPath"; then + echo "πŸ‘Ή Oops! Failed to exclude $item from $targetEnvPath" + exit 1 + fi +done + +echo "βœ… Completed dot env setup!" diff --git a/scripts/setup-fleek-config b/scripts/setup-fleek-config new file mode 100755 index 000000000..36be70925 --- /dev/null +++ b/scripts/setup-fleek-config @@ -0,0 +1,33 @@ +#!/bin/bash + +if [[ -z "$1" || -z "$2" || -z "$3" ]]; then + echo "πŸ‘Ή Oops! Missing arguments required for slug, distDir and buildCommand." + exit 1 +fi + +fleekConfigPath="./fleek.config.json" +temp="$fleekConfigPath.tmp" + +if ! jq --arg slug "$1" --arg distDir "$2" --arg buildCommand "$3" ' + .sites[0].slug = $slug | + .sites[0].distDir = $distDir | + .sites[0].buildCommand = $buildCommand +' "$fleekConfigPath" > "$temp"; then + echo "πŸ‘Ή Oops! Failed to set $fleekConfigPath for some reason..." + exit 1 +fi + +if ! mv "$temp" "$fleekConfigPath"; then + echo "πŸ‘Ή Oops! Failed to override the $fleekConfigPath" + exit 1 +fi + +if ! rm "$temp"; then + echo "⚠️ WARNING: Failed to remove $temp file" +fi + +echo "πŸ” The $fleekConfigPath content is:" +cat "$fleekConfigPath" +echo + +echo "βœ… Completed fleek config setup!" diff --git a/scripts/unarchive_dashboard_files b/scripts/unarchive_dashboard_files new file mode 100755 index 000000000..4226053a5 --- /dev/null +++ b/scripts/unarchive_dashboard_files @@ -0,0 +1,31 @@ +#!/bin/bash + +if [[ -z "$1" || -z "$2" ]]; then + echo "πŸ‘Ή Oops! Missing arguments. Have you provided a filename and output path?" + exit 1 +fi + +artifact_filename="$1" +output_path="$2" + +if ! unzip -q -o "$artifact_filename" -d "$output_path"; then + echo "πŸ‘Ή Oops! Failed to unzip $artifact_filename" + exit 1 +fi + +echo "βœ… Unziped $artifact_filename" + +if ! rm "$artifact_filename"; then + echo "πŸ‘Ή Oops! Failed to delete $artifact_filename" + exit 1 +fi + +echo "βœ… Deleted $artifact_filename" + +if ! mkdir -p "$output_path"; then + echo "πŸ‘Ή Oops! Failed to create the output path $output_path" + exit 1 +fi + +echo "πŸ€– The file content generated the following file tree..." +tree -L 2 "$output_path"