From 6780a16a4aac92ebaa64c93881efc5d28f385f51 Mon Sep 17 00:00:00 2001 From: ggetz Date: Fri, 10 Oct 2025 11:01:55 -0400 Subject: [PATCH 1/5] Fix coverage link in CI --- .github/workflows/dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 3355278ad295..2389f2cfea05 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -31,6 +31,7 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} AWS_REGION: us-east-1 BRANCH: ${{ github.ref_name }} + DEPLOYED_URL: https://ci-builds.cesium.com/cesium/${{ github.ref_name }}/ steps: - uses: actions/checkout@v5 - name: install node 22 From d771cf02b7b2be2e7968220fd6fc80c85568961c Mon Sep 17 00:00:00 2001 From: ggetz Date: Mon, 13 Oct 2025 15:49:35 -0400 Subject: [PATCH 2/5] Centralize env vars in env; Refactor deployment checks --- .env | 17 +++ .github/workflows/deploy.yml | 28 ++-- .github/workflows/dev.yml | 16 ++- .github/workflows/prod.yml | 1 - .github/workflows/sandcastle-dev.yml | 1 - .../Contributors/BuildGuide/README.md | 3 - .../ContinuousIntegration/README.md | 47 +++---- gulpfile.js | 67 +--------- package.json | 6 +- scripts/setDeployStatus.js | 123 ++++++++++++++++++ 10 files changed, 194 insertions(+), 115 deletions(-) create mode 100644 .env create mode 100644 scripts/setDeployStatus.js diff --git a/.env b/.env new file mode 100644 index 000000000000..af4d6aeacc86 --- /dev/null +++ b/.env @@ -0,0 +1,17 @@ +# Get the current git values from GitHub Action variables if triggered from pull-reqest or push; otherwise fallback to the current local git branch +BRANCH="$(git branch --show-current)" +BRANCH=${PULL_REQUEST_HEAD_REF:-${GITHUB_REF_NAME:-${BRANCH}}} +COMMIT_SHA="$(git rev-parse HEAD)" +COMMIT_SHA=${PULL_REQUEST_HEAD_SHA:-${GITHUB_SHA:-${COMMIT_SHA}}} + +# Read the Cesium version from package.json +CESIUM_VERSION=$(npm pkg get version | tr -d '"') + +# Build artifact configuration +BUILD_ARTIFACT_BUCKET="cesium-public-builds" +BUILD_ARTIFACT_URL="https://ci-builds.cesium.com/cesium/${BRANCH}" + +INDEX_URL="${BUILD_ARTIFACT_URL}/index.html" +ZIP_URL="${BUILD_ARTIFACT_URL}/Cesium-${CESIUM_VERSION}.zip" +NPM_URL="${BUILD_ARTIFACT_URL}/cesium-${CESIUM_VERSION}.tgz" +COVERAGE_URL="${BUILD_ARTIFACT_URL}/Build/Coverage/index.html" \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8f4e156b4e0b..f530d378f8a0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -14,16 +14,12 @@ jobs: statuses: write contents: read env: - BUILD_VERSION: ${{ github.ref_name }}.${{ github.run_number }} AWS_ACCESS_KEY_ID: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} AWS_REGION: us-east-1 - BRANCH: ${{ github.ref_name }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPO: ${{ github.repository }} GITHUB_SHA: ${{ github.sha }} BASE_URL: /cesium/${{ github.ref_name }}/ - DEPLOYED_URL: https://ci-builds.cesium.com/cesium/${{ github.ref_name }}/ steps: - uses: actions/checkout@v5 - name: install node 22 @@ -32,8 +28,16 @@ jobs: node-version: '22' - name: npm install run: npm install - - name: set the version in package.json - run: npm run deploy-set-version -- --buildVersion $BUILD_VERSION + - name: set version in package.json + run: | + npx @dotenvx/dotenvx run -- sh -c \ + 'npm version prerelease --preid $BRANCH --ws --include-workspace-root --no-git-tag-version' + - name: set status pending + if: ${{ env.AWS_ACCESS_KEY_ID != '' }} + run: | + node ./scripts/setDeployStatus.js zip pending + node ./scripts/setDeployStatus.js npm pending + node ./scripts/setDeployStatus.js index pending - name: create release zip run: npm run make-zip - name: package cesium module @@ -48,7 +52,8 @@ jobs: - name: deploy to s3 if: ${{ env.AWS_ACCESS_KEY_ID != '' }} run: | - aws s3 sync . s3://cesium-public-builds/cesium/$BRANCH/ \ + npx @dotenvx/dotenvx run -- sh -c \ + 'aws s3 sync . s3://$BUILD_ARTIFACT_BUCKET/cesium/$BRANCH/ \ --cache-control "no-cache" \ --exclude ".git/*" \ --exclude ".github/*" \ @@ -61,7 +66,10 @@ jobs: --exclude "node_modules/*" \ --exclude "scripts/*" \ --exclude "Tools/*" \ - --delete - - name: set status + --delete' + - name: set status success if: ${{ env.AWS_ACCESS_KEY_ID != '' }} - run: npm run deploy-status -- --status success --message Deployed + run: | + node ./scripts/setDeployStatus.js zip ${{ job.status }} + node ./scripts/setDeployStatus.js npm ${{ job.status }} + node ./scripts/setDeployStatus.js index ${{ job.status }} diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 2389f2cfea05..7eb27dbe669f 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -30,8 +30,12 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} AWS_REGION: us-east-1 - BRANCH: ${{ github.ref_name }} - DEPLOYED_URL: https://ci-builds.cesium.com/cesium/${{ github.ref_name }}/ + PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request && github.event.pull_request.head.sha || '' }} + PULL_REQUEST_HEAD_REF: ${{ github.event.pull_request && github.event.pull_request.head.ref || '' }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + permissions: + statuses: write + contents: read steps: - uses: actions/checkout@v5 - name: install node 22 @@ -40,13 +44,19 @@ jobs: node-version: '22' - name: npm install run: npm install + - name: set status pending + if: ${{ env.AWS_ACCESS_KEY_ID != '' }} + run: node ./scripts/setDeployStatus.js coverage pending - name: build run: npm run build - name: coverage (firefox) run: npm run coverage -- --browsers FirefoxHeadless --webgl-stub --failTaskOnError --suppressPassed - name: upload coverage artifacts if: ${{ env.AWS_ACCESS_KEY_ID != '' }} - run: aws s3 sync ./Build/Coverage s3://cesium-public-builds/cesium/$BRANCH/Build/Coverage --delete --color on + run: npx @dotenvx/dotenvx run -- sh -c 'aws s3 sync ./Build/Coverage s3://$BUILD_ARTIFACT_BUCKET/cesium/$BRANCH/Build/Coverage --delete --color on' + - name: set status success + if: ${{ env.AWS_ACCESS_KEY_ID != '' }} + run: node ./scripts/setDeployStatus.js coverage ${{ job.status }} release-tests: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml index 628d8890ac5e..113ff4d1c1a2 100644 --- a/.github/workflows/prod.yml +++ b/.github/workflows/prod.yml @@ -29,7 +29,6 @@ jobs: AWS_REGION: us-east-1 BRANCH: ${{ github.ref_name }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPO: ${{ github.repository }} GITHUB_SHA: ${{ github.sha }} steps: - uses: actions/checkout@v5 diff --git a/.github/workflows/sandcastle-dev.yml b/.github/workflows/sandcastle-dev.yml index 1aec62462108..c4fd3415e216 100644 --- a/.github/workflows/sandcastle-dev.yml +++ b/.github/workflows/sandcastle-dev.yml @@ -13,7 +13,6 @@ jobs: AWS_REGION: us-east-1 BRANCH: ${{ github.ref_name }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPO: ${{ github.repository }} GITHUB_SHA: ${{ github.sha }} steps: - uses: actions/checkout@v5 diff --git a/Documentation/Contributors/BuildGuide/README.md b/Documentation/Contributors/BuildGuide/README.md index 3471d2d628d2..d2137ff4635f 100644 --- a/Documentation/Contributors/BuildGuide/README.md +++ b/Documentation/Contributors/BuildGuide/README.md @@ -153,6 +153,3 @@ Here's the full set of scripts and what they do. - `test-webgl-stub` - Runs all tests using the WebGL stub, which WebGL calls a noop and ignores related test expectations - `test-webgl-validation` - Runs all tests with Karma and enables low-level WebGL validation - `test-release` - Runs all tests on the minified release version of built Cesium -- **Deployment scripts** - - `deploy-status` - Sets the deployment statuses in GitHub, for use in CI - - `deploy-set-version` - Sets the version of `package.json`, for use in CI diff --git a/Documentation/Contributors/ContinuousIntegration/README.md b/Documentation/Contributors/ContinuousIntegration/README.md index 0a9b714951ed..3c930b5dc942 100644 --- a/Documentation/Contributors/ContinuousIntegration/README.md +++ b/Documentation/Contributors/ContinuousIntegration/README.md @@ -18,51 +18,42 @@ CesiumJS uses [GitHub Actions](https://docs.github.com/en/actions) for continuou Reusable actions are defined in `/.github/actions/` and workflows in `.github/workflows/`. -A workflow is triggered whenever someone pushes code to the CesiumJS repository, or an external contributor opens a pull request. After the build has completed, at the bottom of the pull request page the status of the build is shown. In the dropdown menu, individual checks are displayed. Logs and deployed artifacts can be accessed by clicking the "Details" link. +Workflows are triggered when a commit is pushed to the `cesium` repository and when a contributor opens or updates a pull request. After the build has completed, the overall status of the build is shown at the bottom of the pull request page. + +In the dropdown menu, individual status checks are displayed. Logs and deployed build artifacts can be accessed by clicking the link associated with the individual check. ![GitHub Action Checks](github_action_checks.png) -The workflow checks for any CesiumJS branch are accessible under the [Branches](https://github.com/CesiumGS/cesium/branches/all) page by clicking the icon next to the branch name. +The status checks for any branch are also accessible under the [Branches](https://github.com/CesiumGS/cesium/branches/all) page by clicking the icon next to the branch name. ![GitHub Branches](github_branches.png) ## Continuous deployment -Automated deployments make recent code changes available for testing and review without needing to fetch and build locally. We deploy each of the following on a per-branch basis. +Automated deployments make recent code changes available for convenient testing and review—No need to fetch or build locally. In the `cesium` repository, all continuous deployment artifacts are uploaded for commits authored by users with commit access. + +Each of the following are deployed on a per-branch basis. -| Artifact | Link (`main` branch) | -| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Sandcastle | [`https://ci-builds.cesium.com/cesium/main/Apps/Sandcastle/index.html`](https://ci-builds.cesium.com/cesium/main/Apps/Sandcastle/index.html) | -| Documentation | [`https://ci-builds.cesium.com/cesium/main/Build/Documentation/index.html`](https://ci-builds.cesium.com/cesium/main/Build/Documentation/index.html) | -| Coverage results | [`https://ci-builds.cesium.com/cesium/main/Build/Coverage/index.html`](https://ci-builds.cesium.com/cesium/main/Build/Coverage/index.html) | -| Release zip | [`https://ci-builds.cesium.com/cesium/main/..zip`](https://ci-builds.cesium.com/cesium/main/..zip) | -| npm package | [`https://ci-builds.cesium.com/cesium/main/..tgz`](https://ci-builds.cesium.com/cesium/main/..tgz) | +| Artifact | Link pattern (`main`) | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Sandcastle | `https://ci-builds.cesium.com/cesium//Apps/Sandcastle/index.html` (i.e., [`https://ci-builds.cesium.com/cesium/main/Apps/Sandcastle/index.html`](https://ci-builds.cesium.com/cesium/main/Apps/Sandcastle/index.html)) | +| Documentation | `https://ci-builds.cesium.com/cesium//Build/Documentation/index.html` (i.e., [`https://ci-builds.cesium.com/cesium/main/Build/Documentation/index.html`](https://ci-builds.cesium.com/cesium/main/Build/Documentation/index.html)) | +| Coverage results | `https://ci-builds.cesium.com/cesium//Build/Coverage/index.html` (i.e., [`https://ci-builds.cesium.com/cesium/main/Build/Coverage/index.html`](https://ci-builds.cesium.com/cesium/main/Build/Coverage/index.html)) | +| Release zip | `https://ci-builds.cesium.com/cesium//Cesium--.0.zip` (i.e., [`https://ci-builds.cesium.com/cesium/main/Cesium-1.X.X-main.0.zip`](https://ci-builds.cesium.com/cesium/main/Cesium-1.X.X-main.0.zip)) | +| npm package | `https://ci-builds.cesium.com/cesium//cesium--.0.tgz` (i.e., [`https://ci-builds.cesium.com/cesium/main/cesium-1.X.X-main.0.tgz`](https://ci-builds.cesium.com/cesium/main/cesium-1.X.X-main.0.tgz)) | ## Configuration -Additional set up is required for deployment if you do not have commit access to CesiumJS. +Additional set up is required for deployment _only_ if you do not have commit access to CesiumJS. ### Configure a different S3 bucket -It is possible to configure your development branch of CesiumJS to deploy build artifacts to a different [AWS S3 Bucket](http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html). If you are using the cesium-public-builds bucket and have valid credentials, skip to [Configure S3 Credentials](#configure-s3-credentials) - -- In `.gtihub/workflows/dev.yml`, in the following lines, replace "cesium-public-builds" with the name of your S3 bucket. - -```sh -aws s3 sync ./Build/Coverage s3://cesium-public-builds/cesium/$BRANCH/Build/Coverage --delete --color on -``` - -```sh -aws s3 sync Build/unzipped/ s3://cesium-public-builds/cesium/$BRANCH/Build/ --cache-control "no-cache" --delete -``` - -- In `gulpfile.js`, edit the following line: +It is possible to configure your development branch of CesiumJS to deploy build artifacts to a different [AWS S3 Bucket](http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html). If you are using the default "cesium-public-builds" bucket and have valid credentials, skip to [Configure S3 Credentials](#configure-s3-credentials) -```javascript -const devDeployUrl = "https://ci-builds.cesium.com/cesium/"; -``` +In the environment file `.env`, update the following values: -- Edit the URL to match the URL hosting the S3 bucket specified in the previous step. +- Replace the value of `BUILD_ARTIFACT_BUCKET` with the name of the target S3 bucket. +- Replace the value of `BUILD_ARTIFACT_URL` with the public URL correspondeding to the target S3 bucket. ### Configure S3 credentials diff --git a/gulpfile.js b/gulpfile.js index 28297313b758..4b0c3eca3209 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2,7 +2,6 @@ import { writeFileSync, copyFileSync, readFileSync, existsSync } from "fs"; import { readFile, writeFile } from "fs/promises"; import { join, basename, resolve, dirname } from "path"; import { exec, execSync } from "child_process"; -import fetch from "node-fetch"; import { createRequire } from "module"; import { finished } from "stream/promises"; @@ -39,7 +38,8 @@ const scope = "cesium"; const require = createRequire(import.meta.url); const packageJson = require("./package.json"); let version = packageJson.version; -if (/\.0$/.test(version)) { +if (/\.\d+\.0$/.test(version)) { + // Removes the patch release ".0" at the end of any non-prelease version version = version.substring(0, version.length - 2); } const karmaConfigFile = resolve("./Specs/karma.conf.cjs"); @@ -54,7 +54,6 @@ function getWorkspaces(onlyDependencies = false) { : packageJson.workspaces; } -const devDeployUrl = process.env.DEPLOYED_URL; const isProduction = process.env.PROD; //Gulp doesn't seem to have a way to get the currently running tasks for setting @@ -554,8 +553,6 @@ async function pruneScriptsForZip(packageJsonPath) { delete scripts.prettier; // Remove deploy tasks - delete scripts["deploy-status"]; - delete scripts["deploy-set-version"]; delete scripts["website-release"]; // Set server tasks to use production flag @@ -698,66 +695,6 @@ export const makeZip = gulp.series(release, async function createZipFile() { return src; }); -export async function deploySetVersion() { - const buildVersion = argv.buildVersion; - if (buildVersion) { - // NPM versions can only contain alphanumeric and hyphen characters - packageJson.version += `-${buildVersion.replace(/[^[0-9A-Za-z-]/g, "")}`; - return writeFile("package.json", JSON.stringify(packageJson, undefined, 2)); - } -} - -export async function deployStatus() { - const status = argv.status; - const message = argv.message; - const deployUrl = `${devDeployUrl}`; - const zipUrl = `${deployUrl}Cesium-${version}.zip`; - const npmUrl = `${deployUrl}cesium-${version}.tgz`; - const coverageUrl = `${deployUrl}Build/Coverage/index.html`; - - return Promise.all([ - setStatus(status, deployUrl, message, "deploy / artifact: deployment"), - setStatus(status, zipUrl, message, "deploy / artifact: zip file"), - setStatus(status, npmUrl, message, "deploy / artifact: npm package"), - setStatus( - status, - coverageUrl, - message, - "deploy / artifact: coverage results", - ), - ]); -} - -async function setStatus(state, targetUrl, description, context) { - // skip if the environment does not have the token - if (!process.env.GITHUB_TOKEN) { - return; - } - - const body = { - state: state, - target_url: targetUrl, - description: description, - context: context, - }; - - const response = await fetch( - `https://api.github.com/repos/${process.env.GITHUB_REPO}/statuses/${process.env.GITHUB_SHA}`, - { - method: "post", - body: JSON.stringify(body), - headers: { - "Content-Type": "application/json", - Authorization: `token ${process.env.GITHUB_TOKEN}`, - "User-Agent": "Cesium", - }, - }, - ); - - const result = await response.json(); - return result; -} - /** * Generates coverage report. * diff --git a/package.json b/package.json index 5723fedcdf0c..09234fe731fb 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ ], "repository": { "type": "git", - "url": "https://github.com/CesiumGS/cesium.git" + "url": "git+https://github.com/CesiumGS/cesium.git" }, "bugs": { "url": "https://github.com/CesiumGS/cesium/issues" @@ -56,6 +56,7 @@ }, "devDependencies": { "@cesium/eslint-config": "^12.0.0", + "@dotenvx/dotenvx": "^1.51.0", "@playwright/test": "^1.41.1", "chokidar": "^4.0.1", "cloc": "^2.6.0-cloc", @@ -95,7 +96,6 @@ "markdownlint-cli": "^0.45.0", "merge-stream": "^2.0.0", "mkdirp": "^3.0.1", - "node-fetch": "^3.2.10", "open": "^10.0.2", "prettier": "3.6.2", "prismjs": "^1.28.0", @@ -139,8 +139,6 @@ "test-e2e-release-all": "release=true playwright test -c Specs/e2e/playwright.config.js", "test-e2e-report": "playwright show-report Build/Specs/e2e/report", "test-e2e-update": "playwright test -c Specs/e2e/playwright.config.js --project=chromium -u", - "deploy-status": "gulp deployStatus", - "deploy-set-version": "gulp deploySetVersion", "prettier": "prettier --write \"**/*\"", "prettier-check": "prettier --check \"**/*\"", "cspell": "npx cspell lint -c .vscode/cspell.json --unique --no-progress" diff --git a/scripts/setDeployStatus.js b/scripts/setDeployStatus.js new file mode 100644 index 000000000000..a4db53480e00 --- /dev/null +++ b/scripts/setDeployStatus.js @@ -0,0 +1,123 @@ +import yargs from "yargs"; +import { hideBin } from "yargs/helpers"; +import "@dotenvx/dotenvx/config"; + +const GITHUB_TOKEN = process.env.GITHUB_TOKEN; +const GITHUB_REPO = process.env.GITHUB_REPOSITORY; +const COMMIT_SHA = process.env.COMMIT_SHA; +const CESIUM_VERSION = process.env.CESIUM_VERSION; + +export async function setDeployStatus({ status, url, context, message }) { + if (!GITHUB_TOKEN || GITHUB_TOKEN === "") { + throw new Error(`Environment variable is not defined: "GITHUB_TOKEN"`); + } + + if (!GITHUB_REPO || GITHUB_REPO === "") { + throw new Error(`Environment variable is not defined: "GITHUB_REPO"`); + } + + if (!COMMIT_SHA || COMMIT_SHA === "") { + throw new Error(`Environment variable is not defined: "COMMIT_SHA"`); + } + + const body = { + state: status, + context: context, + target_url: url, + description: message, + }; + + console.log(`Posting ${GITHUB_REPO} commit status of ${COMMIT_SHA}: + ${JSON.stringify(body, null, 2)}`); + + const response = await fetch( + `https://api.github.com/repos/${GITHUB_REPO}/statuses/${COMMIT_SHA}`, + { + method: "post", + body: JSON.stringify(body), + headers: { + "Content-Type": "application/json", + Authorization: `token ${GITHUB_TOKEN}`, + "User-Agent": "Cesium", + }, + }, + ); + + if (!response.ok) { + throw new Error(`Responded with ${response.status}`); + } + + const result = await response.json(); + return result; +} + +await yargs() + .command( + "* [context] [url] [message]", + "set deploy status of a build artifact", + (yargs) => + yargs + .positional("status", { + type: "string", + choices: ["error", "failure", "pending", "success"], + describe: "The state that the commit will be marked as.", + }) + .positional("context", { + type: "string", + describe: "A label to differentiate this status check.", + }) + .positional("url", { + type: "string", + describe: "The linked URL to associate with this status.", + }) + .positional("message", { + type: "string", + describe: "A short description of the status.", + }), + setDeployStatus, + ) + .command( + "coverage ", + "set deploy status of a build artifact", + () => {}, + async ({ status }) => + setDeployStatus({ + status, + url: process.env.COVERAGE_URL, + context: "deploy / artifact: coverage report", + }), + ) + .command( + "zip ", + "set deploy status of the zip file", + () => {}, + async ({ status }) => + setDeployStatus({ + status, + url: process.env.ZIP_URL, + context: `deploy / artifact: Cesium-${CESIUM_VERSION}.zip`, + }), + ) + .command( + "npm ", + "set deploy status of the npm package", + () => {}, + async ({ status }) => + setDeployStatus({ + status, + url: process.env.NPM_URL, + context: `deploy / artifact: cesium-${CESIUM_VERSION}.tgz`, + }), + ) + .command( + "index ", + "set deploy status of the static build", + () => {}, + async ({ status }) => + setDeployStatus({ + status, + url: process.env.INDEX_URL, + context: "deploy / artifact: index.html", + }), + ) + .parse(hideBin(process.argv)); From 1ccaa77c83db1c3205b32e299de50271acc33bf3 Mon Sep 17 00:00:00 2001 From: ggetz Date: Mon, 13 Oct 2025 16:31:29 -0400 Subject: [PATCH 3/5] Use correct workflow name --- .env | 2 +- scripts/setDeployStatus.js | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.env b/.env index af4d6aeacc86..9cc21cfde6f9 100644 --- a/.env +++ b/.env @@ -4,7 +4,7 @@ BRANCH=${PULL_REQUEST_HEAD_REF:-${GITHUB_REF_NAME:-${BRANCH}}} COMMIT_SHA="$(git rev-parse HEAD)" COMMIT_SHA=${PULL_REQUEST_HEAD_SHA:-${GITHUB_SHA:-${COMMIT_SHA}}} -# Read the Cesium version from package.json +# Read the CesiumJS version from package.json CESIUM_VERSION=$(npm pkg get version | tr -d '"') # Build artifact configuration diff --git a/scripts/setDeployStatus.js b/scripts/setDeployStatus.js index a4db53480e00..ece1b3ae0e86 100644 --- a/scripts/setDeployStatus.js +++ b/scripts/setDeployStatus.js @@ -4,6 +4,7 @@ import "@dotenvx/dotenvx/config"; const GITHUB_TOKEN = process.env.GITHUB_TOKEN; const GITHUB_REPO = process.env.GITHUB_REPOSITORY; +const GITHUB_WORKFLOW = process.env.GITHUB_WORKFLOW; const COMMIT_SHA = process.env.COMMIT_SHA; const CESIUM_VERSION = process.env.CESIUM_VERSION; @@ -51,6 +52,14 @@ export async function setDeployStatus({ status, url, context, message }) { return result; } +const getArtifactContext = (artifact) => { + if (!GITHUB_WORKFLOW || GITHUB_WORKFLOW === "") { + return `artifact: ${artifact}`; + } + + return `${GITHUB_WORKFLOW} / artifact: ${artifact}`; +}; + await yargs() .command( "* [context] [url] [message]", @@ -84,7 +93,7 @@ await yargs() setDeployStatus({ status, url: process.env.COVERAGE_URL, - context: "deploy / artifact: coverage report", + context: getArtifactContext("coverage report"), }), ) .command( @@ -95,7 +104,7 @@ await yargs() setDeployStatus({ status, url: process.env.ZIP_URL, - context: `deploy / artifact: Cesium-${CESIUM_VERSION}.zip`, + context: getArtifactContext(`Cesium-${CESIUM_VERSION}.zip`), }), ) .command( @@ -106,7 +115,7 @@ await yargs() setDeployStatus({ status, url: process.env.NPM_URL, - context: `deploy / artifact: cesium-${CESIUM_VERSION}.tgz`, + context: getArtifactContext(`cesium-${CESIUM_VERSION}.tgz`), }), ) .command( @@ -117,7 +126,7 @@ await yargs() setDeployStatus({ status, url: process.env.INDEX_URL, - context: "deploy / artifact: index.html", + context: getArtifactContext("index.html"), }), ) .parse(hideBin(process.argv)); From 9a459e96d8a6a966148c442674ae25640498a061 Mon Sep 17 00:00:00 2001 From: ggetz Date: Tue, 14 Oct 2025 12:07:58 -0400 Subject: [PATCH 4/5] Seperate .env per environment, docs --- .env | 10 ++--- .github/workflows/.env.pull_request | 2 + .github/workflows/.env.push | 2 + .github/workflows/coverage.yml | 45 +++++++++++++++++++ .github/workflows/deploy.yml | 27 ++++++----- .github/workflows/dev.yml | 39 ++-------------- .../ContinuousIntegration/README.md | 15 ++++++- ...{setDeployStatus.js => setCommitStatus.js} | 24 +++++----- 8 files changed, 97 insertions(+), 67 deletions(-) create mode 100644 .github/workflows/.env.pull_request create mode 100644 .github/workflows/.env.push create mode 100644 .github/workflows/coverage.yml rename scripts/{setDeployStatus.js => setCommitStatus.js} (85%) diff --git a/.env b/.env index 9cc21cfde6f9..61b8435979f5 100644 --- a/.env +++ b/.env @@ -1,15 +1,15 @@ -# Get the current git values from GitHub Action variables if triggered from pull-reqest or push; otherwise fallback to the current local git branch +# These variables are ovveridden in CI with GitHub Action variables if triggered from pull-reqest or push; +# Locally, fallback to the current local git status BRANCH="$(git branch --show-current)" -BRANCH=${PULL_REQUEST_HEAD_REF:-${GITHUB_REF_NAME:-${BRANCH}}} COMMIT_SHA="$(git rev-parse HEAD)" -COMMIT_SHA=${PULL_REQUEST_HEAD_SHA:-${GITHUB_SHA:-${COMMIT_SHA}}} # Read the CesiumJS version from package.json CESIUM_VERSION=$(npm pkg get version | tr -d '"') # Build artifact configuration -BUILD_ARTIFACT_BUCKET="cesium-public-builds" -BUILD_ARTIFACT_URL="https://ci-builds.cesium.com/cesium/${BRANCH}" +BUILD_ARTIFACT_PATH="cesium/${BRANCH}" +BUILD_ARTIFACT_BUCKET="s3://cesium-public-builds/${BUILD_ARTIFACT_PATH}" +BUILD_ARTIFACT_URL="https://ci-builds.cesium.com/${BUILD_ARTIFACT_PATH}" INDEX_URL="${BUILD_ARTIFACT_URL}/index.html" ZIP_URL="${BUILD_ARTIFACT_URL}/Cesium-${CESIUM_VERSION}.zip" diff --git a/.github/workflows/.env.pull_request b/.github/workflows/.env.pull_request new file mode 100644 index 000000000000..4e83e6a570eb --- /dev/null +++ b/.github/workflows/.env.pull_request @@ -0,0 +1,2 @@ +BRANCH="$(jq -r .pull_request.head.ref ${GITHUB_EVENT_PATH})" +COMMIT_SHA="$(jq -r .pull_request.head.sha ${GITHUB_EVENT_PATH})" \ No newline at end of file diff --git a/.github/workflows/.env.push b/.github/workflows/.env.push new file mode 100644 index 000000000000..ea6d9a0ff956 --- /dev/null +++ b/.github/workflows/.env.push @@ -0,0 +1,2 @@ +BRANCH=${GITHUB_REF_NAME} +COMMIT_SHA=${GITHUB_SHA} \ No newline at end of file diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 000000000000..6e4848cb6613 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,45 @@ +name: coverage +on: + pull_request: +concurrency: + group: coverage-${{ github.ref }} + cancel-in-progress: true +jobs: + coverage: + runs-on: ubuntu-latest + env: + AWS_ACCESS_KEY_ID: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: us-east-1 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + permissions: + statuses: write + contents: read + steps: + - uses: actions/checkout@v5 + - name: install node 22 + uses: actions/setup-node@v5 + with: + node-version: "22" + - name: npm install + run: npm install + - name: set status pending + if: ${{ env.AWS_ACCESS_KEY_ID != '' }} + run: | + npx @dotenvx/dotenvx run -f ./.github/workflows/.env.pull_request -- \ + node ./scripts/setCommitStatus.js coverage pending + - name: build + run: npm run build + - name: coverage (firefox) + run: npm run coverage -- --browsers FirefoxHeadless --webgl-stub --failTaskOnError --suppressPassed + - name: upload coverage artifacts + if: ${{ env.AWS_ACCESS_KEY_ID != '' }} + run: | + npx @dotenvx/dotenvx run -f ./.github/workflows/.env.pull_request -f .env \ + -- sh -c \ + 'aws s3 sync ./Build/Coverage $BUILD_ARTIFACT_BUCKET/Build/Coverage --delete' + - name: set status success + if: ${{ env.AWS_ACCESS_KEY_ID != '' }} + run: | + npx @dotenvx/dotenvx run -f ./.github/workflows/.env.pull_request -- \ + node ./scripts/setCommitStatus.js coverage ${{ job.status }} \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f530d378f8a0..03cf4c9dd8ab 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,7 +2,7 @@ name: deploy on: push: branches-ignore: - - 'cesium.com' + - "cesium.com" - production concurrency: group: deploy-${{ github.ref }} @@ -18,26 +18,27 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} AWS_REGION: us-east-1 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_SHA: ${{ github.sha }} BASE_URL: /cesium/${{ github.ref_name }}/ steps: - uses: actions/checkout@v5 - name: install node 22 uses: actions/setup-node@v5 with: - node-version: '22' + node-version: "22" - name: npm install run: npm install - name: set version in package.json run: | - npx @dotenvx/dotenvx run -- sh -c \ + npx @dotenvx/dotenvx run -f ./.github/workflows/.env.push \ + -- sh -c \ 'npm version prerelease --preid $BRANCH --ws --include-workspace-root --no-git-tag-version' - name: set status pending if: ${{ env.AWS_ACCESS_KEY_ID != '' }} run: | - node ./scripts/setDeployStatus.js zip pending - node ./scripts/setDeployStatus.js npm pending - node ./scripts/setDeployStatus.js index pending + npx @dotenvx/dotenvx run -f ./.github/workflows/.env.push -- \ + node ./scripts/setCommitStatus.js zip pending && \ + node ./scripts/setCommitStatus.js npm pending && \ + node ./scripts/setCommitStatus.js index pending - name: create release zip run: npm run make-zip - name: package cesium module @@ -52,8 +53,9 @@ jobs: - name: deploy to s3 if: ${{ env.AWS_ACCESS_KEY_ID != '' }} run: | - npx @dotenvx/dotenvx run -- sh -c \ - 'aws s3 sync . s3://$BUILD_ARTIFACT_BUCKET/cesium/$BRANCH/ \ + npx @dotenvx/dotenvx run -f ./.github/workflows/.env.push -f .env \ + -- sh -c \ + 'aws s3 sync . $BUILD_ARTIFACT_BUCKET \ --cache-control "no-cache" \ --exclude ".git/*" \ --exclude ".github/*" \ @@ -70,6 +72,7 @@ jobs: - name: set status success if: ${{ env.AWS_ACCESS_KEY_ID != '' }} run: | - node ./scripts/setDeployStatus.js zip ${{ job.status }} - node ./scripts/setDeployStatus.js npm ${{ job.status }} - node ./scripts/setDeployStatus.js index ${{ job.status }} + npx @dotenvx/dotenvx run -f ./.github/workflows/.env.push -- \ + node ./scripts/setCommitStatus.js zip ${{ job.status }} && \ + node ./scripts/setCommitStatus.js npm ${{ job.status }} && \ + node ./scripts/setCommitStatus.js index ${{ job.status }} diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 7eb27dbe669f..109320579a1c 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -15,7 +15,7 @@ jobs: - name: install node 22 uses: actions/setup-node@v5 with: - node-version: '22' + node-version: "22" - name: npm install run: npm install - name: lint *.js @@ -24,39 +24,6 @@ jobs: run: npm run markdownlint - name: format code run: npm run prettier-check - coverage: - runs-on: ubuntu-latest - env: - AWS_ACCESS_KEY_ID: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} - AWS_REGION: us-east-1 - PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request && github.event.pull_request.head.sha || '' }} - PULL_REQUEST_HEAD_REF: ${{ github.event.pull_request && github.event.pull_request.head.ref || '' }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - permissions: - statuses: write - contents: read - steps: - - uses: actions/checkout@v5 - - name: install node 22 - uses: actions/setup-node@v5 - with: - node-version: '22' - - name: npm install - run: npm install - - name: set status pending - if: ${{ env.AWS_ACCESS_KEY_ID != '' }} - run: node ./scripts/setDeployStatus.js coverage pending - - name: build - run: npm run build - - name: coverage (firefox) - run: npm run coverage -- --browsers FirefoxHeadless --webgl-stub --failTaskOnError --suppressPassed - - name: upload coverage artifacts - if: ${{ env.AWS_ACCESS_KEY_ID != '' }} - run: npx @dotenvx/dotenvx run -- sh -c 'aws s3 sync ./Build/Coverage s3://$BUILD_ARTIFACT_BUCKET/cesium/$BRANCH/Build/Coverage --delete --color on' - - name: set status success - if: ${{ env.AWS_ACCESS_KEY_ID != '' }} - run: node ./scripts/setDeployStatus.js coverage ${{ job.status }} release-tests: runs-on: ubuntu-latest steps: @@ -64,7 +31,7 @@ jobs: - name: install node 22 uses: actions/setup-node@v5 with: - node-version: '22' + node-version: "22" - name: npm install run: npm install - name: release build @@ -80,7 +47,7 @@ jobs: - name: install node 20 uses: actions/setup-node@v5 with: - node-version: '20' + node-version: "20" - name: npm install run: npm install - name: release build diff --git a/Documentation/Contributors/ContinuousIntegration/README.md b/Documentation/Contributors/ContinuousIntegration/README.md index 3c930b5dc942..d589a566f5da 100644 --- a/Documentation/Contributors/ContinuousIntegration/README.md +++ b/Documentation/Contributors/ContinuousIntegration/README.md @@ -2,8 +2,9 @@ - [Background](#background) - [Actions and workflows](#actions-and-workflows) + - [Environment variables](#environment-variables) - [Continuous deployment](#continuous-deployment) -- [Configuration](#configuration) +- [Configuration guide](#configuration-guide) - [Configure a different S3 bucket](#configure-a-different-s3-bucket) - [Configure S3 credentials](#configure-s3-credentials) @@ -28,6 +29,16 @@ The status checks for any branch are also accessible under the [Branches](https: ![GitHub Branches](github_branches.png) +### Environment variables + +Any non-secret environment variables for CI and CD are managed using `.env` files and [dotenvx](https://github.com/dotenvx/dotenvx). + +- **Local dev**: `.env` is checked in at the repository root and provides defaults constant values and local fallbacks. + - To run a script or command with these variables configured locally, use `npx @dotenvx/dotenvx run -- `, e.g., `npx @dotenvx/dotenvx run -- node ./scripts/setCommitStatus.js`. + - To expand a variable directly in a command, use a subshell command, e.g., `npx @dotenvx/dotenvx run -- sh -c 'echo "${BRANCH}"'`. +- **GitHub Actions workflow - `push` trigger**: `.github/workflows/.env.push` +- **GitHub Actions workflow - `pull_request` trigger**: `.github/workflows/.env.pull_request` + ## Continuous deployment Automated deployments make recent code changes available for convenient testing and review—No need to fetch or build locally. In the `cesium` repository, all continuous deployment artifacts are uploaded for commits authored by users with commit access. @@ -42,7 +53,7 @@ Each of the following are deployed on a per-branch basis. | Release zip | `https://ci-builds.cesium.com/cesium//Cesium--.0.zip` (i.e., [`https://ci-builds.cesium.com/cesium/main/Cesium-1.X.X-main.0.zip`](https://ci-builds.cesium.com/cesium/main/Cesium-1.X.X-main.0.zip)) | | npm package | `https://ci-builds.cesium.com/cesium//cesium--.0.tgz` (i.e., [`https://ci-builds.cesium.com/cesium/main/cesium-1.X.X-main.0.tgz`](https://ci-builds.cesium.com/cesium/main/cesium-1.X.X-main.0.tgz)) | -## Configuration +## Configuration guide Additional set up is required for deployment _only_ if you do not have commit access to CesiumJS. diff --git a/scripts/setDeployStatus.js b/scripts/setCommitStatus.js similarity index 85% rename from scripts/setDeployStatus.js rename to scripts/setCommitStatus.js index ece1b3ae0e86..1c0b1b4c3aaf 100644 --- a/scripts/setDeployStatus.js +++ b/scripts/setCommitStatus.js @@ -8,7 +8,7 @@ const GITHUB_WORKFLOW = process.env.GITHUB_WORKFLOW; const COMMIT_SHA = process.env.COMMIT_SHA; const CESIUM_VERSION = process.env.CESIUM_VERSION; -export async function setDeployStatus({ status, url, context, message }) { +export async function setCommitStatus({ status, url, context, message }) { if (!GITHUB_TOKEN || GITHUB_TOKEN === "") { throw new Error(`Environment variable is not defined: "GITHUB_TOKEN"`); } @@ -63,7 +63,7 @@ const getArtifactContext = (artifact) => { await yargs() .command( "* [context] [url] [message]", - "set deploy status of a build artifact", + "set commit status, for example, to link to a build artifact", (yargs) => yargs .positional("status", { @@ -81,16 +81,16 @@ await yargs() }) .positional("message", { type: "string", - describe: "A short description of the status.", + describe: "A short description of this status.", }), - setDeployStatus, + setCommitStatus, ) .command( "coverage ", - "set deploy status of a build artifact", + "set deployment status of coverage results", () => {}, async ({ status }) => - setDeployStatus({ + setCommitStatus({ status, url: process.env.COVERAGE_URL, context: getArtifactContext("coverage report"), @@ -98,10 +98,10 @@ await yargs() ) .command( "zip ", - "set deploy status of the zip file", + "set deployment status of the release zip file", () => {}, async ({ status }) => - setDeployStatus({ + setCommitStatus({ status, url: process.env.ZIP_URL, context: getArtifactContext(`Cesium-${CESIUM_VERSION}.zip`), @@ -109,10 +109,10 @@ await yargs() ) .command( "npm ", - "set deploy status of the npm package", + "set deployment status of the npm package", () => {}, async ({ status }) => - setDeployStatus({ + setCommitStatus({ status, url: process.env.NPM_URL, context: getArtifactContext(`cesium-${CESIUM_VERSION}.tgz`), @@ -120,10 +120,10 @@ await yargs() ) .command( "index ", - "set deploy status of the static build", + "set deployment status of the static build", () => {}, async ({ status }) => - setDeployStatus({ + setCommitStatus({ status, url: process.env.INDEX_URL, context: getArtifactContext("index.html"), From 7a060c905f8391fa7dd687149ee4f04adacc117a Mon Sep 17 00:00:00 2001 From: Gabby Getz Date: Tue, 14 Oct 2025 16:07:14 -0400 Subject: [PATCH 5/5] Update .env Co-authored-by: jjspace <8007967+jjspace@users.noreply.github.com> --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 61b8435979f5..f67ef17208dc 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -# These variables are ovveridden in CI with GitHub Action variables if triggered from pull-reqest or push; +# These variables are overridden in CI with GitHub Action variables if triggered from pull-request or push; # Locally, fallback to the current local git status BRANCH="$(git branch --show-current)" COMMIT_SHA="$(git rev-parse HEAD)"