diff --git a/.github/actions/core-cicd/api-limits-check/Readme.md b/.github/actions/core-cicd/api-limits-check/Readme.md new file mode 100644 index 000000000000..e5c7e8823e2e --- /dev/null +++ b/.github/actions/core-cicd/api-limits-check/Readme.md @@ -0,0 +1,32 @@ +# Check GitHub API Rate Limit Action + +This GitHub Action allows you to check the current API rate limits for your GitHub account by querying the `/rate_limit` endpoint of the GitHub API. The action outputs the full JSON response, including rate limits for core, search, GraphQL, and other GitHub API resources. + +## Inputs + +| Input | Description | Required | Default | +|--------|-------------|----------|---------| +| `token` | The GitHub token to authenticate the API request. | true | `${{ github.token }}` | + +## Outputs + +The action outputs the full JSON response from the `/rate_limit` endpoint directly to the workflow log. + +## Usage + +Here’s an example of how to use this action in a GitHub workflow: + +```yaml +name: Check GitHub API Rate Limits + +on: + workflow_dispatch: + +jobs: + check-rate-limits: + runs-on: ubuntu-latest + steps: + - name: Check API Rate Limit + uses: your-repo/check-rate-limit-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/actions/core-cicd/api-limits-check/action.yml b/.github/actions/core-cicd/api-limits-check/action.yml new file mode 100644 index 000000000000..fbbe8e671f42 --- /dev/null +++ b/.github/actions/core-cicd/api-limits-check/action.yml @@ -0,0 +1,15 @@ +name: 'Check GitHub API Rate Limit' +description: 'Outputs information on GitHub API /rate_limit endpoint' + +inputs: + token: + description: 'GitHub token to authenticate the API request' + required: true + default: ${{ github.token }} + +runs: + using: "composite" + steps: + - run: | + curl -s -H "Authorization: token ${{ inputs.token }}" https://api.github.com/rate_limit + shell: bash diff --git a/.github/workflows/cicd_comp_finalize-phase.yml b/.github/workflows/cicd_comp_finalize-phase.yml index 292519e1583a..2ce0b9b5a24a 100644 --- a/.github/workflows/cicd_comp_finalize-phase.yml +++ b/.github/workflows/cicd_comp_finalize-phase.yml @@ -183,4 +183,12 @@ jobs: if [ "${{ needs.prepare-report-data.outputs.aggregate_status }}" != "SUCCESS" ]; then echo "One or more jobs failed or cancelled!" exit 1 - fi \ No newline at end of file + fi + + # Check can be removed if we have resolved root cause + # We cannot use a local github action for this as it is run before we checkout the repo + # secrets.GITHUB_TOKEN is not available in composite workflows so it needs to be passed in. + - name: Check API Rate Limit + shell: bash + run: | + curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN}}" https://api.github.com/rate_limit || true \ No newline at end of file diff --git a/.github/workflows/cicd_comp_initialize-phase.yml b/.github/workflows/cicd_comp_initialize-phase.yml index 57846f6ca2d0..4a5b0163275f 100644 --- a/.github/workflows/cicd_comp_initialize-phase.yml +++ b/.github/workflows/cicd_comp_initialize-phase.yml @@ -64,6 +64,13 @@ jobs: shell: bash run: | echo "Initializing..." + # Check can be removed if we have resolved root cause + # We cannot use a local github action for this as it is run before we checkout the repo + # secrets.GITHUB_TOKEN is not available in composite workflows so it needs to be passed in. + - name: Check API Rate Limit + shell: bash + run: | + curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/rate_limit || true # This job checks for artifacts from previous builds and determines if they can be reused check-previous-build: diff --git a/.github/workflows/cicd_comp_pr-notifier.yml b/.github/workflows/cicd_comp_pr-notifier.yml index 5188eff9ed69..29c8da8709f9 100644 --- a/.github/workflows/cicd_comp_pr-notifier.yml +++ b/.github/workflows/cicd_comp_pr-notifier.yml @@ -89,3 +89,10 @@ jobs: -d "{ \"channel\":\"${channel}\",\"text\":\"${message}\"}" \ -s \ https://slack.com/api/chat.postMessage + # Check can be removed if we have resolved root cause + # We cannot use a local github action for this as it is run before we checkout the repo + # secrets.GITHUB_TOKEN is not available in composite workflows so it needs to be passed in. + - name: Check API Rate Limit + shell: bash + run: | + curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/rate_limit || true \ No newline at end of file diff --git a/.github/workflows/cicd_post-workflow-reporting.yml b/.github/workflows/cicd_post-workflow-reporting.yml index c8bb5622c599..d8e8c71340af 100644 --- a/.github/workflows/cicd_post-workflow-reporting.yml +++ b/.github/workflows/cicd_post-workflow-reporting.yml @@ -271,4 +271,11 @@ jobs: channel-id: ${{ vars.SLACK_REPORT_CHANNEL }} payload: ${{ steps.prepare-slack-message.outputs.payload }} json: true - slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + # Check can be removed if we have resolved root cause + # We cannot use a local github action for this as it is run before we checkout the repo + # secrets.GITHUB_TOKEN is not available in composite workflows so it needs to be passed in. + - name: Check API Rate Limit + shell: bash + run: | + curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/rate_limit || true \ No newline at end of file diff --git a/e2e/dotcms-e2e-node/frontend/.env b/e2e/dotcms-e2e-node/frontend/.env new file mode 100644 index 000000000000..ad03f2f58dc1 --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/.env @@ -0,0 +1,2 @@ +CI=false +BASE_URL=http://localhost:8080 diff --git a/e2e/dotcms-e2e-node/frontend/.env.ci b/e2e/dotcms-e2e-node/frontend/.env.ci new file mode 100644 index 000000000000..8711f95abe93 --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/.env.ci @@ -0,0 +1 @@ +CI=true diff --git a/e2e/dotcms-e2e-node/frontend/.env.local b/e2e/dotcms-e2e-node/frontend/.env.local new file mode 100644 index 000000000000..f6c5e51966eb --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/.env.local @@ -0,0 +1 @@ +BASE_URL=http://localhost:4200 \ No newline at end of file diff --git a/e2e/dotcms-e2e-node/frontend/.gitignore b/e2e/dotcms-e2e-node/frontend/.gitignore new file mode 100644 index 000000000000..68c5d18f00dc --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/e2e/dotcms-e2e-node/frontend/package.json b/e2e/dotcms-e2e-node/frontend/package.json new file mode 100644 index 000000000000..854de4b4a9cd --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/package.json @@ -0,0 +1,15 @@ +{ + "name": "frontend", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "devDependencies": { + "@playwright/test": "^1.47.0", + "@types/node": "^22.5.4", + "dotenv": "^16.4.5" + }, + "scripts": { + "start-local": "CURRENT_ENV=local yarn playwright test", + "start-ci": "CURRENT_ENV=ci yarn playwright test" + } +} diff --git a/e2e/dotcms-e2e-node/frontend/playwright.config.ts b/e2e/dotcms-e2e-node/frontend/playwright.config.ts new file mode 100644 index 000000000000..6779a7d8d994 --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/playwright.config.ts @@ -0,0 +1,68 @@ +import dotenv from 'dotenv'; +import * as path from "node:path"; +import { defineConfig, devices } from '@playwright/test'; + +const resolveEnvs = () => { + const envFiles = ['.env']; + + if (process.env.CURRENT_ENV === 'local') { + envFiles.push('.env.local'); + } else if (process.env.CURRENT_ENV === 'ci') { + envFiles.push('.env.ci'); + } + + envFiles.forEach((file) => { + dotenv.config({ + path: path.resolve(__dirname, file), + override: true + }); + }); +}; + +resolveEnvs(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + baseURL: process.env.BASE_URL, + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + ], + webServer: { + command: 'nx serve dotcms-ui', + cwd: '../../../core-web', + url: process.env.BASE_URL + '/dotAdmin', + reuseExistingServer: !!process.env.CI, + } +}); diff --git a/e2e/dotcms-e2e-node/frontend/tests/welcome.spec.ts b/e2e/dotcms-e2e-node/frontend/tests/welcome.spec.ts new file mode 100644 index 000000000000..a29905b6737d --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/tests/welcome.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('/dotAdmin'); + + // Expect h3 to contain a substring. + expect(await page.locator('h3').textContent()).toContain('Welcome!'); +}); diff --git a/e2e/dotcms-e2e-node/frontend/yarn.lock b/e2e/dotcms-e2e-node/frontend/yarn.lock new file mode 100644 index 000000000000..2472d57e4e3b --- /dev/null +++ b/e2e/dotcms-e2e-node/frontend/yarn.lock @@ -0,0 +1,46 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@playwright/test@^1.47.0": + version "1.47.0" + resolved "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz#69fc55b10754147cc20021afbfa05747d4961bf0" + integrity sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA== + dependencies: + playwright "1.47.0" + +"@types/node@^22.5.4": + version "22.5.4" + resolved "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz#83f7d1f65bc2ed223bdbf57c7884f1d5a4fa84e8" + integrity sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg== + dependencies: + undici-types "~6.19.2" + +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +playwright-core@1.47.0: + version "1.47.0" + resolved "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz#b54ec060fd83e5c2e46b63986b5ebb5e96ace427" + integrity sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg== + +playwright@1.47.0: + version "1.47.0" + resolved "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz#fb9b028883fad11362f9ff63ce7ba44bda0bf626" + integrity sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww== + dependencies: + playwright-core "1.47.0" + optionalDependencies: + fsevents "2.3.2" + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== diff --git a/e2e/dotcms-e2e-node/pom.xml b/e2e/dotcms-e2e-node/pom.xml new file mode 100644 index 000000000000..eb6903f1bdea --- /dev/null +++ b/e2e/dotcms-e2e-node/pom.xml @@ -0,0 +1,182 @@ + + + 4.0.0 + + + com.dotcms + dotcms-nodejs-parent + ${revision}${sha1}${changelist} + ../../nodejs-parent/pom.xml + + + jar + dotcms-e2e-node + + + UTF-8 + false + install --frozen-lockfile + global add playwright + true + local + run start-${e2e.test.env} + 8080 + http://localhost:${tomcat.port} + ${ext.wiremock.api.key} + ${ext.docker.image.wiremock} + ./src/test/resources + /home/wiremock + + + + + + com.github.eirslett + frontend-maven-plugin + + + install + + yarn + + + generate-resources + + ${skip.npm.install} + ${yarn.install.cmd} + + + + install-playwrigth + + yarn + + + generate-resources + + ${skip.npm.install} + ${playwright.install.cmd} + + + + run node script + + + yarn + + integration-test + + ./frontend + ${e2e.test.skip} + ${e2e.test.cmd} + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + ${e2e.test.skip} + + + + integration-test + none + + + verify + + verify + + + + + + + + io.fabric8 + docker-maven-plugin + + true + true + ${e2e.test.skip} + + + ${docker.image.wiremock} + + + wiremock.port:8080 + + + + ${docker.wm.volume}:${docker.wm.volume.internal} + + + + [WireMock] + green + + + + + + + -XX:+PrintFlagsFinal + 15 + FORCE + false + false + 600 + obfuscate_me + true + http://localhost:8080 + true + true + http://wm:8080/c + http://wm:8080/i + http://wm:8080/e + http://wm:8080/m + true + + + wiremock:wm + + + + + + + + cleanup-at-start + + stop + volume-remove + + pre-integration-test + + + start + + start + + pre-integration-test + + + stop + + stop + + verify + + + + + + + + + + \ No newline at end of file diff --git a/e2e/pom.xml b/e2e/pom.xml index 77bd5cd7315c..858fd6756a11 100644 --- a/e2e/pom.xml +++ b/e2e/pom.xml @@ -20,7 +20,7 @@ dotcms-e2e-java - + dotcms-e2e-node diff --git a/pom.xml b/pom.xml index baf25e35824f..77fd5695e41e 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ dotcms-postman reports e2e/dotcms-e2e-java - + e2e/dotcms-e2e-node