From ac0ec2613f8aac4c06c386e3cc0ccf688731a68b Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Fri, 15 Mar 2024 16:32:28 +0100 Subject: [PATCH 01/14] ci: add nightly codespace CI --- .devcontainer/devcontainer.json | 15 +++++++++++---- .github/workflows/codespaces-ci.sh | 19 +++++++++++++++++++ .github/workflows/codespaces-ci.yml | 21 +++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100755 .github/workflows/codespaces-ci.sh create mode 100644 .github/workflows/codespaces-ci.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9fa6c2a33..c8a7f21c6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -24,10 +24,15 @@ }, "ghcr.io/devcontainers/features/github-cli:1": { "version": "latest" + }, + "ghcr.io/devcontainers/features/sshd:1": { + "version": "latest" } }, - // add labels to ports + // add labels to ports that are being used + // this will make it easier to identify what is running on each port + // it's also used by nightly builds to check all services are running as expected "portsAttributes": { "4280": { "label": "Portal App", @@ -48,10 +53,15 @@ "4300": { "label": "Web PubSub API", "onAutoForward": "notify" + }, + "4200": { + "label": "Angular", + "onAutoForward": "notify" } }, // Use 'forwardPorts' to make a list of ports inside the container available locally. + // Note: do not forward 4200 as it's being proxied by 4280 "forwardPorts": [4280, 4242, 3000, 1337], // Use 'postCreateCommand' to run commands after the container is created. @@ -90,7 +100,4 @@ "memory": "8gb", "storage": "32gb" } - - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" } diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh new file mode 100755 index 000000000..8484e7a3c --- /dev/null +++ b/.github/workflows/codespaces-ci.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +GITHUB_REPOSITORY="Azure-Samples/contoso-real-estate" +BRANCH="codespaces-ci" +APP_PORT="4280" + +# gh auth login --with-token $GITHUB_TOKEN +gh codespace create \ + --repo $GITHUB_REPOSITORY \ + --branch $BRANCH \ + --retention-period "1h" \ + --display-name "Contoso Real Estate Nightly" \ + --idle-timeout "30m" \ + --machine "largePremiumLinux" \ + --status \ + --default-permissions + +# gh codespace stop -R $GITHUB_REPOSITORY +# gh codespace delete -R $GITHUB_REPOSITORY diff --git a/.github/workflows/codespaces-ci.yml b/.github/workflows/codespaces-ci.yml new file mode 100644 index 000000000..e7450fb63 --- /dev/null +++ b/.github/workflows/codespaces-ci.yml @@ -0,0 +1,21 @@ +name: Nightly Codespace CI + +on: + push: + branches: + - main + schedule: + # Runs every day at 4:00 AM pacific (UTC-7) + - cron: '0 12 * * *' + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Deploy to Codespace + env: + GITHUB_TOKEN: ${{ secrets.CODESPACES_TOKEN }} + run: ./.github/workflows/codespaces-ci.sh \ No newline at end of file From bfee5b47dd86da9ab5177cca31a57ae948523009 Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Fri, 15 Mar 2024 17:00:39 +0100 Subject: [PATCH 02/14] ci: add root route to portal API --- packages/api/src/index.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 733786ea6..897ee55c1 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -7,6 +7,18 @@ import { getListingById, getListings } from "./functions/listings"; import { openApi } from "./functions/openapi"; import { postCheckout } from "./functions/checkout"; +// This route is used by nightly builds as a health check +app.get("get-root", { + route: "/", + authLevel: "anonymous", + handler: async () => { + return { + status: 200, + body: "Welcome to Contoso Real Estate API", + }; + } +}); + //#region User Function app.get("get-users", { route: "users", From 66746f06aefc2f6214bba281e17f3fe53d3961fa Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Fri, 15 Mar 2024 17:51:31 +0100 Subject: [PATCH 03/14] ci: add missing deps for stripe --- packages/stripe/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/stripe/package.json b/packages/stripe/package.json index b019a02af..039c198c9 100644 --- a/packages/stripe/package.json +++ b/packages/stripe/package.json @@ -35,6 +35,7 @@ "concurrently": "^7.0.0", "tap": "^16.1.0", "ts-node": "^10.4.0", - "typescript": "^5.3.2" + "typescript": "^5.3.2", + "data-uri-to-buffer": "^4.0.1" } } From e7009afb16132a806b069194530084c07a7cdc58 Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Sat, 16 Mar 2024 01:31:46 +0100 Subject: [PATCH 04/14] ci: fix root API route --- packages/api/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 897ee55c1..b2e54e98b 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -9,7 +9,7 @@ import { postCheckout } from "./functions/checkout"; // This route is used by nightly builds as a health check app.get("get-root", { - route: "/", + route: "", authLevel: "anonymous", handler: async () => { return { From b12be9730e1bb0de42b79ab4b7f44a6b1e715bef Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Sat, 16 Mar 2024 01:37:54 +0100 Subject: [PATCH 05/14] ci: add package-lock --- package-lock.json | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/package-lock.json b/package-lock.json index 8d16879f8..dc099b8db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19583,6 +19583,28 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -20090,6 +20112,17 @@ "node": ">= 6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/formidable": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", @@ -27504,6 +27537,24 @@ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -39238,6 +39289,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -40645,6 +40704,7 @@ "dependencies": { "@fastify/autoload": "^5.8.0", "@fastify/sensible": "^5.5.0", + "data-uri-to-buffer": "^4.0.1", "fastify": "^4.24.3", "fastify-cli": "^5.9.0", "fastify-plugin": "^4.5.1", @@ -40662,6 +40722,14 @@ "typescript": "^5.3.2" } }, + "packages/stripe/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, "packages/stripe/node_modules/node-fetch": { "version": "3.3.2", "license": "MIT", From 25616eb1230883be79a2b23811d6564895b6cce0 Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Sat, 16 Mar 2024 01:57:37 +0100 Subject: [PATCH 06/14] ci: improve ci script --- .github/workflows/codespaces-ci.sh | 92 ++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh index 8484e7a3c..9d053c77b 100755 --- a/.github/workflows/codespaces-ci.sh +++ b/.github/workflows/codespaces-ci.sh @@ -1,19 +1,99 @@ #!/bin/bash +set -e GITHUB_REPOSITORY="Azure-Samples/contoso-real-estate" BRANCH="codespaces-ci" -APP_PORT="4280" +CODESPACE_NAME="nightly-build-$(date +%s)" +CODESPACE_ID="" +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color -# gh auth login --with-token $GITHUB_TOKEN +# login to GitHub CLI +echo "Login to GitHub CLI..." +echo ${{ $GITHUB_TOKEN }} | gh auth login --with-token + +echo "Check auth status..." +gh auth status + +# create a codespace +echo "Create a codespace "$CODESPACE_NAME" for $GITHUB_REPOSITORY on branch $BRANCH..." gh codespace create \ --repo $GITHUB_REPOSITORY \ --branch $BRANCH \ + --display-name $CODESPACE_NAME \ --retention-period "1h" \ - --display-name "Contoso Real Estate Nightly" \ - --idle-timeout "30m" \ + --idle-timeout "1h" \ --machine "largePremiumLinux" \ --status \ --default-permissions -# gh codespace stop -R $GITHUB_REPOSITORY -# gh codespace delete -R $GITHUB_REPOSITORY +CODESPACE_ID=$(gh codespace list -R $GITHUB_REPOSITORY --jq ".[] | select(.displayName == \"$CODESPACE_NAME\")" --json displayName,name) | jq -r '.name' +echo "Codespace created and started: $CODESPACE_ID" + +# connect to the codespace and start the app +echo "Running all services..." +gh codespace ssh -c $CODESPACE_ID "npm start --prefix /workspaces/contoso-real-estate" & + +# Wait for the app to start +echo "Waiting 30s for all ports to be fowarded..." +sleep 30 + +# check all services are running +nb_services_down=0 +max_retries=5 +while [ $nb_services_down > 0 ]; do + + echo -ne "Fetching registered services..." + services=$(gh cs ports -c $CODESPACE_ID --json label,browseUrl | jq -r '.[] | select(.label != "") | .browseUrl') + nb_services=$(echo "$services" | awk 'END { print NR }') + echo " Found $nb_services" + + nb_services_down=0 + echo "---------------------------------------------------------------------------------------------------------" + for service in $services; do + echo -ne "Inspecting: $service ... " + status=$(curl -H "X-Github-Token: $GITHUB_TOKEN" -s -o /dev/null -w "%{http_code}" $service) + + if [ $status == 200 ] || [ $status == 404 ]; then + echo -e "${GREEN}$status OK${NC}" + else + echo -e "${RED}$status ERROR${NC}" + ((nb_services_down++)) + fi + done + + if [ $nb_services_down == 0 ]; then + echo "All services are running!" + break + fi + + if [ $max_retries == 0 ]; then + echo "Max retries reached, exiting..." + break + fi + + echo "---------------------------------------------------------------------------------------------------------" + echo "Found $nb_services_down services down..." + echo "Wait 10s before retrying... (retries left: $max_retries)" + sleep 10 + ((max_retries--)) +done + + +# print all codespaces logs +echo "Fetching codespace logs before exiting..." +gh codespace logs -c $CODESPACE_ID + +# stop and delete the codespace +echo "Stopping and deleting codespace $CODESPACE_ID..." +gh codespace stop -R $GITHUB_REPOSITORY +gh codespace delete -R $GITHUB_REPOSITORY + +if [ $nb_services_down > 0 ]; then + echo -e "${RED}ERROR: Some services are still down, exiting with error.${NC}" + exit 1 +else + echo -e "${GREEN}OK: All services are running, exiting with success.${NC}" + exit 0 +fi \ No newline at end of file From b12e3d75b2c9bf16ab77522fa4aab60131aef334 Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Mon, 18 Mar 2024 18:00:00 +0100 Subject: [PATCH 07/14] ci: improve ci script --- .github/workflows/codespaces-ci.sh | 182 +++++++++++++++++------------ 1 file changed, 108 insertions(+), 74 deletions(-) diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh index 9d053c77b..de6c083ba 100755 --- a/.github/workflows/codespaces-ci.sh +++ b/.github/workflows/codespaces-ci.sh @@ -10,90 +10,124 @@ GREEN='\033[0;32m' NC='\033[0m' # No Color # login to GitHub CLI -echo "Login to GitHub CLI..." -echo ${{ $GITHUB_TOKEN }} | gh auth login --with-token +function gh_login() { + echo "Loging in with GitHub CLI as admin..." + echo $X_GITHUB_TOKEN | gh auth login --with-token -echo "Check auth status..." -gh auth status + echo "Checking auth status..." + gh auth status +} # create a codespace -echo "Create a codespace "$CODESPACE_NAME" for $GITHUB_REPOSITORY on branch $BRANCH..." -gh codespace create \ - --repo $GITHUB_REPOSITORY \ - --branch $BRANCH \ - --display-name $CODESPACE_NAME \ - --retention-period "1h" \ - --idle-timeout "1h" \ - --machine "largePremiumLinux" \ - --status \ - --default-permissions - -CODESPACE_ID=$(gh codespace list -R $GITHUB_REPOSITORY --jq ".[] | select(.displayName == \"$CODESPACE_NAME\")" --json displayName,name) | jq -r '.name' -echo "Codespace created and started: $CODESPACE_ID" - -# connect to the codespace and start the app -echo "Running all services..." -gh codespace ssh -c $CODESPACE_ID "npm start --prefix /workspaces/contoso-real-estate" & - -# Wait for the app to start -echo "Waiting 30s for all ports to be fowarded..." -sleep 30 +function gh_create_codespace() { + echo "Creating a codespace $CODESPACE_NAME for $GITHUB_REPOSITORY on branch $BRANCH..." + gh codespace create \ + --repo $GITHUB_REPOSITORY \ + --branch $BRANCH \ + --display-name $CODESPACE_NAME \ + --retention-period "1h" \ + --idle-timeout "1h" \ + --machine "largePremiumLinux" \ + --status \ + --default-permissions +} + +# fetch the codespace ID +function gh_fetch_codespace_id() { + CODESPACE_ID=$(gh codespace list -R $GITHUB_REPOSITORY --jq ".[] | select(.displayName == \"$CODESPACE_NAME\")" --json displayName,name | jq -r '.name') + echo "Codespace created and started: $CODESPACE_ID" +} + +# connect to the codespace and start the services +function gh_codespace_start_services() { + echo "Running all services (over SSH)..." + (gh codespace ssh -c $CODESPACE_ID "npm start --prefix /workspaces/contoso-real-estate") & +} # check all services are running -nb_services_down=0 -max_retries=5 -while [ $nb_services_down > 0 ]; do - - echo -ne "Fetching registered services..." - services=$(gh cs ports -c $CODESPACE_ID --json label,browseUrl | jq -r '.[] | select(.label != "") | .browseUrl') - nb_services=$(echo "$services" | awk 'END { print NR }') - echo " Found $nb_services" - +function gh_codespace_check_services_status() { nb_services_down=0 - echo "---------------------------------------------------------------------------------------------------------" - for service in $services; do - echo -ne "Inspecting: $service ... " - status=$(curl -H "X-Github-Token: $GITHUB_TOKEN" -s -o /dev/null -w "%{http_code}" $service) - - if [ $status == 200 ] || [ $status == 404 ]; then - echo -e "${GREEN}$status OK${NC}" - else - echo -e "${RED}$status ERROR${NC}" - ((nb_services_down++)) - fi - done + max_retries=5 + while [ $nb_services_down > 0 ]; do - if [ $nb_services_down == 0 ]; then - echo "All services are running!" - break - fi + echo -ne "Fetching registered services..." + services=$(gh codespace ports -c $CODESPACE_ID --json label,browseUrl | jq -r '.[] | select(.label != "") | .browseUrl') + nb_services=$(echo "$services" | awk 'END { print NR }') + echo " Found $nb_services" - if [ $max_retries == 0 ]; then - echo "Max retries reached, exiting..." - break - fi + if [ -z "$services" ]; then + echo "No services found, exiting..." + break + fi - echo "---------------------------------------------------------------------------------------------------------" - echo "Found $nb_services_down services down..." - echo "Wait 10s before retrying... (retries left: $max_retries)" - sleep 10 - ((max_retries--)) -done + nb_services_down=0 + echo "---------------------------------------------------------------------------------------------------------" + for service in $services; do + echo -ne "Inspecting: $service ... " + status=$(curl -H "X-Github-Token: $GITHUB_TOKEN" -s -o /dev/null -w "%{http_code}" $service) + + if [ $status == 200 ] || [ $status == 404 ]; then + echo -e "${GREEN}$status OK${NC}" + else + echo -e "${RED}$status ERROR${NC}" + ((nb_services_down++)) + fi + done + + if [ $nb_services_down == 0 ]; then + echo "All services are running!" + break + fi + if [ $max_retries == 0 ]; then + echo "Max retries reached, exiting..." + break + fi -# print all codespaces logs -echo "Fetching codespace logs before exiting..." -gh codespace logs -c $CODESPACE_ID + echo "---------------------------------------------------------------------------------------------------------" + echo "Found $nb_services_down services down..." + echo "Wait 10s before retrying... (retries left: $max_retries)" + sleep 10 + ((max_retries--)) + done +} + +# Wait for the services to start +function wait_for_services() { + echo -ne "Waiting 30s for all services to start" + for i in {1..30}; do + echo -ne "." + sleep 1 + done + echo "" +} # stop and delete the codespace -echo "Stopping and deleting codespace $CODESPACE_ID..." -gh codespace stop -R $GITHUB_REPOSITORY -gh codespace delete -R $GITHUB_REPOSITORY - -if [ $nb_services_down > 0 ]; then - echo -e "${RED}ERROR: Some services are still down, exiting with error.${NC}" - exit 1 -else - echo -e "${GREEN}OK: All services are running, exiting with success.${NC}" - exit 0 -fi \ No newline at end of file +function gh_codespace_stop_and_delete() { + echo "Stopping and deleting codespace $CODESPACE_ID..." + gh codespace stop -c $CODESPACE_ID + gh codespace delete -c $CODESPACE_ID -f +} + +function print_report_and_exit() { + if [ $nb_services == 0 ]; then + echo -e "${RED}ERROR: No services found. Inspect the logs above for more details.${NC}" + exit 1 + elif [ $nb_services_down > 0 ]; then + echo -e "${RED}ERROR: $nb_services_down services are still down. Inspect the logs above for more details.${NC}" + exit 1 + else + echo -e "${GREEN}OK: All services are running, exiting with success.${NC}" + exit 0 + fi +} + +############################################ +gh_login; +gh_create_codespace; +gh_fetch_codespace_id; +gh_codespace_start_services; +wait_for_services; +gh_codespace_check_services_status; +gh_codespace_stop_and_delete; +print_report_and_exit; \ No newline at end of file From 30d3632a5aef2b661a02a20d9ef9ecc4081e47c8 Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Mon, 18 Mar 2024 18:04:44 +0100 Subject: [PATCH 08/14] ci: trigger workflow on codespaces-ci --- .github/workflows/codespaces-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codespaces-ci.yml b/.github/workflows/codespaces-ci.yml index e7450fb63..4bcb7e4f4 100644 --- a/.github/workflows/codespaces-ci.yml +++ b/.github/workflows/codespaces-ci.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - codespaces-ci schedule: # Runs every day at 4:00 AM pacific (UTC-7) - cron: '0 12 * * *' @@ -17,5 +18,5 @@ jobs: - name: Deploy to Codespace env: - GITHUB_TOKEN: ${{ secrets.CODESPACES_TOKEN }} + X_GITHUB_TOKEN: ${{ secrets.CODESPACES_TOKEN }} run: ./.github/workflows/codespaces-ci.sh \ No newline at end of file From 6cefcc85e8b234f3910fabc5ca2eb3197befbecc Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Tue, 19 Mar 2024 15:43:08 +0100 Subject: [PATCH 09/14] ci: create cs via api --- .github/workflows/codespaces-ci.sh | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh index de6c083ba..d31cf0c44 100755 --- a/.github/workflows/codespaces-ci.sh +++ b/.github/workflows/codespaces-ci.sh @@ -20,7 +20,7 @@ function gh_login() { # create a codespace function gh_create_codespace() { - echo "Creating a codespace $CODESPACE_NAME for $GITHUB_REPOSITORY on branch $BRANCH..." + echo "Creating a codespace $CODESPACE_NAME for $GITHUB_REPOSITORY on branch $BRANCH (w/ ssh)..." gh codespace create \ --repo $GITHUB_REPOSITORY \ --branch $BRANCH \ @@ -31,6 +31,25 @@ function gh_create_codespace() { --status \ --default-permissions } +function api_create_codespace() { + echo "Creating a codespace $CODESPACE_NAME for $GITHUB_REPOSITORY on branch $BRANCH (w/ api)..." + CODESPACE_ID=$(gh api \ + /repos/$GITHUB_REPOSITORY/codespaces \ + -X POST \ + -H 'Accept: application/vnd.github+json' \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -f owner="$GITHUB_REPOSITORY" \ + -f repo="$GITHUB_REPOSITORY" \ + -f ref="$BRANCH" \ + -f display_name="$CODESPACE_NAME" \ + -f retentionPeriod='1h' \ + -f idleTimeout='1h' \ + -f machineType=l'argePremiumLinux' \ + -f status='true' \ + -f defaultPermissions='true' \ + -q '.name') + echo "Codespace created and started: $CODESPACE_ID" +} # fetch the codespace ID function gh_fetch_codespace_id() { @@ -124,8 +143,9 @@ function print_report_and_exit() { ############################################ gh_login; -gh_create_codespace; -gh_fetch_codespace_id; +# gh_create_codespace; +api_create_codespace; +# gh_fetch_codespace_id; gh_codespace_start_services; wait_for_services; gh_codespace_check_services_status; From 97b8ba840d50aafbd7456da123f24d0cd3db888f Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Tue, 19 Mar 2024 21:28:40 +0100 Subject: [PATCH 10/14] ci: try npm start on post create --- .devcontainer/post-create-command.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/post-create-command.sh b/.devcontainer/post-create-command.sh index c1163967c..33a536f37 100755 --- a/.devcontainer/post-create-command.sh +++ b/.devcontainer/post-create-command.sh @@ -11,3 +11,4 @@ npm i -g azure-functions-core-tools@4 --unsafe-perm true # Install monorepo dependencies npm install +npm start \ No newline at end of file From adbb0fe8a53ea31958687bd5e5cd6ced91982fe7 Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Tue, 19 Mar 2024 22:13:39 +0100 Subject: [PATCH 11/14] ci: use ci-nightly-build-* as naming convention --- .devcontainer/post-create-command.sh | 6 +++++- .github/workflows/codespaces-ci.sh | 16 +++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.devcontainer/post-create-command.sh b/.devcontainer/post-create-command.sh index 33a536f37..1af2605d6 100755 --- a/.devcontainer/post-create-command.sh +++ b/.devcontainer/post-create-command.sh @@ -11,4 +11,8 @@ npm i -g azure-functions-core-tools@4 --unsafe-perm true # Install monorepo dependencies npm install -npm start \ No newline at end of file + +# run npm start if CODESPACE_NAME starts with "CODESPACE_NAME=nightly-build" +if [[ $CODESPACE_NAME == "ci-nightly-build"* ]]; then + npm start +fi \ No newline at end of file diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh index d31cf0c44..88d779d48 100755 --- a/.github/workflows/codespaces-ci.sh +++ b/.github/workflows/codespaces-ci.sh @@ -3,7 +3,7 @@ set -e GITHUB_REPOSITORY="Azure-Samples/contoso-real-estate" BRANCH="codespaces-ci" -CODESPACE_NAME="nightly-build-$(date +%s)" +CODESPACE_NAME="ci-nightly-build-$(date +%s)" CODESPACE_ID="" RED='\033[0;31m' GREEN='\033[0;32m' @@ -25,8 +25,8 @@ function gh_create_codespace() { --repo $GITHUB_REPOSITORY \ --branch $BRANCH \ --display-name $CODESPACE_NAME \ - --retention-period "1h" \ - --idle-timeout "1h" \ + --retention-period "15min" \ + --idle-timeout "5min" \ --machine "largePremiumLinux" \ --status \ --default-permissions @@ -42,8 +42,8 @@ function api_create_codespace() { -f repo="$GITHUB_REPOSITORY" \ -f ref="$BRANCH" \ -f display_name="$CODESPACE_NAME" \ - -f retentionPeriod='1h' \ - -f idleTimeout='1h' \ + -f retentionPeriod='15min' \ + -f idleTimeout='5min' \ -f machineType=l'argePremiumLinux' \ -f status='true' \ -f defaultPermissions='true' \ @@ -60,7 +60,8 @@ function gh_fetch_codespace_id() { # connect to the codespace and start the services function gh_codespace_start_services() { echo "Running all services (over SSH)..." - (gh codespace ssh -c $CODESPACE_ID "npm start --prefix /workspaces/contoso-real-estate") & + # (gh codespace ssh -c $CODESPACE_ID "npm start --prefix /workspaces/contoso-real-estate") & + (gh codespace ssh -c $CODESPACE_ID "env") } # check all services are running @@ -146,7 +147,8 @@ gh_login; # gh_create_codespace; api_create_codespace; # gh_fetch_codespace_id; -gh_codespace_start_services; +wait_for_services; +# gh_codespace_start_services; wait_for_services; gh_codespace_check_services_status; gh_codespace_stop_and_delete; From a297e9d79d9c4f7c8783df77a74fd3ca6ac1482d Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Wed, 20 Mar 2024 14:02:24 +0100 Subject: [PATCH 12/14] ci: upgrade docker-in-docker to v2 --- .devcontainer/devcontainer.json | 3 ++- .github/workflows/codespaces-ci.sh | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c8a7f21c6..13dd10802 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,9 +13,10 @@ "version": "18.15.0" }, "ghcr.io/devcontainers-contrib/features/postgres-asdf:1": {}, - "ghcr.io/devcontainers/features/docker-in-docker:1": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { "version": "20.10.23", "moby": "false", + "azureDnsAutoDetection": "false", "dockerDashComposeVersion": "v2" }, "ghcr.io/devcontainers/features/azure-cli:1": { diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh index 88d779d48..a6bd23cff 100755 --- a/.github/workflows/codespaces-ci.sh +++ b/.github/workflows/codespaces-ci.sh @@ -114,8 +114,8 @@ function gh_codespace_check_services_status() { # Wait for the services to start function wait_for_services() { - echo -ne "Waiting 30s for all services to start" - for i in {1..30}; do + echo -ne "Waiting 6 mintues for all dependencies to be installed and starting all services..." + for i in {1..360}; do echo -ne "." sleep 1 done @@ -147,7 +147,7 @@ gh_login; # gh_create_codespace; api_create_codespace; # gh_fetch_codespace_id; -wait_for_services; +# wait_for_services; # gh_codespace_start_services; wait_for_services; gh_codespace_check_services_status; From 1e249923267f57a09851ac0bf9c776994b6bbb28 Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Thu, 4 Apr 2024 16:03:47 +0200 Subject: [PATCH 13/14] ci: change error color from red to purple --- .github/workflows/codespaces-ci.sh | 32 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh index a6bd23cff..85e5b058c 100755 --- a/.github/workflows/codespaces-ci.sh +++ b/.github/workflows/codespaces-ci.sh @@ -1,18 +1,20 @@ #!/bin/bash set -e +# IMPORTANT:a valid GITHUB_TOKEN is required to run this script + GITHUB_REPOSITORY="Azure-Samples/contoso-real-estate" BRANCH="codespaces-ci" CODESPACE_NAME="ci-nightly-build-$(date +%s)" CODESPACE_ID="" -RED='\033[0;31m' +RED='\033[0;35m' # this is not red, it's purple! GREEN='\033[0;32m' NC='\033[0m' # No Color # login to GitHub CLI function gh_login() { echo "Loging in with GitHub CLI as admin..." - echo $X_GITHUB_TOKEN | gh auth login --with-token + echo $X_GITHUB_TOKEN | gh auth login --with-token echo "Checking auth status..." gh auth status @@ -33,7 +35,7 @@ function gh_create_codespace() { } function api_create_codespace() { echo "Creating a codespace $CODESPACE_NAME for $GITHUB_REPOSITORY on branch $BRANCH (w/ api)..." - CODESPACE_ID=$(gh api \ + response=$(gh api \ /repos/$GITHUB_REPOSITORY/codespaces \ -X POST \ -H 'Accept: application/vnd.github+json' \ @@ -46,9 +48,14 @@ function api_create_codespace() { -f idleTimeout='5min' \ -f machineType=l'argePremiumLinux' \ -f status='true' \ - -f defaultPermissions='true' \ - -q '.name') - echo "Codespace created and started: $CODESPACE_ID" + -f defaultPermissions='true') + CODESPACE_ID=$(echo "$response" | jq '.name') + CODESPACE_URL=$(echo "$response" | jq '.web_url') + CODESPACE_API=$(echo "$response" | jq '.url') + echo "Codespace created and started:" + echo " - ID: $CODESPACE_ID" + echo " - Web: $CODESPACE_URL" + echo " - API: $CODESPACE_API" } # fetch the codespace ID @@ -81,7 +88,7 @@ function gh_codespace_check_services_status() { fi nb_services_down=0 - echo "---------------------------------------------------------------------------------------------------------" + echo "---------------------------------------------------------------------------------------------------------" for service in $services; do echo -ne "Inspecting: $service ... " status=$(curl -H "X-Github-Token: $GITHUB_TOKEN" -s -o /dev/null -w "%{http_code}" $service) @@ -112,12 +119,15 @@ function gh_codespace_check_services_status() { done } -# Wait for the services to start +# Wait for all services to start function wait_for_services() { - echo -ne "Waiting 6 mintues for all dependencies to be installed and starting all services..." - for i in {1..360}; do + echo "Waiting 10 mintues for all dependencies to be installed and starting all services" + for i in {1..600}; do echo -ne "." sleep 1 + if ! ((i % 60)); then + echo "" + fi done echo "" } @@ -152,4 +162,4 @@ api_create_codespace; wait_for_services; gh_codespace_check_services_status; gh_codespace_stop_and_delete; -print_report_and_exit; \ No newline at end of file +print_report_and_exit; From 163c2ef267d6d87352a2cef118519793d12de84a Mon Sep 17 00:00:00 2001 From: Wassim Chegham Date: Thu, 4 Apr 2024 16:08:59 +0200 Subject: [PATCH 14/14] ci: use proper token var --- .devcontainer/post-create-command.sh | 4 ++-- .github/workflows/codespaces-ci.sh | 15 ++++++++------- .github/workflows/codespaces-ci.yml | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.devcontainer/post-create-command.sh b/.devcontainer/post-create-command.sh index 1af2605d6..c1d83199a 100755 --- a/.devcontainer/post-create-command.sh +++ b/.devcontainer/post-create-command.sh @@ -14,5 +14,5 @@ npm install # run npm start if CODESPACE_NAME starts with "CODESPACE_NAME=nightly-build" if [[ $CODESPACE_NAME == "ci-nightly-build"* ]]; then - npm start -fi \ No newline at end of file + npm start > npm _start.log 2>&1 & +fi diff --git a/.github/workflows/codespaces-ci.sh b/.github/workflows/codespaces-ci.sh index 85e5b058c..d1f79e66f 100755 --- a/.github/workflows/codespaces-ci.sh +++ b/.github/workflows/codespaces-ci.sh @@ -1,13 +1,14 @@ #!/bin/bash set -e -# IMPORTANT:a valid GITHUB_TOKEN is required to run this script +# IMPORTANT: a valid X_GITHUB_TOKEN is required to run this script +# Token must have the following permissions: 'admin:org', 'codespace', 'repo' GITHUB_REPOSITORY="Azure-Samples/contoso-real-estate" BRANCH="codespaces-ci" CODESPACE_NAME="ci-nightly-build-$(date +%s)" CODESPACE_ID="" -RED='\033[0;35m' # this is not red, it's purple! +RED='\033[0m' # this is not red, it's just to reset the color GREEN='\033[0;32m' NC='\033[0m' # No Color @@ -49,9 +50,9 @@ function api_create_codespace() { -f machineType=l'argePremiumLinux' \ -f status='true' \ -f defaultPermissions='true') - CODESPACE_ID=$(echo "$response" | jq '.name') - CODESPACE_URL=$(echo "$response" | jq '.web_url') - CODESPACE_API=$(echo "$response" | jq '.url') + CODESPACE_ID=$(echo "$response" | jq -r '.name') + CODESPACE_URL=$(echo "$response" | jq -r '.web_url') + CODESPACE_API=$(echo "$response" | jq -r '.url') echo "Codespace created and started:" echo " - ID: $CODESPACE_ID" echo " - Web: $CODESPACE_URL" @@ -91,7 +92,7 @@ function gh_codespace_check_services_status() { echo "---------------------------------------------------------------------------------------------------------" for service in $services; do echo -ne "Inspecting: $service ... " - status=$(curl -H "X-Github-Token: $GITHUB_TOKEN" -s -o /dev/null -w "%{http_code}" $service) + status=$(curl -H "X-Github-Token: $X_GITHUB_TOKEN" -s -o /dev/null -w "%{http_code}" $service) if [ $status == 200 ] || [ $status == 404 ]; then echo -e "${GREEN}$status OK${NC}" @@ -121,7 +122,7 @@ function gh_codespace_check_services_status() { # Wait for all services to start function wait_for_services() { - echo "Waiting 10 mintues for all dependencies to be installed and starting all services" + echo "Waiting 10 minutes for all dependencies to be installed and starting all services\n" for i in {1..600}; do echo -ne "." sleep 1 diff --git a/.github/workflows/codespaces-ci.yml b/.github/workflows/codespaces-ci.yml index 4bcb7e4f4..f635f9a44 100644 --- a/.github/workflows/codespaces-ci.yml +++ b/.github/workflows/codespaces-ci.yml @@ -18,5 +18,5 @@ jobs: - name: Deploy to Codespace env: - X_GITHUB_TOKEN: ${{ secrets.CODESPACES_TOKEN }} - run: ./.github/workflows/codespaces-ci.sh \ No newline at end of file + X_GITHUB_TOKEN: ${{ secrets.X_GITHUB_TOKEN }} + run: ./.github/workflows/codespaces-ci.sh