diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 9cb1cdc9f..000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -ARG VARIANT=12 -FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:${VARIANT} \ No newline at end of file diff --git a/.devcontainer/base.Dockerfile b/.devcontainer/base.Dockerfile deleted file mode 100644 index 16313f77e..000000000 --- a/.devcontainer/base.Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -ARG VARIANT=12-buster -FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:dev-${VARIANT} - -# Install tslint, typescript. eslint is installed by javascript image -ARG NODE_MODULES="tslint-to-eslint-config typescript" -RUN su node -c "umask 0002 && npm install -g ${NODE_MODULES}" \ - && npm cache clean --force > /dev/null 2>&1 \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 7717c0935..000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,17 +0,0 @@ -// https://github.com/microsoft/vscode-dev-containers/tree/master/containers/typescript-node -{ - "name": "Node.js & TypeScript", - "build": { - "dockerfile": "Dockerfile", - "args": { - "VARIANT": "12" - } - }, - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - }, - "extensions": [ - "dbaeumer.vscode-eslint" - ], - "remoteUser": "node" -} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index adf484fbc..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "plugins": ["jest", "@typescript-eslint", "github"], - "extends": ["plugin:github/recommended"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 9, - "sourceType": "module", - "project": "./tsconfig.lint.json" - }, - "globals": { - "fetch": true - }, - "rules": { - "eslint-comments/no-use": "off", - "import/no-namespace": "off", - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": "error", - "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], - "@typescript-eslint/no-require-imports": "error", - "@typescript-eslint/array-type": "error", - "@typescript-eslint/await-thenable": "error", - "@typescript-eslint/ban-ts-comment": "error", - "camelcase": "off", - "@typescript-eslint/naming-convention": [ - "error", - { - "selector": "default", - "format": ["camelCase", "UPPER_CASE", "StrictPascalCase"] - } - ], - "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}], - "@typescript-eslint/func-call-spacing": ["error", "never"], - "@typescript-eslint/no-array-constructor": "error", - "@typescript-eslint/no-empty-interface": "error", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-extraneous-class": "error", - "@typescript-eslint/no-for-in-array": "error", - "@typescript-eslint/no-inferrable-types": "error", - "@typescript-eslint/no-misused-new": "error", - "@typescript-eslint/no-namespace": "error", - "@typescript-eslint/no-non-null-assertion": "warn", - "@typescript-eslint/no-unnecessary-qualifier": "error", - "@typescript-eslint/no-unnecessary-type-assertion": "error", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "error", - "@typescript-eslint/prefer-for-of": "warn", - "@typescript-eslint/prefer-function-type": "warn", - "@typescript-eslint/prefer-includes": "error", - "@typescript-eslint/prefer-string-starts-ends-with": "error", - "@typescript-eslint/promise-function-async": "error", - "@typescript-eslint/require-array-sort-compare": "error", - "@typescript-eslint/restrict-plus-operands": "error", - "semi": "off", - "@typescript-eslint/semi": ["error", "never"], - "@typescript-eslint/type-annotation-spacing": "error", - "@typescript-eslint/unbound-method": "error", - "no-console": "off", - "no-shadow": "off", // replaced by ts-eslint rule below - "@typescript-eslint/no-shadow": "error" - }, - "env": { - "node": true, - "es6": true, - "jest/globals": true - } -} diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 077f6c801..a0ccaeeec 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1 @@ -# These are supported funding model platforms - github: [JamesIves] diff --git a/.github/ISSUE_TEMPLATE/BUG.yml b/.github/ISSUE_TEMPLATE/BUG.yml new file mode 100644 index 000000000..7e7d010c6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG.yml @@ -0,0 +1,50 @@ +name: Bug Report ๐Ÿ +description: Create a bug report to help us improve the action. +title: 'bug: ๐Ÿ ' +labels: ['bug ๐Ÿ', 'triage โš ๏ธ'] +assignees: + - JamesIves +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to report a bug. Please fill out the sections below to help us reproduce the issue and improve the action. If you're unsure about something, feel free to skip it or write N/A in the field. + + [Please check the Q&A before posting an issue here](https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AQ%26A). + - type: textarea + id: bug-description + attributes: + label: Describe the bug + description: 'Please provide a clear and concise description of what the bug is and what you expected to happen.' + validations: + required: true + - type: textarea + id: reproduction-steps + attributes: + label: Reproduction Steps + description: 'Steps to reproduce the behavior. Please provide a minimal example if possible.' + validations: + required: true + - type: textarea + id: logs + attributes: + label: Logs + description: "Please provide your deployment logs if applicable. If the error message isn't revealing the problem please set ACTIONS_STEP_DEBUG to true in your repository's secrets menu and run the workflow again." + render: shell + validations: + required: false + - type: textarea + id: workflow + attributes: + label: Workflow + description: 'Please provide a link or snippet of your workflow yml file.' + render: yml + validations: + required: true + - type: textarea + id: additional-comments + attributes: + label: Additional Comments + description: 'Add any other context about the problem here that does not fit elsewhere.' + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md deleted file mode 100644 index c5cbb3c77..000000000 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: Bug Report -about: Create a bug report to help us improve the action. -labels: - - bug - ---- - - - -## Describe the bug - - -## Reproduction Steps - - -## Logs - - -## Additional Comments - diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 308bb38a3..963d5cdef 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,8 +3,7 @@ contact_links: - name: Feature Request and Ideas url: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AIdeas about: If you have an idea or would like to make a feature request please open a discussion thread. - + - name: Support and Questions url: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AQ%26A about: Need help or just have a general question? Please open a discussion thread. - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8e4d2a435..78b8880c2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,11 @@ ## Description + ## Testing Instructions + ## Additional Notes + diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3f8f5b239..074d88244 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,40 @@ version: 2 updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily - time: "10:00" - open-pull-requests-limit: 10 \ No newline at end of file + - package-ecosystem: npm + directory: '/' + schedule: + interval: daily + time: '10:00' + open-pull-requests-limit: 10 + groups: + eslint: + patterns: + - 'eslint-*' + - '@typescript-eslint/*' + - '@eslint/*' + + typescript: + patterns: + - 'typescript-*' + - '@typescript/*' + + jest: + patterns: + - 'jest-*' + - '@jest/*' + + actions: + patterns: + - 'actions/*' + - '@actions/*' + + misc: + patterns: + - '*' + + - package-ecosystem: github-actions + directory: '/' + schedule: + interval: daily + time: '10:00' + open-pull-requests-limit: 10 diff --git a/.github/docs/icon.png b/.github/docs/icon.png new file mode 100644 index 000000000..2edaa4e2b Binary files /dev/null and b/.github/docs/icon.png differ diff --git a/assets/screenshot.png b/.github/docs/screenshot.png similarity index 100% rename from assets/screenshot.png rename to .github/docs/screenshot.png diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..7c8c562a6 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,37 @@ +changelog: + categories: + - title: Breaking Changes ๐Ÿ’ฅ + labels: + - breaking ๐Ÿ’ฅ + - breaking + - title: New Features ๐ŸŽ‰ + labels: + - feature โœจ + - feat + - title: Bug Fixes ๐Ÿ + labels: + - fix ๐Ÿ + - bug ๐Ÿ + - fix + - title: Performance โšก + labels: + - performance โšก + - perf + - title: Build ๐Ÿ”ง + labels: + - build ๐Ÿ”ง + - build + - title: Testing ๐Ÿงช + labels: + - test ๐Ÿงช + - test + - title: Documentation ๐Ÿ“– + labels: + - documentation ๐Ÿ“– + - docs + - title: Dependencies ๐Ÿค– + labels: + - dependencies + - title: Other Changes + labels: + - '*' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 491270a13..b76fe5f08 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: unit-tests +name: Unit Tests ๐Ÿงช on: pull_request: branches: @@ -6,7 +6,7 @@ on: - 'releases/v*' push: branches: - - 'dev*' + - '*' tags-ignore: - '*.*' jobs: @@ -14,11 +14,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v4.4.0 with: - node-version: 'v12.18.4' + node-version-file: '.node-version' registry-url: 'https://registry.npmjs.org/' - name: Install Yarn @@ -26,12 +26,13 @@ jobs: - name: Install and Test run: | - yarn install - yarn lint + yarn install --frozen-lockfile + yarn lint:check + yarn lint:format:check yarn test - name: Uploade CodeCov Report - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v5.4.3 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -39,11 +40,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v4.4.0 with: - node-version: 'v12.18.4' + node-version-file: '.node-version' registry-url: 'https://registry.npmjs.org/' - name: Install Yarn @@ -51,16 +52,16 @@ jobs: - name: Build lib run: | - yarn install + yarn install --frozen-lockfile yarn build - name: Rebuild production node_modules run: | - yarn install --production + yarn install --production --frozen-lockfile ls node_modules - name: artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.6.2 with: name: dist path: | @@ -72,22 +73,22 @@ jobs: needs: build strategy: matrix: - branch: ["gh-pages", "no-pages"] - commit: ["singleCommit", "add commits"] + branch: ['gh-pages', 'no-pages'] + commit: ['singleCommit', 'add commits'] max-parallel: 1 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v4.4.0 with: - node-version: 'v12.18.4' + node-version-file: '.node-version' registry-url: 'https://registry.npmjs.org/' - name: Download artifact - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4.3.0 with: name: dist @@ -120,7 +121,7 @@ jobs: if: ${{ matrix.branch == 'gh-pages' }} with: folder: integration - branch: ${{ matrix.branch }} + branch: ${{ matrix.branch }} single-commit: ${{ matrix.commit == 'singleCommit' }} dry-run: true diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index c1454fed5..000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: "CodeQL" -on: - push: - branches: - - dev - - 'dev-v*' - - 'releases/v*' - pull_request: - branches: - - dev - - 'dev-v*' - schedule: - - cron: '0 9 * * 4' - -jobs: - analyse: - name: Analyse - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..bb837cf0a --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,100 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '26 1 * * 3' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # โ„น๏ธ Command-line programs to run using the OS shell. + # ๐Ÿ“š See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c75b88867..e8527e705 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Deploy Code to Release Branch +name: Deploy Code to Release Branch ๐Ÿš€ on: workflow_dispatch: @@ -8,14 +8,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 # Workflow dispatch event that pushes the current version to the release branch. # From here the secondary production deployment workflow will trigger to build the dependencies. - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@4.0.0 + uses: JamesIves/github-pages-deploy-action@v4 with: branch: releases/v4 folder: . clean: false - single-commit: true \ No newline at end of file + single-commit: true diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index c16f51f7e..a16eae808 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -1,90 +1,82 @@ -name: integration-tests +name: Integration Tests ๐Ÿงช on: + workflow_call: workflow_dispatch: - inputs: - branch: - description: 'Specifies the branch which the integration tests should run on.' - required: true - default: 'releases/v4' schedule: - cron: 30 15 * * 0-6 - push: - tags-ignore: - - '*.*' - branches: - - releases/v4 jobs: - # Deploys cross repo with an access token. integration-cross-repo-push: + container: node:16.13 runs-on: ubuntu-latest steps: + - name: Install Container Dependencies ๐Ÿ“š + run: | + apt-get update && apt-get install -y rsync + - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: git-config-name: Montezuma git-config-email: montezuma@jamesiv.es repository-name: MontezumaIves/lab token: ${{ secrets.ACCESS_TOKEN }} - branch: gh-pages + commit-message: 'Test commit' folder: integration single-commit: true clean: true - silent: true - - # Deploys using checkout@v1 with an ACCESS_TOKEN. + silent: false + integration-checkout-v1: needs: integration-cross-repo-push runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v1 + uses: actions/checkout@v4.2.2 - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: token: ${{ secrets.ACCESS_TOKEN }} - branch: gh-pages folder: integration target-folder: cat/montezuma git-config-name: Montezuma git-config-email: montezuma@jamesiv.es - silent: true + silent: false - name: Cleanup Generated Branch - uses: dawidd6/action-delete-branch@v2.0.1 + uses: dawidd6/action-delete-branch@v3.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} branches: gh-pages - # Deploys using checkout@v2 with a GITHUB_TOKEN. integration-checkout-v2: needs: integration-checkout-v1 runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: - branch: gh-pages folder: integration target-folder: cat/montezuma2 - silent: true + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es - name: Cleanup Generated Branch - uses: dawidd6/action-delete-branch@v2.0.1 + uses: dawidd6/action-delete-branch@v3.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} branches: gh-pages - # Deploys using a container that requires you to install rsync. integration-container: needs: integration-checkout-v2 @@ -95,7 +87,7 @@ jobs: LANG: C.UTF-8 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false @@ -104,15 +96,16 @@ jobs: apt-get update && apt-get install -y rsync - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: - branch: gh-pages folder: integration target-folder: cat/montezuma2 - silent: true + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es - name: Cleanup Generated Branch - uses: dawidd6/action-delete-branch@v2.0.1 + uses: dawidd6/action-delete-branch@v3.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} branches: gh-pages @@ -123,21 +116,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: ssh-key: ${{ secrets.DEPLOY_KEY }} - branch: gh-pages folder: integration target-folder: cat/montezuma3 - silent: true + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es - name: Cleanup Generated Branch - uses: dawidd6/action-delete-branch@v2.0.1 + uses: dawidd6/action-delete-branch@v3.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} branches: gh-pages @@ -148,99 +142,220 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false - name: Install SSH Client - uses: webfactory/ssh-agent@v0.4.1 + uses: webfactory/ssh-agent@v0.9.1 with: ssh-private-key: ${{ secrets.DEPLOY_KEY }} - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: ssh-key: true - branch: gh-pages folder: integration target-folder: cat/montezuma4 - silent: true + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es - name: Cleanup Generated Branch - uses: dawidd6/action-delete-branch@v2.0.1 + uses: dawidd6/action-delete-branch@v3.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} - branches: gh-pages - # Deploys using a custom env. + # Deploys using a custom env. (Includes subsequent commit) integration-env: needs: integration-ssh-third-party-client runs-on: ubuntu-latest steps: - - uses: actions/setup-node@v1.4.4 - with: - node-version: '10.x' - - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false + - uses: actions/setup-node@v4.4.0 + with: + node-version-file: '.node-version' + - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: ssh-key: ${{ secrets.DEPLOY_KEY }} - branch: gh-pages folder: integration target-folder: cat/montezuma4 - silent: true + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es + + - name: Build and Deploy + uses: JamesIves/github-pages-deploy-action@v4 + with: + ssh-key: ${{ secrets.DEPLOY_KEY }} + folder: integration + target-folder: cat/subsequent + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es - name: Cleanup Generated Branch - uses: dawidd6/action-delete-branch@v2.0.1 + uses: dawidd6/action-delete-branch@v3.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} branches: gh-pages # Deploys using the CLEAN option. integration-clean: - needs: [integration-checkout-v1, integration-checkout-v2, integration-container, integration-ssh, integration-ssh-third-party-client, integration-env] + needs: + [ + integration-checkout-v1, + integration-checkout-v2, + integration-container, + integration-ssh, + integration-ssh-third-party-client, + integration-env + ] runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 with: token: ${{ secrets.ACCESS_TOKEN }} - branch: gh-pages folder: integration clean: true - silent: true + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es - # Deploys to a branch that doesn't exist with SINGLE_COMMIT. + # Deploys to a branch that doesn't exist with SINGLE_COMMIT. (Includes subsequent commit) integration-branch-creation: needs: integration-clean runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 with: persist-credentials: false - name: Build and Deploy - uses: JamesIves/github-pages-deploy-action@releases/v4 + uses: JamesIves/github-pages-deploy-action@v4 + with: + token: ${{ secrets.ACCESS_TOKEN }} + branch: integration-test-delete-prod + folder: integration + single-commit: true + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es + + - name: Build and Deploy + uses: JamesIves/github-pages-deploy-action@v4 with: token: ${{ secrets.ACCESS_TOKEN }} branch: integration-test-delete-prod folder: integration single-commit: true - silent: true + target-folder: jives + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es - name: Cleanup Generated Branch - uses: dawidd6/action-delete-branch@v2.0.1 + uses: dawidd6/action-delete-branch@v3.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} branches: integration-test-delete-prod + + # Creates two competing deployments, one of which should rebase over the other. + # First conflicting deployment + integration-rebase-conflicts-1: + needs: integration-branch-creation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.2.2 + + - name: Create random file + run: echo $RANDOM > integration/1 + + - name: Build and Deploy + uses: JamesIves/github-pages-deploy-action@v4 + with: + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es + repository-name: MontezumaIves/lab + token: ${{ secrets.ACCESS_TOKEN }} + branch: gh-pages-rebase-conflict + folder: integration + force: false + + # Second conflicting deployment + integration-rebase-conflicts-2: + needs: integration-rebase-conflicts-1 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.2.2 + + - name: Create random file + run: echo $RANDOM > integration/2 + + - name: Build and Deploy + uses: JamesIves/github-pages-deploy-action@v4 + with: + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es + repository-name: MontezumaIves/lab + token: ${{ secrets.ACCESS_TOKEN }} + branch: gh-pages-rebase-conflict + folder: integration + force: false + + # Clean up conflicting deployments + integration-rebase-conflicts-cleanup: + needs: [integration-rebase-conflicts-1, integration-rebase-conflicts-2] + runs-on: ubuntu-latest + steps: + - name: Cleanup Generated Branch + uses: dawidd6/action-delete-branch@v3.1.0 + with: + github_token: ${{ secrets.ACCESS_TOKEN }} + owner: MontezumaIves + repository: lab + branches: gh-pages + + integration-root-folder: + needs: integration-rebase-conflicts-cleanup + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.2.2 + with: + persist-credentials: false + + - name: Echo + working-directory: integration + run: | + echo "Here" + + - name: Build and Deploy + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: . + target-folder: cat/montezuma5 + silent: false + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es + + - name: Cleanup Generated Branch + uses: dawidd6/action-delete-branch@v3.1.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branches: gh-pages diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 000000000..e3980ccd9 --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,95 @@ +name: Label Pull Requests ๐Ÿท๏ธ + +on: + pull_request: + types: [opened, reopened, labeled, unlabeled, synchronize] + +permissions: + pull-requests: write + contents: read + +jobs: + assign-labels: + runs-on: ubuntu-latest + name: Assign labels in pull request ๐Ÿท๏ธ + if: github.event.pull_request.merged == false + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4.2.2 + + - name: Assign Labels ๐Ÿท๏ธ + id: action-assign-labels + uses: mauroalderete/action-assign-labels@v1.5.1 + with: + pull-request-number: ${{ github.event.pull_request.number }} + github-token: ${{ secrets.GITHUB_TOKEN }} + conventional-commits: | + conventional-commits: + - type: 'fix' + nouns: ['FIX', 'Fix', 'fix', 'FIXED', 'Fixed', 'fixed'] + labels: ['bug ๐Ÿ', 'fix ๐Ÿ'] + - type: 'feature' + nouns: ['FEATURE', 'Feature', 'feature', 'FEAT', 'Feat', 'feat'] + labels: ['feature โœจ'] + - type: 'breaking_change' + nouns: ['BREAKING CHANGE', 'BREAKING', 'MAJOR'] + labels: ['breaking ๐Ÿ’ฅ'] + - type: 'documentation' + nouns: ['doc', 'docu', 'docs', 'document', 'documentation'] + labels: ['documentation ๐Ÿ“–'] + - type: 'build' + nouns: ['build', 'rebuild'] + labels: ['build ๐Ÿ”ง'] + - type: 'chore' + nouns: ['chore', 'tidy', 'cleanup'] + labels: ['chore ๐Ÿงน'] + - type: 'dependencies' + nouns: ['dependency', 'dependencies', 'package', 'packages', 'bump', 'dependabot'] + labels: ['dependencies ๐Ÿค–'] + - type: 'duplicate' + nouns: ['duplicate', 'dupe', 'copy'] + labels: ['duplicate 2๏ธโƒฃ'] + - type: 'good_first_issue' + nouns: ['good first issue', 'beginner', 'newcomer', 'first-timer'] + labels: ['good first issue ๐Ÿฉ'] + - type: 'help_wanted' + nouns: ['help wanted', 'need help', 'assistance required'] + labels: ['help wanted โ•'] + - type: 'proposal' + nouns: ['proposal', 'suggest', 'suggestion'] + labels: ['proposal ๐Ÿ”ฎ'] + - type: 'question' + nouns: ['question', 'inquiry', 'query'] + labels: ['question โ“'] + - type: 'test' + nouns: ['test', 'testing', 'tests'] + labels: ['test ๐Ÿงช'] + - type: 'triage' + nouns: ['triage', 'sort', 'prioritize'] + labels: ['triage โš ๏ธ'] + - type: 'wontfix' + nouns: ['wontfix', 'will not fix', 'not fixing'] + labels: ['wontfix ๐Ÿ”จ'] + - type: 'style' + nouns: ['style', 'formatting', 'format'] + labels: ['style ๐ŸŽ€'] + - type: 'security' + nouns: ['security', 'secure', 'safety'] + labels: ['security ๐Ÿ”’'] + - type: 'performance' + nouns: ['performance', 'speed', 'optimization'] + labels: ['performance ๐Ÿš€'] + - type: 'refactor' + nouns: ['refactor', 'refactoring', 'rework'] + labels: ['refactor ๐Ÿ› '] + - type: 'release' + nouns: ['release', 'deploy', 'deployment'] + labels: ['release ๐Ÿš€'] + - type: 'ci' + nouns: ['ci', 'continuous integration', 'CI/CD'] + labels: ['ci ๐Ÿš€'] + - type: 'hacktoberfest' + nouns: ['hacktoberfest', 'october', 'open source'] + labels: ['hacktoberfest ๐ŸŽƒ'] + maintain-labels-not-matched: false + apply-changes: true diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index e9e1f66c4..1ad9400dc 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -1,4 +1,4 @@ -name: Deploy Production Dependencies and Code +name: Deploy Production Dependencies and Code ๐Ÿš€ on: workflow_dispatch: push: @@ -13,18 +13,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.2.2 - - uses: actions/setup-node@v1.4.4 + - uses: actions/setup-node@v4.4.0 with: - node-version: 'v12.18.4' + node-version-file: '.node-version' registry-url: 'https://registry.npmjs.org/' - name: Install Yarn run: npm install -g yarn - name: Clobber lib - run: rm -rf lib + run: rm -rf lib - name: Set up .gitignore run: | @@ -32,12 +32,12 @@ jobs: - name: Build run: | - yarn install + yarn install --frozen-lockfile yarn build - name: Install Production node_modules run: | - yarn install --production + yarn install --production --frozen-lockfile - name: Commit and Push # Keep the run green if the commit fails for the lack of changes diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 3871332dc..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: publish-to-npm -on: - workflow_dispatch: - inputs: - version: - description: 'The updated registry version number.' - required: true - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - ref: dev - - # Setup .npmrc file to publish to npm - - uses: actions/setup-node@v1.4.4 - with: - node-version: '10.15.1' - registry-url: 'https://registry.npmjs.org/' - scope: '@jamesives' - - - name: Configure Git - run: | - git config user.email "iam@jamesiv.es" - git config user.name "James Ives" - - - name: Install Yarn - run: npm install -g yarn - - - run: yarn install --frozen-lockfile - - run: yarn build - - run: npm version ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }} ๐Ÿ“ฃ" - - run: git push - - # Publish to npm - - run: npm publish --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - # Setup .npmrc file to publish to GitHub Packages - - uses: actions/setup-node@v1.4.4 - with: - node-version: 12 - registry-url: 'https://npm.pkg.github.com/' - scope: '@jamesives' - - - name: Authenticate with the GitHub Package Registry - run: - echo "//npm.pkg.github.com:_authToken=${{ secrets.GITHUB_TOKEN }}" > - ~/.npmrc - - # Publish to GitHub Packages - - run: npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml new file mode 100644 index 000000000..4e106f538 --- /dev/null +++ b/.github/workflows/sponsors.yml @@ -0,0 +1,41 @@ +name: Publish Sponsors to README ๐Ÿ“ฃ +on: + workflow_dispatch: + schedule: + - cron: 30 15 * * 0-6 + +jobs: + generate-sponsors: + runs-on: ubuntu-latest + steps: + - name: Checkout ๐Ÿ›Ž๏ธ + uses: actions/checkout@v4.2.2 + + - name: Generate Sponsors ๐Ÿ’– + uses: JamesIves/github-sponsors-readme-action@v1 + with: + token: ${{ secrets.PAT }} + file: 'README.md' + template: '{{{ login }}}  ' + maximum: 2499 + active-only: false + include-private: true + + - name: Generate Sponsors ๐Ÿ’– + uses: JamesIves/github-sponsors-readme-action@v1 + with: + token: ${{ secrets.PAT }} + file: 'README.md' + minimum: 2500 + template: '{{{ login }}}  ' + marker: 'premium' + active-only: false + include-private: true + + - name: Deploy to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + branch: dev + folder: '.' + git-config-name: Montezuma + git-config-email: montezuma@jamesiv.es diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 000000000..f2c9e97c9 --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,43 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload entire repository + path: '.' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml new file mode 100644 index 000000000..7d8124996 --- /dev/null +++ b/.github/workflows/version.yml @@ -0,0 +1,75 @@ +name: Update Major Version Tag and Publish to Registry ๐Ÿ“ฆ + +on: + push: + tags: + - 'v*' + +jobs: + update-majorver: + name: Update Major Version Tag + runs-on: ubuntu-latest + steps: + - uses: nowactions/update-majorver@v1.1.2 + + call-integration-workflow: + name: Verify Major Tag ๐Ÿš€ + needs: update-majorver + secrets: inherit + uses: ./.github/workflows/integration.yml + + update-registries: + needs: call-integration-workflow + name: Publish to Registries ๐Ÿ“ฆ + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.2.2 + with: + ref: dev + + # Setup .npmrc file to publish to npm + - uses: actions/setup-node@v4.4.0 + with: + node-version-file: '.node-version' + registry-url: 'https://registry.npmjs.org/' + scope: '@jamesives' + + - name: Configure Git + run: | + git config user.email "iam@jamesiv.es" + git config user.name "James Ives" + + - name: Install Yarn + run: npm install -g yarn + + - run: yarn install --frozen-lockfile + - run: yarn build + - run: git stash + - name: Set version to match the tag + run: | + VERSION=${GITHUB_REF#refs/tags/v} + npm version $VERSION -m "Release $VERSION ๐Ÿ“ฃ" + env: + GITHUB_REF: ${{ github.ref }} + - run: git push + + # Publish to npm + - run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + # Setup .npmrc file to publish to GitHub Packages + - uses: actions/setup-node@v4.4.0 + with: + node-version-file: '.node-version' + registry-url: 'https://npm.pkg.github.com/' + scope: '@jamesives' + + - name: Authenticate with the GitHub Package Registry + run: | + echo "//npm.pkg.github.com:_authToken=${{ secrets.GITHUB_TOKEN }}" > ~/.npmrc + + # Publish to GitHub Packages + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index b38e794d0..a2b64ff10 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,7 @@ yarn-error.log coverage # Yarn Integrity file -.yarn-integrity \ No newline at end of file +.yarn-integrity + +# Dot Env +.env \ No newline at end of file diff --git a/.node-version b/.node-version new file mode 100644 index 000000000..05f04686d --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +v22.11.0 \ No newline at end of file diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 82f87fa0a..000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v12.18.4 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..084c93c9f --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +# Ignore artifacts: +build +coverage +lib \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json index 386485a76..c34bafcb8 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -6,6 +6,5 @@ "singleQuote": true, "trailingComma": "none", "bracketSpacing": false, - "arrowParens": "avoid", - "parser": "typescript" -} \ No newline at end of file + "arrowParens": "avoid" +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index ad25d444c..c1b7046a2 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation. Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting ## Our Responsibilities diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ec715534..e546499c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,21 +1,21 @@ # Contributing โœ๏ธ -When contributing to this repository, please first discuss the change you wish to make via issue, +When contributing to this repository, please first discuss the change you wish to make via issue, [email, or any other method with the owners of this repository](https://jamesiv.es) before making a change. If you are planning to work on an issue that already exists please let us know before writing any code incase it's already in flight! -## Before Making a Pull Request ๐ŸŽ’ +## Before Making a Pull Request ๐ŸŽ’ 1. Ensure that you've tested your feature/change yourself. As the primary focus of this project is deployment, providing a link to a deployed repository using your branch is preferred. You can reference the forked action using your GitHub username, for example `yourname/github-pages-deplpy-action@dev`. 2. Ensure your change passes all of the integration tests. -3. Make sure you update the README if you've made a change that requires documentation. +3. Make sure you update the README if you've made a change that requires documentation. 4. When making a pull request, highlight any areas that may cause a breaking change so the maintainer can update the version number accordingly on the GitHub marketplace and package registries. -5. Make sure you've formatted and linted your code. You can do this by running `yarn format` and `yarn lint`. +5. Make sure you've linted and formatted your code. You can do this by running `yarn lint` and `yarn lint:format`. 6. Fix or add any tests where applicable. You can run `yarn test` to run the suite. As this action is small in scope it's important that a high level of test coverage is maintained. All tests are written using [Jest](https://jestjs.io/). 7. As this package is written in [TypeScript](https://www.typescriptlang.org/) please ensure all typing is accurate and the action compiles correctly by running `yarn build`. ## Deploying ๐Ÿšš -In order to deploy and test your own fork of this action, you must commit the `node_modules` dependencies. Be sure to run `nvm use` before installing any dependencies. You can learn more about nvm [here](https://github.com/nvm-sh/nvm/blob/master/README.md). +In order to deploy and test your own fork of this action, you must commit the `node_modules` dependencies. Be sure to switch to the Node version listed in the [.node-version](./.node-version) file first. To do this you can follow the instructions below: @@ -32,7 +32,7 @@ Comment out the following in distribution branches: # lib/ ``` -Build the project: +Build the project: ``` yarn build @@ -49,6 +49,6 @@ The `node_modules` and `lib` folders should _not_ be included when making a pull ## Resources ๐Ÿ’ก -* [TypeScript](https://www.typescriptlang.org/) -* [Jest](https://jestjs.io/) -* [GitHub Actions Documentation](https://help.github.com/en/actions) +- [TypeScript](https://www.typescriptlang.org/) +- [Jest](https://jestjs.io/) +- [GitHub Actions Documentation](https://help.github.com/en/actions) diff --git a/LICENSE b/LICENSE index 4fef0fdd6..9da7e7bac 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 James Ives +Copyright (c) 2025-2004 Unity-Engineering-software-engineering-Billal Mesloub Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6ee4c0314..5c8bc8942 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- + GitHub Pages Deploy Action Logo

@@ -9,63 +9,58 @@

- - Unit test status badge - - - - Integration test status badge - - - - Code coverage status badge - - - - Release version badge - - - - Github marketplace badge - + Automatically deploy your project to GitHub Pages with GitHub Actions. This action can be configured to push your production-ready code into any branch you'd like, including gh-pages and docs. It can also handle cross repository deployments and works with GitHub Enterprise too. +

+ +

+

- This GitHub Action will automatically deploy your project to GitHub Pages. It can be configured to push your production-ready code into any branch you'd like, including gh-pages and docs. It can also handle cross repository deployments and works with GitHub Enterprise too. +Maintenance of this project is made possible by all the contributors and sponsors. If you'd like to sponsor this project and have your avatar or company logo appear below click here. ๐Ÿ’–

- +github  annegentle  tonjohn     +

+ +

+Chooksta69  MattWillFlood  jonathan-milan-pollock  raoulvdberge  robjtede  hadley  kevinchalet  Yousazoe  planetoftheweb  melton1968  szepeviktor  sckott  provinzkraut  electrovir  Griefed  MontezumaIves  wylie  pylapp      

## Getting Started :airplane: -You can include the action in your workflow to trigger on any event that [GitHub actions supports](https://help.github.com/en/articles/events-that-trigger-workflows). If the remote branch that you wish to deploy to doesn't already exist the action will create it for you. Your workflow will also need to include the `actions/checkout` step before this workflow runs in order for the deployment to work. +You can include the action in your workflow to trigger on any event that [GitHub actions supports](https://help.github.com/en/articles/events-that-trigger-workflows). If the remote branch that you wish to deploy to doesn't already exist the action will create it for you. Your workflow will also need to include the `actions/checkout` step before this workflow runs in order for the deployment to work. If you intend to make multiple deployments in quick succession [you may need to leverage the concurrency parameter in your workflow](https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#concurrency) to prevent overlaps. You can view an example of this below. ```yml name: Build and Deploy on: [push] +permissions: + contents: write jobs: build-and-deploy: + concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession. runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v2.3.1 + uses: actions/checkout@v4 - name: Install and Build ๐Ÿ”ง # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. run: | - npm install + npm ci npm run build - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@4.1.1 + uses: JamesIves/github-pages-deploy-action@v4 with: - branch: gh-pages # The branch the action should deploy to. folder: build # The folder the action should deploy. ``` +> [!NOTE] +> You must configure your repository to deploy from the branch you push to. To do this, go to your repository settings, click on `Pages`, and choose `Deploy from a Branch` from the `Source` dropdown. From there select the branch you supplied to the action. In most cases this will be `gh-pages` as that's the default. + If you'd like to make it so the workflow only triggers on push events to specific branches then you can modify the `on` section. ```yml @@ -75,43 +70,14 @@ on: - main ``` -It's recommended that you use [Dependabot](https://dependabot.com/github-actions/) to keep your workflow up-to-date. You can find the latest tagged version on the [GitHub Marketplace](https://github.com/marketplace/actions/deploy-to-github-pages) or on the [releases page](https://github.com/JamesIves/github-pages-deploy-action/releases). - -#### Install as a Node Module ๐Ÿ“ฆ - -If you'd like to use the functionality provided by this action in your own action you can install it using [yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/get-npm) by running the following commands. It's available on both the [npm](https://www.npmjs.com/package/@jamesives/github-pages-deploy-action) and [GitHub registry](https://github.com/JamesIves/github-pages-deploy-action/packages/229985). - -``` -yarn add @jamesives/github-pages-deploy-action -``` - -``` -npm install @jamesives/github-pages-deploy-action -``` +> [!WARNING] +> If you do not supply the action with an access token or an SSH key, you must access your repositories settings and provide `Read and Write Permissions` to the provided `GITHUB_TOKEN`, otherwise you'll potentially run into permission issues. Alternatively you can set the following in your workflow file to grant the action the permissions it needs. -It can then be imported into your project like so. - -```javascript -import run from "github-pages-deploy-action"; -``` - -Calling the functions directly will require you to pass in an object containing the variables found in the configuration section, you'll also need to provide a `workspace` with a path to your project. - -```javascript -import run from "github-pages-deploy-action"; - -run({ - token: process.env["ACCESS_TOKEN"], - branch: "gh-pages", - folder: "build", - repositoryName: "JamesIves/github-pages-deploy-action", - silent: true, - workspace: "src/project/location", -}); +```yml +permissions: + contents: write ``` -For more information regarding the [action interface please click here](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/src/constants.ts#L7). - ## Configuration ๐Ÿ“ The `with` portion of the workflow **must** be configured before the action will work. You can add these in the `with` section found in the examples above. Any `secrets` must be referenced using the bracket syntax and stored in the GitHub repository's `Settings/Secrets` menu. You can learn more about setting environment variables with GitHub actions [here](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets). @@ -120,33 +86,35 @@ The `with` portion of the workflow **must** be configured before the action will The following options must be configured in order to make a deployment. -| Key | Value Information | Type | Required | -| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | -| `branch` | This is the branch you wish to deploy to, for example `gh-pages` or `docs`. | `with` | **Yes** | -| `folder` | The folder in your repository that you want to deploy. If your build script compiles into a directory named `build` you'd put it here. If you wish to deploy the root directory you can place a `.` here. You can also utilize absolute file paths by appending `~` to your folder path. | `with` | **Yes** | +| Key | Value Information | Type | Required | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | +| `folder` | The folder in your repository that you want to deploy. If your build script compiles into a directory named `build` you'd put it here. If you wish to deploy the root directory you can place a `.` here. You can also utilize absolute file paths by prepending `~` to your folder path. Note that any files/folders matching `.gitignore` entries will not be deployed. Some tools auto-generate a `.gitignore` file for build output. | `with` | **Yes** | -By default the action does not need any token configuration and uses the provided repository scoped GitHub token to make the deployment. If you require more customization you can modify the deployment type using the following options. +By default, the action does not need any token configuration and uses the provided repository scoped GitHub token to make the deployment. If you require more customization you can modify the deployment type using the following options. -| Key | Value Information | Type | Required | -| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- | -| `token` | This option defaults to the repository scoped GitHub Token. However if you need more permissions for things such as deploying to another repository, you can add a Personal Access Token (PAT) here. This should be stored in the `secrets / with` menu **as a secret**. We recommend using a service account with the least permissions necessary and recommend when generating a new PAT that you select the least permission scopes necessary. [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) | `with` | **No** | -| `ssh-key` | You can configure the action to deploy using SSH by setting this option to a private SSH key stored **as a secret**. It can also be set to `true` to use an existing SSH client configuration. For more detailed information on how to add your public/private ssh key pair please refer to the [Using a Deploy Key section of this README](https://github.com/JamesIves/github-pages-deploy-action/tree/dev#using-an-ssh-deploy-key-). | `with` | **No** | +| Key | Value Information | Type | Required | +| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | +| `token` | This option defaults to the repository scoped GitHub Token. However, if you need more permissions for things such as deploying to another repository, you can add a Personal Access Token (PAT) here. This should be stored in the `secrets / with` menu **as a secret**. We recommend using a service account with the least permissions necessary and recommend when generating a new PAT that you select the least permission scopes necessary. [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) | `with` | **No** | +| `ssh-key` | You can configure the action to deploy using SSH by setting this option to a private SSH key stored **as a secret**. It can also be set to `true` to use an existing SSH client configuration. For more detailed information on how to add your public/private ssh key pair please refer to the [Using a Deploy Key section of this README](https://github.com/JamesIves/github-pages-deploy-action/tree/dev#using-an-ssh-deploy-key-). | `with` | **No** | #### Optional Choices -| Key | Value Information | Type | Required | -| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | -| `git-config-name` | Allows you to customize the name that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action. | `with` | **No** | -| `git-config-email` | Allows you to customize the email that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email. | `with` | **No** | -| `repository-name` | Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: `JamesIves/github-pages-deploy-action`. You'll need to use a PAT in the `token` input for this configuration option to work properly. | `with` | **No** | -| `target-folder` | If you'd like to push the contents of the deployment folder into a specific directory on the deployment branch you can specify it here. | `with` | **No** | -| `commit-message` | If you need to customize the commit message for an integration you can do so. | `with` | **No** | -| `clean` | If your project generates hashed files on build you can use this option to automatically delete them from the target folder on the deployment branch with each deploy. This option is turned on by default, and can be toggled off by setting it to `false`. | `with` | **No** | -| `clean-exclude` | If you need to use `clean` but you'd like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string. | `with` | **No** | -| `dry-run` | Do not actually push back, but use `--dry-run` on `git push` invocations instead. | `with` | **No** | -| `single-commit` | This option can be toggled to `true` if you'd prefer to have a single commit on the deployment branch instead of maintaining the full history. **Using this option will also cause any existing history to be wiped from the deployment branch**. | `with` | **No** | -| `silent` | Silences the action output preventing it from displaying git messages. | `with` | **No** | -| `workspace` | This should point to where your project lives on the virtual machine. The GitHub Actions environment will set this for you. It is only necessary to set this variable if you're using the node module. | `with` | **No** | +| Key | Value Information | Type | Required | +| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | +| `branch` | This is the branch you wish to deploy to, for example, `gh-pages` or `docs`. Defaults to `gh-pages`. | `with` | **No** | +| `git-config-name` | Allows you to customize the name that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action. | `with` | **No** | +| `git-config-email` | Allows you to customize the email that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email. You can include `<>` for the value if you wish to omit this field altogether and push the commits without an email. | `with` | **No** | +| `repository-name` | Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: `JamesIves/github-pages-deploy-action`. You'll need to use a PAT in the `token` input for this configuration option to work properly. | `with` | **No** | +| `target-folder` | If you'd like to push the contents of the deployment folder into a specific directory on the deployment branch you can specify it here. | `with` | **No** | +| `commit-message` | If you need to customize the commit message for an integration you can do so. | `with` | **No** | +| `clean` | You can use this option to delete files from your deployment destination that no longer exist in your deployment source. One use case is if your project generates hashed files that vary from build to build. Using `clean` will not affect `.git`, `.github`, or `.ssh` directories. This option is turned on by default and can be toggled off by setting it to `false`. | `with` | **No** | +| `clean-exclude` | If you need to use `clean` but you'd like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string. | `with` | **No** | +| `dry-run` | Do not actually push back, but use `--dry-run` on `git push` invocations instead. | `with` | **No** | +| `single-commit` | This option can be toggled to `true` if you'd prefer to have a single commit on the deployment branch instead of maintaining the full history. **Using this option will also cause any existing history to be wiped from the deployment branch**. | `with` | **No** | +| `force` | Force-push new deployments to overwrite the previous version; otherwise, attempt to rebase new deployments onto any existing ones. This option is turned on by default and can be toggled off by setting it to `false`, which may be useful if there are multiple deployments in a single branch. | `with` | **No** | +| `attempt-limit` | How many rebase attempts to make before suspending the job. This option defaults to `3` and may be useful to increase when there are multiple deployments in a single branch. | `with` | **No** | +| `silent` | Silences the action output preventing it from displaying git messages. | `with` | **No** | +| `tag` | Add a tag to the commit. Only works when `dry-run` is not used. | `with` | **No** | With the action correctly configured you should see the workflow trigger the deployment under the configured conditions. @@ -154,11 +122,11 @@ With the action correctly configured you should see the workflow trigger the dep The action will export an environment variable called `deployment_status` that you can use in your workflow to determine if the deployment was successful or not. You can find an explanation of each status type below. -| Status | Description | -| ------------- |-------------| -| `success` | The `success` status indicates that the action was able to successfully deploy to the branch. | -| `failed` | The `failed` status indicates that the action encountered an error while trying to deploy. | -| `skipped` | The `skipped` status indicates that the action exited early as there was nothing new to deploy. | +| Status | Description | +| --------- | ----------------------------------------------------------------------------------------------- | +| `success` | The `success` status indicates that the action was able to successfully deploy to the branch. | +| `failed` | The `failed` status indicates that the action encountered an error while trying to deploy. | +| `skipped` | The `skipped` status indicates that the action exited early as there was nothing new to deploy. | This value is also set as a step output as `deployment-status`. @@ -172,15 +140,14 @@ If you'd prefer to use an SSH deploy key as opposed to a token you must first ge ssh-keygen -t rsa -m pem -b 4096 -C "youremailhere@example.com" -N "" ``` -Once you've generated the key pair you must add the contents of the public key within your repository's [deploy keys menu](https://developer.github.com/v3/guides/managing-deploy-keys/). You can find this option by going to `Settings > Deploy Keys`, you can name the public key whatever you want, but you **do** need to give it write access. Afterwards add the contents of the private key to the `Settings > Secrets` menu as `DEPLOY_KEY`. +Once you've generated the key pair you must add the contents of the public key within your repository's [deploy keys menu](https://developer.github.com/v3/guides/managing-deploy-keys/). You can find this option by going to `Settings > Deploy Keys`, you can name the public key whatever you want, but you **do** need to give it write access. Afterwards, add the contents of the private key to the `Settings > Secrets` menu as `DEPLOY_KEY`. -With this configured you can then set the `ssh-key` part of the action to your private key stored as a secret. +With this configured, you can then set the `ssh-key` part of the action to your private key stored as a secret. ```yml - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@4.1.1 + uses: JamesIves/github-pages-deploy-action@v4 with: - branch: gh-pages folder: site ssh-key: ${{ secrets.DEPLOY_KEY }} ``` @@ -193,23 +160,23 @@ name: Build and Deploy on: push: branches: - - master + - main jobs: deploy: + concurrency: ci-${{ github.ref }} runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v2.3.1 + uses: actions/checkout@v4 - name: Install and Build ๐Ÿ”ง # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. run: | - npm install + npm ci npm run build - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@4.1.1 + uses: JamesIves/github-pages-deploy-action@v4 with: - branch: gh-pages folder: build clean: true clean-exclude: | @@ -221,7 +188,7 @@ jobs:

-Alternatively if you've already configured the SSH client within a previous step you can set the `ssh-key` option to `true` to allow it to deploy using an existing SSH client. Instead of adjusting the client configuration it will simply switch to using GitHub's SSH endpoints. +Alternatively, if you've already configured the SSH client within a previous step you can set the `ssh-key` option to `true` to allow it to deploy using an existing SSH client. Instead of adjusting the client configuration, it will simply switch to using GitHub's SSH endpoints. --- @@ -243,16 +210,18 @@ If you're using an operating system such as [Windows](https://www.microsoft.com/ ```yml name: Build and Deploy on: [push] +permissions: + contents: write jobs: build: runs-on: windows-latest # The first job utilizes windows-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v2.3.1 + uses: actions/checkout@v4 - name: Install and Build ๐Ÿ”ง # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. run: | - npm install + npm ci npm run build - name: Upload Artifacts ๐Ÿ”บ # The project is then uploaded as an artifact named 'site'. @@ -262,11 +231,12 @@ jobs: path: build deploy: - needs: [build] # The second job must depend on the first one to complete before running, and uses ubuntu-latest instead of windows. + concurrency: ci-${{ github.ref }} + needs: [build] # The second job must depend on the first one to complete before running and uses ubuntu-latest instead of windows. runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v2.3.1 + uses: actions/checkout@v4 - name: Download Artifacts ๐Ÿ”ป # The built project is downloaded into the 'site' folder. uses: actions/download-artifact@v1 @@ -274,11 +244,9 @@ jobs: name: site - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@4.1.1 + uses: JamesIves/github-pages-deploy-action@v4 with: - token: ${{ secrets.ACCESS_TOKEN }} - branch: gh-pages - folder: "site" # The deployment folder should match the name of the artifact. Even though our project builds into the 'build' folder the artifact name of 'site' must be placed here. + folder: 'site' # The deployment folder should match the name of the artifact. Even though our project builds into the 'build' folder the artifact name of 'site' must be placed here. ```

@@ -296,55 +264,50 @@ If you use a [container](https://help.github.com/en/actions/automating-your-work apt-get update && apt-get install -y rsync - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@4.1.1 + uses: JamesIves/github-pages-deploy-action@v4 ``` --- ### Additional Build Files ๐Ÿ“ -If you're using a custom domain and require a `CNAME` file, or if you require the use of a `.nojekyll` file, you can safely commit these files directly into deployment branch without them being overridden after each deployment, additionally you can include these files in your deployment folder to update them. If you need to add additional files to the deployment that should be ignored by the build clean-up steps you can utilize the `clean-exclude` option. +If you're using a custom domain and require a `CNAME` file, or if you require the use of a `.nojekyll` file, you can safely commit these files directly into the deployment branch without them being overridden after each deployment, additionally, you can include these files in your deployment folder to update them. If you need to add additional files to the deployment that should be ignored by the build clean-up steps you can utilize the `clean-exclude` option.
Click here to view an example of this.

```yml name: Build and Deploy +permissions: + contents: write on: push: branches: - - master + - main jobs: deploy: + concurrency: ci-${{ github.ref }} runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v2.3.1 + uses: actions/checkout@v4 - name: Install and Build ๐Ÿ”ง # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. run: | - npm install + npm ci npm run build - name: Deploy ๐Ÿš€ - uses: JamesIves/github-pages-deploy-action@4.1.1 + uses: JamesIves/github-pages-deploy-action@v4 with: - branch: gh-pages folder: build clean: true clean-exclude: | special-file.txt some/*.txt ``` +

If you wish to remove these files you must go into the deployment branch directly to remove them. This is to prevent accidental changes in your deployment script from creating breaking changes. - ---- - -## Support ๐Ÿ’– - -This project would not be possible without all of our fantastic [contributors](https://github.com/JamesIves/github-pages-deploy-action/graphs/contributors). - -If you'd like to support the maintenance and upkeep of this project you can [donate via GitHub Sponsors](https://github.com/sponsors/JamesIves). This project is distributed under the [MIT](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/LICENSE) license, and the project logo was created by [Paganini](https://twitter.com/paganiniart). diff --git a/SECURITY.md b/SECURITY.md index 6edd31706..917da7150 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,7 +7,7 @@ The current version is actively maintained and will receive frequent updates and | Version | Supported | | ------- | ------------------ | | 4.0.x | :white_check_mark: | -| < 3.0 | :x: | +| < 4.0.0 | :x: | ## Reporting a Vulnerability diff --git a/__tests__/env.js b/__tests__/env.js index 5c29df783..a63280e2f 100644 --- a/__tests__/env.js +++ b/__tests__/env.js @@ -1 +1,2 @@ process.env.ACTIONS_STEP_DEBUG = 'false' +process.env.RUNNER_OS = 'Windows' diff --git a/__tests__/execute.test.ts b/__tests__/execute.test.ts index 14831ba80..f517e812f 100644 --- a/__tests__/execute.test.ts +++ b/__tests__/execute.test.ts @@ -10,11 +10,13 @@ describe('execute', () => { stdout('hello') await execute('echo Montezuma', './', true) - expect(exec).toBeCalledWith('echo Montezuma', [], { + expect(exec).toHaveBeenCalledWith('echo Montezuma', [], { cwd: './', silent: true, + ignoreReturnCode: false, listeners: { - stdout: expect.any(Function) + stdout: expect.any(Function), + stderr: expect.any(Function) } }) }) @@ -25,11 +27,13 @@ describe('execute', () => { stdout('hello') await execute('echo Montezuma', './', false) - expect(exec).toBeCalledWith('echo Montezuma', [], { + expect(exec).toHaveBeenCalledWith('echo Montezuma', [], { cwd: './', silent: false, + ignoreReturnCode: false, listeners: { - stdout: expect.any(Function) + stdout: expect.any(Function), + stderr: expect.any(Function) } }) }) diff --git a/__tests__/git.test.ts b/__tests__/git.test.ts index 5f704c7ce..9aba5c36c 100644 --- a/__tests__/git.test.ts +++ b/__tests__/git.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable import/first */ // Initial env variable setup for tests. process.env['INPUT_FOLDER'] = 'build' process.env['GITHUB_SHA'] = '123' @@ -29,9 +28,8 @@ jest.mock('@actions/io', () => ({ })) jest.mock('../src/execute', () => ({ - // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, - execute: jest.fn() + execute: jest.fn(() => ({stdout: '', stderr: ''})) })) describe('git', () => { @@ -56,7 +54,7 @@ describe('git', () => { }) await init(action) - expect(execute).toBeCalledTimes(5) + expect(execute).toHaveBeenCalledTimes(7) }) it('should catch when a function throws an error', async () => { @@ -81,7 +79,7 @@ describe('git', () => { try { await init(action) } catch (error) { - expect(error.message).toBe( + expect(error instanceof Error && error.message).toBe( 'There was an error initializing the repository: Mocked throw โŒ' ) } @@ -103,7 +101,7 @@ describe('git', () => { }) await init(action) - expect(execute).toBeCalledTimes(5) + expect(execute).toHaveBeenCalledTimes(7) }) it('should not unset git config if a user is using ssh', async () => { @@ -125,7 +123,7 @@ describe('git', () => { }) await init(action) - expect(execute).toBeCalledTimes(4) + expect(execute).toHaveBeenCalledTimes(6) process.env.CI = undefined }) @@ -146,7 +144,7 @@ describe('git', () => { }) await init(action) - expect(execute).toBeCalledTimes(5) + expect(execute).toHaveBeenCalledTimes(7) }) }) @@ -169,8 +167,8 @@ describe('git', () => { const response = await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(11) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(15) + expect(rmRF).toHaveBeenCalledTimes(1) expect(response).toBe(Status.SUCCESS) }) @@ -192,8 +190,8 @@ describe('git', () => { const response = await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(10) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(14) + expect(rmRF).toHaveBeenCalledTimes(1) expect(response).toBe(Status.SUCCESS) }) @@ -217,8 +215,8 @@ describe('git', () => { await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(10) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(15) + expect(rmRF).toHaveBeenCalledTimes(1) }) it('should execute commands with single commit toggled and existing branch', async () => { @@ -241,8 +239,8 @@ describe('git', () => { await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(9) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(14) + expect(rmRF).toHaveBeenCalledTimes(1) }) it('should execute commands with single commit and dryRun toggled', async () => { @@ -266,8 +264,8 @@ describe('git', () => { await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(9) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(14) + expect(rmRF).toHaveBeenCalledTimes(1) }) it('should not ignore CNAME or nojekyll if they exist in the deployment folder', async () => { @@ -297,9 +295,9 @@ describe('git', () => { const response = await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(11) - expect(rmRF).toBeCalledTimes(1) - expect(fs.existsSync).toBeCalledTimes(2) + expect(execute).toHaveBeenCalledTimes(15) + expect(rmRF).toHaveBeenCalledTimes(1) + expect(fs.existsSync).toHaveBeenCalledTimes(2) expect(response).toBe(Status.SUCCESS) }) @@ -329,8 +327,8 @@ describe('git', () => { await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(8) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(12) + expect(rmRF).toHaveBeenCalledTimes(1) }) }) @@ -354,8 +352,8 @@ describe('git', () => { await deploy(action) // Includes the call to generateWorktree - expect(execute).toBeCalledTimes(8) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(12) + expect(rmRF).toHaveBeenCalledTimes(1) }) it('should gracefully handle target folder', async () => { @@ -374,9 +372,9 @@ describe('git', () => { await deploy(action) - expect(execute).toBeCalledTimes(8) - expect(rmRF).toBeCalledTimes(1) - expect(mkdirP).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(12) + expect(rmRF).toHaveBeenCalledTimes(1) + expect(mkdirP).toHaveBeenCalledTimes(1) }) it('should stop early if there is nothing to commit', async () => { @@ -394,8 +392,8 @@ describe('git', () => { }) const response = await deploy(action) - expect(execute).toBeCalledTimes(8) - expect(rmRF).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(12) + expect(rmRF).toHaveBeenCalledTimes(1) expect(response).toBe(Status.SKIPPED) }) @@ -420,10 +418,56 @@ describe('git', () => { try { await deploy(action) } catch (error) { - expect(error.message).toBe( + expect(error instanceof Error && error.message).toBe( 'The deploy step encountered an error: Mocked throw โŒ' ) } }) + + it('should execute commands if force is false and retry until limit is exceeded', async () => { + Object.assign(action, { + hostname: 'github.com', + silent: false, + folder: 'assets', + branch: 'branch', + force: false, + token: '123', + repositoryName: 'JamesIves/montezuma', + pusher: { + name: 'asd', + email: 'as@cat' + }, + isTest: TestFlag.HAS_CHANGED_FILES + }) + + try { + await deploy(action) + } catch (error) { + expect(error instanceof Error && error.message).toBe( + 'The deploy step encountered an error: Attempt limit exceeded โŒ' + ) + } + }) + + it('should add a tag to the commit', async () => { + Object.assign(action, { + hostname: 'github.com', + silent: false, + folder: 'assets', + branch: 'branch', + token: '123', + repositoryName: 'JamesIves/montezuma', + tag: 'v0.1', + pusher: { + name: 'asd', + email: 'as@cat' + }, + isTest: TestFlag.HAS_CHANGED_FILES + }) + + const response = await deploy(action) + expect(execute).toHaveBeenCalledTimes(17) + expect(response).toBe(Status.SUCCESS) + }) }) }) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index a1708ecb3..3d33495aa 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -1,8 +1,10 @@ -/* eslint-disable import/first */ // Initial env variable setup for tests. process.env['INPUT_FOLDER'] = 'build' process.env['GITHUB_SHA'] = '123' process.env['INPUT_DEBUG'] = 'debug' +process.env['GITHUB_REF_NAME'] = 'test' +process.env['RUNNER_OS'] = 'Linux' +process.env['CI'] = 'true' import '../src/main' import {action, TestFlag} from '../src/constants' @@ -14,7 +16,7 @@ import {setFailed, exportVariable} from '@actions/core' const originalAction = JSON.stringify(action) jest.mock('../src/execute', () => ({ - execute: jest.fn() + execute: jest.fn(() => ({stdout: '', stderr: ''})) })) jest.mock('@actions/io', () => ({ @@ -27,7 +29,8 @@ jest.mock('@actions/core', () => ({ setOutput: jest.fn(), exportVariable: jest.fn(), isDebug: jest.fn(), - info: jest.fn() + info: jest.fn(), + notice: jest.fn() })) describe('main', () => { @@ -38,7 +41,7 @@ describe('main', () => { it('should run through the commands', async () => { Object.assign(action, { repositoryPath: 'JamesIves/github-pages-deploy-action', - folder: 'assets', + folder: '.github/docs', branch: 'branch', token: '123', hostname: 'github.com', @@ -50,16 +53,16 @@ describe('main', () => { debug: true }) await run(action) - expect(execute).toBeCalledTimes(13) - expect(rmRF).toBeCalledTimes(1) - expect(exportVariable).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(19) + expect(rmRF).toHaveBeenCalledTimes(1) + expect(exportVariable).toHaveBeenCalledTimes(1) }) it('should run through the commands and succeed', async () => { Object.assign(action, { hostname: 'github.com', repositoryPath: 'JamesIves/github-pages-deploy-action', - folder: 'assets', + folder: '.github/docs', branch: 'branch', token: '123', sshKey: true, @@ -70,15 +73,15 @@ describe('main', () => { isTest: TestFlag.HAS_CHANGED_FILES }) await run(action) - expect(execute).toBeCalledTimes(16) - expect(rmRF).toBeCalledTimes(1) - expect(exportVariable).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(22) + expect(rmRF).toHaveBeenCalledTimes(1) + expect(exportVariable).toHaveBeenCalledTimes(1) }) it('should throw if an error is encountered', async () => { Object.assign(action, { hostname: 'github.com', - folder: 'assets', + folder: '.github/docs', branch: 'branch', token: null, sshKey: null, @@ -89,8 +92,8 @@ describe('main', () => { isTest: TestFlag.HAS_CHANGED_FILES }) await run(action) - expect(execute).toBeCalledTimes(0) - expect(setFailed).toBeCalledTimes(1) - expect(exportVariable).toBeCalledTimes(1) + expect(execute).toHaveBeenCalledTimes(0) + expect(setFailed).toHaveBeenCalledTimes(1) + expect(exportVariable).toHaveBeenCalledTimes(1) }) }) diff --git a/__tests__/ssh.test.ts b/__tests__/ssh.test.ts index b9dc73cde..36f9b8b83 100644 --- a/__tests__/ssh.test.ts +++ b/__tests__/ssh.test.ts @@ -33,7 +33,7 @@ jest.mock('@actions/core', () => ({ })) jest.mock('../src/execute', () => ({ - execute: jest.fn() + execute: jest.fn(() => ({stdout: '', stderr: ''})) })) describe('configureSSH', () => { @@ -57,9 +57,9 @@ describe('configureSSH', () => { await configureSSH(action) - expect(execute).toBeCalledTimes(0) - expect(mkdirP).toBeCalledTimes(0) - expect(appendFileSync).toBeCalledTimes(0) + expect(execute).toHaveBeenCalledTimes(0) + expect(mkdirP).toHaveBeenCalledTimes(0) + expect(appendFileSync).toHaveBeenCalledTimes(0) }) it('should configure the ssh client if a key is defined', async () => { @@ -82,9 +82,9 @@ describe('configureSSH', () => { await configureSSH(action) - expect(execFileSync).toBeCalledTimes(1) - expect(exportVariable).toBeCalledTimes(2) - expect(execSync).toBeCalledTimes(3) + expect(execFileSync).toHaveBeenCalledTimes(1) + expect(exportVariable).toHaveBeenCalledTimes(2) + expect(execSync).toHaveBeenCalledTimes(3) }) it('should not export variables if the return from ssh-agent is skewed', async () => { @@ -107,9 +107,9 @@ describe('configureSSH', () => { await configureSSH(action) - expect(execFileSync).toBeCalledTimes(1) - expect(exportVariable).toBeCalledTimes(0) - expect(execSync).toBeCalledTimes(3) + expect(execFileSync).toHaveBeenCalledTimes(1) + expect(exportVariable).toHaveBeenCalledTimes(0) + expect(execSync).toHaveBeenCalledTimes(3) }) it('should throw if something errors', async () => { @@ -133,7 +133,7 @@ describe('configureSSH', () => { try { await configureSSH(action) } catch (error) { - expect(error.message).toBe( + expect(error instanceof Error && error.message).toBe( 'The ssh client configuration encountered an error: Mocked throw โŒ' ) } diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index a7ade4a39..08399a787 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -6,7 +6,8 @@ import { generateFolderPath, suppressSensitiveInformation, checkParameters, - stripProtocolFromUrl + stripProtocolFromUrl, + extractErrorMessage } from '../src/util' describe('util', () => { @@ -222,8 +223,8 @@ describe('util', () => { try { checkParameters(action) } catch (e) { - expect(e.message).toMatch( - 'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.' + expect(e instanceof Error && e.message).toMatch( + 'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. For more details on how to use an ssh deploy key please refer to the documentation.' ) } }) @@ -242,8 +243,8 @@ describe('util', () => { try { checkParameters(action) } catch (e) { - expect(e.message).toMatch( - 'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.' + expect(e instanceof Error && e.message).toMatch( + 'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. For more details on how to use an ssh deploy key please refer to the documentation.' ) } }) @@ -262,7 +263,7 @@ describe('util', () => { try { checkParameters(action) } catch (e) { - expect(e.message).toMatch('Branch is required.') + expect(e instanceof Error && e.message).toMatch('Branch is required.') } }) @@ -280,7 +281,7 @@ describe('util', () => { try { checkParameters(action) } catch (e) { - expect(e.message).toMatch( + expect(e instanceof Error && e.message).toMatch( 'You must provide the action with a folder to deploy.' ) } @@ -301,7 +302,7 @@ describe('util', () => { action.folderPath = generateFolderPath(action) checkParameters(action) } catch (e) { - expect(e.message).toMatch( + expect(e instanceof Error && e.message).toMatch( `The directory you're trying to deploy named notARealFolder doesn't exist. Please double check the path and any prerequisite build scripts and try again. โ—` ) } @@ -327,4 +328,22 @@ describe('util', () => { ) }) }) + + describe('extractErrorMessage', () => { + it('gets the message of a Error', () => { + expect(extractErrorMessage(new Error('a error message'))).toBe( + 'a error message' + ) + }) + + it('gets the message of a string', () => { + expect(extractErrorMessage('a error message')).toBe('a error message') + }) + + it('gets the message of a object', () => { + expect(extractErrorMessage({special: 'a error message'})).toBe( + `{"special":"a error message"}` + ) + }) + }) }) diff --git a/__tests__/worktree.error.test.ts b/__tests__/worktree.error.test.ts index 0bbf7df6f..da928ce0c 100644 --- a/__tests__/worktree.error.test.ts +++ b/__tests__/worktree.error.test.ts @@ -3,9 +3,8 @@ import {execute} from '../src/execute' import {generateWorktree} from '../src/worktree' jest.mock('../src/execute', () => ({ - // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, - execute: jest.fn() + execute: jest.fn(() => ({stdout: '', stderr: ''})) })) describe('generateWorktree', () => { @@ -28,7 +27,7 @@ describe('generateWorktree', () => { true ) } catch (error) { - expect(error.message).toBe( + expect(error instanceof Error && error.message).toBe( 'There was an error creating the worktree: Mocked throw โŒ' ) } diff --git a/__tests__/worktree.test.ts b/__tests__/worktree.test.ts index 4d5e1e96f..99287af91 100644 --- a/__tests__/worktree.test.ts +++ b/__tests__/worktree.test.ts @@ -14,15 +14,16 @@ jest.mock('@actions/core', () => ({ })) /* - Test generateWorktree against a known git repository. - The upstream repository `origin` is set up once for the test suite, - and for each test run, a new clone is created. - - See workstree.error.test.ts for testing mocked errors from git.*/ + Test generateWorktree against a known git repository. + The upstream repository `origin` is set up once for the test suite, + and for each test run, a new clone is created. + See worktree.error.test.ts for testing mocked errors from git. + */ describe('generateWorktree', () => { let tempdir: string | null = null let clonedir: string | null = null + beforeAll(async () => { // Set up origin repository const silent = true @@ -50,6 +51,7 @@ describe('generateWorktree', () => { await execute('git add .', origin, silent) await execute('git commit -mgh1', origin, silent) }) + beforeEach(async () => { // Clone origin to our workspace for each test const silent = true @@ -65,17 +67,19 @@ describe('generateWorktree', () => { await execute('git fetch --depth=1 origin main', clonedir, silent) await execute('git checkout main', clonedir, silent) }) + afterEach(async () => { // Tear down workspace await rmRF(clonedir as string) }) + afterAll(async () => { // Tear down origin repository if (tempdir) { await rmRF(tempdir) - // console.log(tempdir) } }) + describe('with existing branch and new commits', () => { it('should check out the latest commit', async () => { const workspace = clonedir as string @@ -92,24 +96,29 @@ describe('generateWorktree', () => { 'worktree', true ) + const dirEntries = await fs.promises.readdir( path.join(workspace, 'worktree') ) + expect(dirEntries.sort((a, b) => a.localeCompare(b))).toEqual([ '.git', 'gh1' ]) + const commitMessages = await execute( 'git log --format=%s', path.join(workspace, 'worktree'), true ) - expect(commitMessages).toBe('gh1') + + expect(commitMessages.stdout).toBe('gh1') }) }) describe('with missing branch and new commits', () => { it('should create initial commit', async () => { const workspace = clonedir as string + await generateWorktree( { hostname: 'github.com', @@ -123,21 +132,26 @@ describe('generateWorktree', () => { 'worktree', false ) + const dirEntries = await fs.promises.readdir( path.join(workspace, 'worktree') ) + expect(dirEntries).toEqual(['.git']) + const commitMessages = await execute( 'git log --format=%s', path.join(workspace, 'worktree'), true ) - expect(commitMessages).toBe('Initial no-pages commit') + + expect(commitMessages.stdout).toBe('Initial no-pages commit') }) }) describe('with existing branch and singleCommit', () => { it('should check out the latest commit', async () => { const workspace = clonedir as string + await generateWorktree( { hostname: 'github.com', @@ -151,14 +165,17 @@ describe('generateWorktree', () => { 'worktree', true ) + const dirEntries = await fs.promises.readdir( path.join(workspace, 'worktree') ) + expect(dirEntries.sort((a, b) => a.localeCompare(b))).toEqual([ '.git', 'gh1' ]) - expect(async () => { + + return expect(async () => { await execute( 'git log --format=%s', path.join(workspace, 'worktree'), @@ -170,6 +187,7 @@ describe('generateWorktree', () => { describe('with missing branch and singleCommit', () => { it('should create initial commit', async () => { const workspace = clonedir as string + await generateWorktree( { hostname: 'github.com', @@ -183,11 +201,14 @@ describe('generateWorktree', () => { 'worktree', false ) + const dirEntries = await fs.promises.readdir( path.join(workspace, 'worktree') ) + expect(dirEntries).toEqual(['.git']) - expect(async () => { + + return expect(async () => { await execute( 'git log --format=%s', path.join(workspace, 'worktree'), diff --git a/action.yml b/action.yml index 8c1786c35..ac97fc721 100644 --- a/action.yml +++ b/action.yml @@ -2,7 +2,7 @@ name: 'Deploy to GitHub Pages' description: 'This action will handle the deployment process of your project to GitHub Pages.' author: 'James Ives ' runs: - using: 'node12' + using: 'node20' main: 'lib/main.js' branding: icon: 'git-commit' @@ -24,16 +24,17 @@ inputs: However if you need more permissions for things such as deploying to another repository, you can add a Personal Access Token (PAT) here. This should be stored in the `secrets / with` menu **as a secret**. - We recommend using a service account with the least permissions neccersary + We recommend using a service account with the least permissions necessary and when generating a new PAT that you select the least permission scopes required. - + [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) required: false default: ${{ github.token }} branch: description: 'This is the branch you wish to deploy to, for example gh-pages or docs.' - required: true + required: false + default: gh-pages folder: description: 'The folder in your repository that you want to deploy. If your build script compiles into a directory named build you would put it here. Folder paths cannot have a leading / or ./. If you wish to deploy the root directory you can place a . here.' @@ -53,27 +54,32 @@ inputs: default: true clean-exclude: - description: "If you need to use clean but you would like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string." + description: 'If you need to use clean but you would like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string.' required: false dry-run: - description: "Do not actually push back, but use `--dry-run` on `git push` invocations insead." + description: 'Do not actually push back, but use `--dry-run` on `git push` invocations instead.' + required: false + + force: + description: 'Whether to force-push and overwrite any existing deployment. Setting this to false will attempt to rebase simultaneous deployments. This option is on by default and can be toggled off by setting it to false.' required: false + default: true git-config-name: - description: "Allows you to customize the name that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action." + description: 'Allows you to customize the name that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action.' required: false git-config-email: - description: "Allows you to customize the email that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email." + description: 'Allows you to customize the email that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email.' required: false repository-name: - description: "Allows you to speicfy a different repository path so long as you have permissions to push to it. This should be formatted like so: JamesIves/github-pages-deploy-action" + description: 'Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: JamesIves/github-pages-deploy-action' required: false - workspace: - description: "This should point to where your project lives on the virtual machine. The GitHub Actions environment will set this for you. It is only neccersary to set this variable if you're using the node module." + tag: + description: "Add a tag to the commit, this can be used like so: 'v0.1'. Only works when 'dry-run' is not used." required: false single-commit: @@ -81,8 +87,13 @@ inputs: required: false silent: - description: "Silences the action output preventing it from displaying git messages." + description: 'Silences the action output preventing it from displaying git messages.' + required: false + + attempt-limit: + description: 'How many rebase attempts to make before suspending the job. This option defaults to `3` and may be useful to increase when there are multiple deployments in a single branch.' required: false + default: 3 outputs: deployment-status: diff --git a/assets/icon.png b/assets/icon.png deleted file mode 100644 index f1b729fd1..000000000 Binary files a/assets/icon.png and /dev/null differ diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..33301eb0e --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,72 @@ +import eslint from '@eslint/js' +import tseslint from 'typescript-eslint' +import eslintConfigPrettier from 'eslint-config-prettier' +import jest from 'eslint-plugin-jest' + +export default tseslint.config( + eslintConfigPrettier, + jest.configs['flat/recommended'], + eslint.configs.recommended, + ...tseslint.configs.recommended, + { + languageOptions: { + globals: { + process: true, + module: true + } + }, + rules: { + 'jest/no-conditional-expect': 'off', + '@typescript-eslint/no-restricted-types': [ + 'error', + { + types: { + Number: { + message: 'Use number instead', + fixWith: 'number' + }, + String: { + message: 'Use string instead', + fixWith: 'string' + }, + Boolean: { + message: 'Use boolean instead', + fixWith: 'boolean' + }, + Object: { + message: 'Use object instead', + fixWith: 'object' + }, + '{}': { + message: 'Use object instead', + fixWith: 'object' + }, + Symbol: { + message: 'Use symbol instead', + fixWith: 'symbol' + } + } + } + ], + '@typescript-eslint/array-type': ['error', {default: 'array'}], + '@typescript-eslint/explicit-module-boundary-types': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-unused-vars': 'error', + '@typescript-eslint/explicit-function-return-type': 'error', + 'object-shorthand': ['error', 'always'], + 'prefer-destructuring': [ + 'error', + { + array: false, + object: true + }, + { + enforceForRenamedProperties: false + } + ], + 'no-console': ['error', {allow: ['warn', 'error']}], + 'no-alert': 'error', + 'no-debugger': 'error' + } + } +) diff --git a/integration/.nojekyll b/integration/.nojekyll new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/integration/.nojekyll @@ -0,0 +1 @@ + diff --git a/integration/index.html b/integration/index.html index 024fc79a4..48f62593d 100644 --- a/integration/index.html +++ b/integration/index.html @@ -1,12 +1,13 @@ - + - + Integration Test