diff --git a/.github/branches.md b/.github/branches.md new file mode 100644 index 0000000000..56475575f6 --- /dev/null +++ b/.github/branches.md @@ -0,0 +1,30 @@ + +main branch +- contains latest stable release + +dev branch +- latest dev version +- branch off this to make feature X, then PR back in + +1 branch per release (aka release branches) +- note that these are for preparing a release, not making a deployment +- these are created by branching off the dev branch, e.g. release/0.3.45 +- do all the testing here, e.g. staging, etc +- when sufficiently tested, merge branch into main + +on merge of release/x.y.z into main +- after merging to main, create a tag for that version on main branch +- delete the release branch - we don't need it anymore. Releases should be managed via tags due to immutability (e.g. a branch could be pushed to in the future, whcih wouldn't make sense for a release of 0.3.45 to be mutated after being released to npm, dockerhub, etc, whereas a tag is just as-is, can't be updated) +- deploy to dockerhub, npm, etc +- merge main into dev branch to bring across version bumps for the release (and any other release based changes, e.g. changelog, etc) + +pros: +- main contains the latest stable code, so easy to work with for newcomers (we don't have this currently as main is the bleeding edge code) +- merging a release branch into main is a great place to do the tagging of releases (e.g. release 0.3.45), i.e. main just becomes a log of release/a.b.c then release/d.e.f, etc, etc +- staging in the release branch +- release branches allow us a gap to prep a release, i.e. build it, make a contract / staging env, run some automated or manual tests, etc. It's essentially saying "take dev branch in this state and prep a release". The prep can be tweaking the dev code if need be to making it release worthy, but only changes required for releasing, we shouldn't be doing dev on release branches +- hotfixes are easy, branch off main, make the fix, do a release branch, pr back into main, then the hotfix will get pushed to dev too + +cons: +- more branches so more discipline needed by us to not f it up (though I think the above plan is pretty simple, we can do it) +- two big branches (main and dev) compared to our current process of 1 diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml deleted file mode 100644 index d8cd3a39c4..0000000000 --- a/.github/release-drafter.yml +++ /dev/null @@ -1,5 +0,0 @@ -# https://github.com/release-drafter/release-drafter -template: | - ## What’s Changed - - $CHANGES diff --git a/.github/weekly-digest.yml b/.github/weekly-digest.yml deleted file mode 100644 index 08cced6393..0000000000 --- a/.github/weekly-digest.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Configuration for weekly-digest - https://github.com/apps/weekly-digest -publishDay: mon -canPublishIssues: true -canPublishPullRequests: true -canPublishContributors: true -canPublishStargazers: true -canPublishCommits: true diff --git a/.github/workflows/auto_merge.yml b/.github/workflows/auto_merge.yml index 2adc98bddb..1c3d8e58ab 100644 --- a/.github/workflows/auto_merge.yml +++ b/.github/workflows/auto_merge.yml @@ -1,15 +1,21 @@ +# Merge a PR automatically when opened or reopened + name: auto_merge on: pull_request: - branches: [main] types: - opened - reopened +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: auto_merge: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -53,7 +59,9 @@ jobs: - uses: actions/setup-node@v3 with: node-version-file: '.nvmrc' - - run: npm i -g npm@$(cat package.json | jq -r .engines.npm) + + - name: Install + run: npm i -g npm@$(cat package.json | jq -r .engines.npm) - name: Enable auto-merge on PR env: diff --git a/.github/workflows/bump_version.yml b/.github/workflows/bump_version.yml index 69a183e4f1..3e123779f0 100644 --- a/.github/workflows/bump_version.yml +++ b/.github/workflows/bump_version.yml @@ -1,3 +1,5 @@ +# Workflow which bumps the version of all packages in the repo + name: bump_version on: @@ -57,51 +59,25 @@ jobs: - uses: actions/checkout@v3 - - run: mkdir -p protocol/cargo-cache - - run: mkdir -p protocol/target - - run: mkdir -p node_modules - - run: mkdir -p ~/.cache/Cypress - - - name: Restore cache - uses: actions/cache/restore@v3 - with: - path: | - protocol/cargo-cache - protocol/target - node_modules - ~/.cache/Cypress - # note that restoring a cache in github is a pain. The trailing '-' matches any string after the '-', therefore 'abc-' would match a cache named 'abc-1234' or 'abc-5678', etc. - # the problem is 'abc-' will not match a cache named 'abc'! So if you're using wildcard cache name selectors like this, you need a field that changes as the suffix to become the wildcard - # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` - key: some-unused-cache-key - restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- - - - run: ls -la ~/.cache/Cypress || true - - run: ls -la protocol/cargo-cache || true - - run: ls -la protocol/target/ink || true - - run: ls -la node_modules || true - - - uses: actions/setup-node@v3 - with: - node-version-file: '.nvmrc' - - run: npm i -g npm@$(cat package.json | jq -r .engines.npm) - - - run: npm ci - - - run: npm run build -w @prosopo/scripts - - run: npm run build -w @prosopo/protocol-dev - - name: Bump version env: GITHUB_TOKEN: ${{ secrets.PROSOPONATOR_PAT }} run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + # make a new branch for the version changes - git switch -c bump-version-${{ github.event.inputs.version }} - - # make the version changes - npm run version ${{ github.event.inputs.version }} - + git switch -c release/${{ github.event.inputs.version }} + + # find all package.json files, recursively + pkgJsons=$(find . -name package.json -prune -not -path '*/node_modules/*' -not -path '*/.next/*') + # replace the version in all package.json files + xargs -I % sh -c "cat % | jq '.version = \"${{ github.event.inputs.version }}\"' > %.new && mv %.new %" <<< "$pkgJsons" + + # find all Cargo.toml files + cargoTomls=$(find . -name Cargo.toml -prune -not -path '*/protocol/cargo-cache/*') + # replace the first version line in all Cargo.toml files + xargs -I % sh -c "sed -i '0,/version =/s/version =.*/version = \"${{ github.event.inputs.version }}\"/' %" <<< "$cargoTomls" + # rebuild typechain npm run build:typechain diff --git a/.github/workflows/post_pr.yml b/.github/workflows/cache.yml similarity index 85% rename from .github/workflows/post_pr.yml rename to .github/workflows/cache.yml index 0b1207d637..84acb3d50b 100644 --- a/.github/workflows/post_pr.yml +++ b/.github/workflows/cache.yml @@ -1,11 +1,10 @@ -name: post_pr +# Build a cache of build artifacts after PRs to speed up subsequent builds + +name: cache -# on push to main, or manually triggered -# we do this because any branch can use caches built on main, whereas caches built on other branches are only available to that branch and its children on: push: - branches: - - 'main' + branches: [main, dev] workflow_dispatch: concurrency: @@ -60,6 +59,7 @@ jobs: - uses: actions/checkout@v3 + # make cache dirs - run: mkdir -p protocol/cargo-cache - run: mkdir -p protocol/target - run: mkdir -p node_modules @@ -103,20 +103,21 @@ jobs: protocol/target node_modules ~/.cache/Cypress - key: project-cache-${{ runner.os }}-${{ runner.arch }}-${{ github.run_id }}-${{ github.run_attempt }} + key: project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}-${{ github.run_id }}-${{ github.run_attempt }} # remove all but the latest cache, leaving only the cache we just saved - name: Cleanup caches if: always() run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + set +e; gh extension install actions/gh-actions-cache; set -e - REPO=${{ github.repository }} echo "Fetching list of cache key" - cacheKeys=$(gh actions-cache list --sort created-at --order desc --limit 100 -R $REPO --key project-cache-${{ runner.os }}-${{ runner.arch }}- | cut -f 1 | tail -n +3) + cacheKeys=$(gh actions-cache list --sort created-at --order desc --limit 100 -R ${{ github.repository }} --key project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- | cut -f 1 | tail -n +3) echo caches to be removed: echo ${cacheKeys} set +e for cacheKey in $cacheKeys do - gh actions-cache delete $cacheKey -R $REPO --confirm + gh actions-cache delete $cacheKey -R ${{ github.repository }} --confirm done diff --git a/.github/workflows/check_version_bump.yml b/.github/workflows/check_version_bump.yml new file mode 100644 index 0000000000..a344e163b9 --- /dev/null +++ b/.github/workflows/check_version_bump.yml @@ -0,0 +1,99 @@ +# Check the version has been bumped before releasing + +name: check_version_bump + +on: + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + check: + runs-on: ubuntu-latest + if: github.event.pull_request.draft == false + steps: + - name: Print contexts + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + ENV_CONTEXT: ${{ toJson(env) }} + VARS_CONTEXT: ${{ toJson(vars) }} + JOB_CONTEXT: ${{ toJson(job) }} + STEPS_CONTEXT: ${{ toJson(steps) }} + RUNNER_CONTEXT: ${{ toJson(runner) }} + SECRETS_CONTEXT: ${{ toJson(secrets) }} + STRATEGY_CONTEXT: ${{ toJson(strategy) }} + MATRIX_CONTEXT: ${{ toJson(matrix) }} + NEEDS_CONTEXT: ${{ toJson(needs) }} + INPUTS_CONTEXT: ${{ toJson(inputs) }} + run: | + echo "******************************" + echo "github:" "$GITHUB_CONTEXT" + echo "******************************" + echo "env:" "$ENV_CONTEXT" + echo "******************************" + echo "vars:" "$VARS_CONTEXT" + echo "******************************" + echo "job:" "$JOB_CONTEXT" + echo "******************************" + echo "steps:" "$STEPS_CONTEXT" + echo "******************************" + echo "runner:" "$RUNNER_CONTEXT" + echo "******************************" + echo "secrets:" "$SECRETS_CONTEXT" + echo "******************************" + echo "strategy:" "$STRATEGY_CONTEXT" + echo "******************************" + echo "matrix:" "$MATRIX_CONTEXT" + echo "******************************" + echo "needs:" "$NEEDS_CONTEXT" + echo "******************************" + echo "inputs:" "$INPUTS_CONTEXT" + echo "******************************" + + - uses: actions/checkout@v3 + + # fail-fast step to check if the version has been bumped + # when running manually, there won't be a version line change, so we need to skip this step in that case + - name: Detect version bump + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + + # get the next version as the version currently set in the root package.json + NEXT=$(jq -r '.version' package.json) + echo "Next version: $NEXT" + + # checkout the repo back to before this pr + git checkout ${{ github.event.before }} + + # get the previous version as the version currently set in the root package.json in the before state + PREV=$(jq -r '.version' package.json) + echo "Previous version: $PREV" + + # switch back to the current state + git switch - + + # break next and previous versions into major, minor, patch + NEXT_MAJOR=$(echo $NEXT | cut -d. -f1) + NEXT_MINOR=$(echo $NEXT | cut -d. -f2) + NEXT_PATCH=$(echo $NEXT | cut -d. -f3) + PREV_MAJOR=$(echo $PREV | cut -d. -f1) + PREV_MINOR=$(echo $PREV | cut -d. -f2) + PREV_PATCH=$(echo $PREV | cut -d. -f3) + + # compare the versions, checking for an *increasing* version + + if [[ $NEXT_MAJOR -gt $PREV_MAJOR ]]; then + echo "Major version bump" + elif [[ $NEXT_MAJOR -eq $PREV_MAJOR && $NEXT_MINOR -gt $PREV_MINOR ]]; then + echo "Minor version bump" + elif [[ $NEXT_MAJOR -eq $PREV_MAJOR && $NEXT_MINOR -eq $PREV_MINOR && $NEXT_PATCH -gt $PREV_PATCH ]]; then + echo "Patch version bump" + else + echo "Version not bumped / not an increasing version" + exit 1 + fi diff --git a/.github/workflows/consistent_versions.yml b/.github/workflows/consistent_engine_node.yml similarity index 70% rename from .github/workflows/consistent_versions.yml rename to .github/workflows/consistent_engine_node.yml index 263066616b..a435040c99 100644 --- a/.github/workflows/consistent_versions.yml +++ b/.github/workflows/consistent_engine_node.yml @@ -1,11 +1,13 @@ -name: consistent_versions +# Check the node versions are consistent across packages + +name: consistent_engine_node on: pull_request: - branches: [main] + branches: [main, dev, release/*] paths: - '**/package.json' - - 'package.json' + - '.github/workflows/consistent_engine_node.yml' workflow_dispatch: concurrency: @@ -20,6 +22,7 @@ env: jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -61,22 +64,19 @@ jobs: - uses: actions/checkout@v3 - - name: Check versions are consistent amongst packages + - name: Check contract version matches provider version run: | - # for each package, get the version then filter to unique versions - versions=$(npx --workspaces npm pkg get version | grep "@" | awk '{print $2}' | uniq) - # if more than one version is detected, fail - if [ $(echo "$versions" | wc -l) -gt 1 ]; then - echo "Versions are not consistent amongst packages:" - echo "$versions" - exit 1 - fi - # if version doesn't match the root workspace version, fail - root_version=$(npm pkg get version) - if [ "$versions" != "$root_version" ]; then - echo "Version is not consistent with root workspace version:" + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # find all package.json files, recursively + pkgJsons=$(find . -name package.json -prune -not -path '*/node_modules/*' -not -path '*/.next/*') + + # extract the node version from the package.json files + versions=$(jq -r '.engines.node' $pkgJsons) + + # ensure all node versions are the same + if [ $(echo "$versions" | uniq | wc -l) -ne 1 ]; then + echo "Node versions are not consistent across packages" echo "$versions" - echo "$root_version" exit 1 - fi - # else versions are consistent, pass + fi diff --git a/.github/workflows/consistent_engine_npm.yml b/.github/workflows/consistent_engine_npm.yml new file mode 100644 index 0000000000..89ba5986dd --- /dev/null +++ b/.github/workflows/consistent_engine_npm.yml @@ -0,0 +1,82 @@ +# Check the npm versions are consistent across packages + +name: consistent_engine_npm + +on: + pull_request: + branches: [main, dev, release/*] + paths: + - '**/package.json' + - '.github/workflows/consistent_engine_npm.yml' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + ENVIRONMENT: development + GH_TOKEN: ${{ github.token }} + +jobs: + check: + runs-on: ubuntu-latest + if: github.event.pull_request.draft == false + steps: + - name: Print contexts + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + ENV_CONTEXT: ${{ toJson(env) }} + VARS_CONTEXT: ${{ toJson(vars) }} + JOB_CONTEXT: ${{ toJson(job) }} + STEPS_CONTEXT: ${{ toJson(steps) }} + RUNNER_CONTEXT: ${{ toJson(runner) }} + SECRETS_CONTEXT: ${{ toJson(secrets) }} + STRATEGY_CONTEXT: ${{ toJson(strategy) }} + MATRIX_CONTEXT: ${{ toJson(matrix) }} + NEEDS_CONTEXT: ${{ toJson(needs) }} + INPUTS_CONTEXT: ${{ toJson(inputs) }} + run: | + echo "******************************" + echo "github:" "$GITHUB_CONTEXT" + echo "******************************" + echo "env:" "$ENV_CONTEXT" + echo "******************************" + echo "vars:" "$VARS_CONTEXT" + echo "******************************" + echo "job:" "$JOB_CONTEXT" + echo "******************************" + echo "steps:" "$STEPS_CONTEXT" + echo "******************************" + echo "runner:" "$RUNNER_CONTEXT" + echo "******************************" + echo "secrets:" "$SECRETS_CONTEXT" + echo "******************************" + echo "strategy:" "$STRATEGY_CONTEXT" + echo "******************************" + echo "matrix:" "$MATRIX_CONTEXT" + echo "******************************" + echo "needs:" "$NEEDS_CONTEXT" + echo "******************************" + echo "inputs:" "$INPUTS_CONTEXT" + echo "******************************" + + - uses: actions/checkout@v3 + + - name: Check contract version matches provider version + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # find all package.json files, recursively + pkgJsons=$(find . -name package.json -prune -not -path '*/node_modules/*' -not -path '*/.next/*') + + # extract the npm version from the package.json files + versions=$(jq -r '.engines.npm' $pkgJsons) + + # ensure all npm versions are the same + if [ $(echo "$versions" | uniq | wc -l) -ne 1 ]; then + echo "Npm versions are not consistent across packages" + echo "$versions" + exit 1 + fi diff --git a/.github/workflows/webpack_bundling.yml b/.github/workflows/consistent_nvmrc.yml similarity index 55% rename from .github/workflows/webpack_bundling.yml rename to .github/workflows/consistent_nvmrc.yml index 6931b9002c..b29390a677 100644 --- a/.github/workflows/webpack_bundling.yml +++ b/.github/workflows/consistent_nvmrc.yml @@ -1,11 +1,14 @@ -name: webpack_bundling +# Check the npm versions are consistent across packages + +name: consistent_nvmrc on: pull_request: - branches: [main] + branches: [main, dev, release/*] paths: - - 'src/**' - - 'package.json' + - '**/package.json' + - '**/.nvmrc' + - '.github/workflows/consistent_engine_node_and_nvmrc.yml' workflow_dispatch: concurrency: @@ -14,12 +17,13 @@ concurrency: env: CARGO_TERM_COLOR: always + ENVIRONMENT: development GH_TOKEN: ${{ github.token }} - NODE_ENV: test jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -58,42 +62,30 @@ jobs: echo "******************************" echo "inputs:" "$INPUTS_CONTEXT" echo "******************************" - # Checkout the repo - - uses: actions/checkout@v3 - - - run: mkdir -p protocol/cargo-cache - - run: mkdir -p protocol/target - - run: mkdir -p node_modules - - run: mkdir -p ~/.cache/Cypress - - name: Restore cache - uses: actions/cache/restore@v3 - with: - path: | - protocol/cargo-cache - protocol/target - node_modules - ~/.cache/Cypress - # note that restoring a cache in github is a pain. The trailing '-' matches any string after the '-', therefore 'abc-' would match a cache named 'abc-1234' or 'abc-5678', etc. - # the problem is 'abc-' will not match a cache named 'abc'! So if you're using wildcard cache name selectors like this, you need a field that changes as the suffix to become the wildcard - # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` - key: some-unused-cache-key - restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version-file: '.nvmrc' - - name: Install npm - run: npm i -g npm@$(cat package.json | jq -r .engines.npm) + - name: Check contract version matches provider version + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # find all .nvmrc files except in node_modules and get the content + nvmrcs=$(find . -name '.nvmrc' -not -path '*/node_modules/*' -exec cat {} +) - - run: npm install + # check all .nvmrc files are the same content + if [ $(echo "$nvmrcs" | uniq | wc -l) -gt 1 ]; then + echo "ERROR: .nvmrc files are not consistent" + echo "$nvmrcs" + exit 1 + fi - # build all packages in workspace - - run: npm run build scripts - - run: npm run build:all:cjs + # check nvmrc version matches engine + engine=$(jq -r '.engines.node' package.json) - # bundle procaptcha-bundle using webpack - - name: Webpack Bundle procaptcha-bundle - run: | - npm run -w @prosopo/procaptcha-bundle bundle:dev:webpack + if [ "$engine" != "$(cat .nvmrc)" ]; then + echo "ERROR: .nvmrc version does not match engine" + echo "engine: $engine" + echo ".nvmrc: $(cat .nvmrc)" + exit 1 + fi + diff --git a/.github/workflows/consistent_workflow_names.yml b/.github/workflows/consistent_workflow_names.yml index b4836c90e1..2a3fba342f 100644 --- a/.github/workflows/consistent_workflow_names.yml +++ b/.github/workflows/consistent_workflow_names.yml @@ -1,10 +1,12 @@ +# Check workflow names are consistent with their filenames for easier debugging + name: consistent_workflow_names on: pull_request: - branches: [main] # only when workflow file is changed paths: ['.github/workflows/**'] + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -13,6 +15,7 @@ concurrency: jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -56,6 +59,8 @@ jobs: - name: Check workflow names run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + cd .github/workflows # Iterate through files in the current directory for file in *.yml *.yaml; do diff --git a/.github/workflows/contract_version.yml b/.github/workflows/contract_version.yml index 0c2f1c4cb5..c508a4ab14 100644 --- a/.github/workflows/contract_version.yml +++ b/.github/workflows/contract_version.yml @@ -1,8 +1,10 @@ +# Check the contract JS is in sync with the Rust version + name: contract_version on: pull_request: - branches: [main] + branches: [main, dev, release/*] paths: - '**/package.json' - '**/Cargo.toml' @@ -21,6 +23,7 @@ env: jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -64,13 +67,18 @@ jobs: - name: Check contract version matches provider version run: | - set -eu - provider=$(cat packages/provider/package.json | jq -r '.version') - find protocol/target/ink/*/ -name "Cargo.toml" | while read line; do - contract=$(cat $line | grep -m 1 "version = " | cut -d '"' -f 2) - echo "checking version in $line" - if [[ "$contract" != "$provider" ]]; then - echo "version mismatch: $contract != $provider" - exit 1 - fi - done + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # get the version of the contract in js pkg + for contract in contracts/*; do + echo "checking version in $contract" + jsVer=$(cat $contract/package.json | jq -r .version) + echo "js version: $jsVer" + # get the version of the contract in rust pkg + # assuming the contract version is the first version line in Cargo.toml + rustVer=$(cat protocol/contracts/$contract/Cargo.toml | grep -m 1 "version = " | cut -d '"' -f 2) + if [[ "$jsVer" != "$rustVer" ]]; then + echo "version mismatch: $jsVer != $rustVer" + exit 1 + fi + done diff --git a/.github/workflows/create_diagram.yml b/.github/workflows/create_diagram.yml deleted file mode 100644 index b5f0ec24b9..0000000000 --- a/.github/workflows/create_diagram.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: create_diagram -on: - workflow_dispatch: {} - pull_request: - branches: - - main -jobs: - get_data: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: githubocto/repo-visualizer@main - with: - branch: repo-diagram diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index 960a175b6c..b6936c4504 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -1,15 +1,10 @@ +# Run cypress tests + name: cypress on: pull_request: - branches: [main] - paths: - - 'docker/**' - - 'packages/**' - - 'demos/**' - - 'dev/**' - - 'contracts/**' - - '.github/workflows/tests.yml' + branches: [main, dev, release/*] workflow_dispatch: concurrency: @@ -24,6 +19,7 @@ env: jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -73,6 +69,7 @@ jobs: - name: Restore cache uses: actions/cache/restore@v3 with: + # must restore all cache dirs, and they must exist ahead of this! path: | protocol/cargo-cache protocol/target @@ -83,7 +80,7 @@ jobs: # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` key: some-unused-cache-key restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- - uses: actions/setup-node@v3 with: @@ -97,6 +94,8 @@ jobs: - name: Setup env run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + cp demos/client-example-server/env.development demos/client-example-server/.env.test cp demos/client-example/env.development demos/client-example/.env.test cp dev/scripts/env.test .env.test @@ -120,10 +119,6 @@ jobs: # by the cypress tests to find the elements they need to interact with - run: NODE_ENV=test npm -w @prosopo/procaptcha-bundle run bundle:dev - # Needs concurrently to avoid vite hanging forever https://github.com/vitejs/vite/discussions/8745 - - name: Install concurrently and cypress - run: npm i concurrently cypress - - name: Run the cypress tests on client-example run: | npx concurrently "npm run start:server" "npm run start:provider" "npm run start:demo" "sleep 10s && npm -w @prosopo/cypress-shared run cypress:run:client-example" --success "first" --kill-others diff --git a/.github/workflows/dependent_issues.yml b/.github/workflows/dependent_issues.yml index 12500011aa..838cea55d6 100644 --- a/.github/workflows/dependent_issues.yml +++ b/.github/workflows/dependent_issues.yml @@ -1,3 +1,5 @@ +# Check for dependent issues and pull requests in GitHub repositories. + name: dependent_issues on: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000..3f200f1f11 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,271 @@ +# Publish / release / deploy packages after a release + +name: deploy + +on: + push: + branches: [ main ] + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Print contexts + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + ENV_CONTEXT: ${{ toJson(env) }} + VARS_CONTEXT: ${{ toJson(vars) }} + JOB_CONTEXT: ${{ toJson(job) }} + STEPS_CONTEXT: ${{ toJson(steps) }} + RUNNER_CONTEXT: ${{ toJson(runner) }} + SECRETS_CONTEXT: ${{ toJson(secrets) }} + STRATEGY_CONTEXT: ${{ toJson(strategy) }} + MATRIX_CONTEXT: ${{ toJson(matrix) }} + NEEDS_CONTEXT: ${{ toJson(needs) }} + INPUTS_CONTEXT: ${{ toJson(inputs) }} + run: | + echo "******************************" + echo "github:" "$GITHUB_CONTEXT" + echo "******************************" + echo "env:" "$ENV_CONTEXT" + echo "******************************" + echo "vars:" "$VARS_CONTEXT" + echo "******************************" + echo "job:" "$JOB_CONTEXT" + echo "******************************" + echo "steps:" "$STEPS_CONTEXT" + echo "******************************" + echo "runner:" "$RUNNER_CONTEXT" + echo "******************************" + echo "secrets:" "$SECRETS_CONTEXT" + echo "******************************" + echo "strategy:" "$STRATEGY_CONTEXT" + echo "******************************" + echo "matrix:" "$MATRIX_CONTEXT" + echo "******************************" + echo "needs:" "$NEEDS_CONTEXT" + echo "******************************" + echo "inputs:" "$INPUTS_CONTEXT" + echo "******************************" + + # Add support for more platforms with QEMU (optional) + # https://github.com/docker/setup-qemu-action + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Dockerhub login + run: | + echo "Logging into Docker Hub." + echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin 2> /dev/null + + - uses: actions/checkout@v3 + + - name: Next version + id: next_version + run: | + + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + VERSION=$(cat package.json | jq -r '.version') + + # if version not detected, error + if [[ -z "$VERSION" ]]; then + echo "Failed to get version" + exit 1 + fi + # or if version null + if [[ "$VERSION" == "null" ]]; then + echo "Failed to get version" + exit 1 + fi + + # split into major, minor, patch + MAJOR=$(echo $VERSION | cut -d. -f1) + MINOR=$(echo $VERSION | cut -d. -f2) + PATCH=$(echo $VERSION | cut -d. -f3) + echo "version=$VERSION" + echo "major=$MAJOR" + echo "minor=$MINOR" + echo "patch=$PATCH" + + # export the next version numbers + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "major=$MAJOR" >> $GITHUB_OUTPUT + echo "minor=$MINOR" >> $GITHUB_OUTPUT + echo "patch=$PATCH" >> $GITHUB_OUTPUT + + - uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' + - run: npm i -g npm@$(cat package.json | jq -r .engines.npm) + + - run: npm ci + + # build from scratch to ensure nothing bought over from cache + + - name: Build packages + run: | + echo "Building packages..." + npm run build:all + npm run build:all:cjs + + - name: Build the contract sources + run: npm -w @prosopo/protocol run build:contracts + + - name: Build JS bundle + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # Copy the rococo env file to production env file + echo "Copying the rococo env to production env file in procaptcha-bundle" + cp ./dev/scripts/env.production ./packages/procaptcha-bundle/.env.production + + # Navigate to the JS bundle directory and build + echo "Navigating to 'packages/procaptcha-bundle' and building JS bundle..." + cd packages/procaptcha-bundle + + NODE_ENV=production npm run bundle:prod + + - name: Build docker js_server + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # technically, if the release is for a version which is less than a published version, the following code will have bundles from versions ahead of this one. However, this isn't really a problem, as we just want the latest bundle to be available alongside old ones, not so bothered about newer ones. + + # Set the JS location in the container + JS_FOLDER="/usr/share/nginx/html/js" + + # Get the most recent version of the js_server image + docker pull prosopo/js_server:latest + + # Create a temporary container from the latest image + echo "Building Docker image..." + OLD_CONTAINER_ID=$(docker create prosopo/js_server:$VERSION) + + # Remove the old js temp folder + rm -rf ./js_bundles_host_temp + + # Copy out the old files + docker cp $OLD_CONTAINER_ID:$JS_FOLDER ./js_bundles_host_temp + + # Build the new image + docker build --file ./docker/images/js.server.dockerfile . -t prosopo/js_server:${{ steps.next_version.outputs.version }} --no-cache + + # Run the new image + NEW_CONTAINER_ID=$(docker create prosopo/js_server:${{ steps.next_version.outputs.version }}) + + # Copy the legacy files across + docker cp ./js_bundles_host_temp/ $NEW_CONTAINER_ID:$JS_FOLDER/ + + # Copy the new bundle files to the container into a folder with the version name + docker cp packages/procaptcha-bundle/dist/bundle/. $NEW_CONTAINER_ID:$JS_FOLDER + + # Start the new container + docker start $NEW_CONTAINER_ID + + # Move procaptcha.bundle.js + docker exec $NEW_CONTAINER_ID mv $JS_FOLDER/procaptcha.bundle.js $JS_FOLDER/procaptcha.bundle.${{ steps.next_version.outputs.version }}.js + + # Symlink JS_FOLDER/procaptcha.bundle.js to JS_FOLDER/procaptcha.bundle.VERSION.js + docker exec $NEW_CONTAINER_ID ln -sf $JS_FOLDER/procaptcha.bundle.${{ steps.next_version.outputs.version }}.js $JS_FOLDER/procaptcha.bundle.js + + # Commit the changes to the container + docker commit $NEW_CONTAINER_ID prosopo/js_server:${{ steps.next_version.outputs.version }} + + # Check this new docker image works locally + docker run -d -p 3080:80 prosopo/js_server:${{ steps.next_version.outputs.version }} + + # Start the bundle demo & run the cypress tests against the new bundle + # npx concurrently "npm run start:bundle" "npm run -w @prosopo/cypress-shared cypress:run:client-bundle-example:js_server" --success "first" --kill-others + + - name: Build the production CLI package + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + echo "Building the production CLI package..." + # Copy the rococo env file to production env file + echo "Copying the rococo env to production env file in cli package" + cp ./dev/scripts/env.production ./packages/cli/.env.production + + # Navigate to the provider CLI directory and build + echo "Navigating to 'packages/cli' and bundling..." + cd packages/cli + NODE_ENV=production npm run build + NODE_ENV=production npm run bundle:prod + + # Navigate back to the project root + echo "Navigating back to project root..." + cd ../.. + + # this will error if there's already a release for this version. This is by design, if you need to fix a release (e.g. because a deploy failed) then bump the version and try again + - name: Github release + id: github_release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # do a gh release with the contract sources + bundle + gh release create --generate-notes "v${{ steps.next_version.outputs.version }}" "./protocol/target/ink/captcha/captcha.contract" "./protocol/target/ink/proxy/proxy.contract" "./protocol/target/ink/common/common.contract" "./packages/procaptcha-bundle/dist/bundle/procaptcha.bundle.js" + + - name: Npm release + run: | + if [[ "${{ vars.HOST_GITHUB_ACTIONS }}" == true ]]; then + echo "Running on GitHub Actions" + # Write the npm token to ~/.npmrc + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc + echo "Publishing to npm dry-run..." + npm run publish:dry-run + echo "Publishing to npm..." + npm run publish + else + echo "Running locally via act, skipping npm publish." + fi + + - name: Docker js_server release + id: docker_js_server_release + run: | + # Push the new image to Docker Hub + echo "Pushing Docker image..." + docker push prosopo/js_server:${{ steps.next_version.outputs.version }} + + # Push latest + docker tag prosopo/js_server:${{ steps.next_version.outputs.version }} prosopo/js_server:latest + docker push prosopo/js_server:latest + + - name: Redeploy flux docker js_server + env: + PROSOPO_ZELCORE_PRIVATE_KEY: ${{ secrets.PROSOPO_ZELCORE_PRIVATE_KEY }} + PROSOPO_ZELCORE_PUBLIC_KEY: ${{ secrets.PROSOPO_ZELCORE_PUBLIC_KEY }} + run: | + if [[ "${{ steps.docker_js_server_release.outcome }}" == 'success' ]]; then + echo "Installing @prosopo/flux..." + npm i -g @prosopo/flux + echo "Soft redeploying flux docker js_server." + npx flux redeploy --app ProcaptchaJavascriptServer + else + echo "Skipping flux redeploy." + fi + + - name: Build and push the Provider Container + uses: docker/build-push-action@v5 + with: + context: ${{github.workspace}} + file: ${{github.workspace}}/docker/images/provider.dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: prosopo/provider:${{ steps.next_version.outputs.version }},prosopo/provider:latest + + - name: Deploy fail notification + if: failure() + run: | + echo "Deploy failed" + curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-failed: Deploy <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> failed.\"}" ${{ secrets.SLACKBOT_DEVOPS }} + + - name: Deploy success notification + if: success() + run: | + echo "Deploy succeeded" + curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-passed: Deploy <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> succeeded.\"}" ${{ secrets.SLACKBOT_DEVOPS }} diff --git a/.github/workflows/event_dev_push.yml b/.github/workflows/event_dev_push.yml new file mode 100644 index 0000000000..1e8b615ff6 --- /dev/null +++ b/.github/workflows/event_dev_push.yml @@ -0,0 +1,69 @@ +# Send an event to other repos on push to main + +name: event_dev_push + +on: + push: + branches: [dev] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + ENVIRONMENT: development + GH_TOKEN: ${{ github.token }} + +jobs: + event: + runs-on: ubuntu-latest + steps: + - name: Print contexts + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + ENV_CONTEXT: ${{ toJson(env) }} + VARS_CONTEXT: ${{ toJson(vars) }} + JOB_CONTEXT: ${{ toJson(job) }} + STEPS_CONTEXT: ${{ toJson(steps) }} + RUNNER_CONTEXT: ${{ toJson(runner) }} + SECRETS_CONTEXT: ${{ toJson(secrets) }} + STRATEGY_CONTEXT: ${{ toJson(strategy) }} + MATRIX_CONTEXT: ${{ toJson(matrix) }} + NEEDS_CONTEXT: ${{ toJson(needs) }} + INPUTS_CONTEXT: ${{ toJson(inputs) }} + run: | + echo "******************************" + echo "github:" "$GITHUB_CONTEXT" + echo "******************************" + echo "env:" "$ENV_CONTEXT" + echo "******************************" + echo "vars:" "$VARS_CONTEXT" + echo "******************************" + echo "job:" "$JOB_CONTEXT" + echo "******************************" + echo "steps:" "$STEPS_CONTEXT" + echo "******************************" + echo "runner:" "$RUNNER_CONTEXT" + echo "******************************" + echo "secrets:" "$SECRETS_CONTEXT" + echo "******************************" + echo "strategy:" "$STRATEGY_CONTEXT" + echo "******************************" + echo "matrix:" "$MATRIX_CONTEXT" + echo "******************************" + echo "needs:" "$NEEDS_CONTEXT" + echo "******************************" + echo "inputs:" "$INPUTS_CONTEXT" + echo "******************************" + + - name: Send event + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + curl -X POST \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.everest-preview+json" \ + -d '{"event_type": "captcha_dev_push"}' \ + https://api.github.com/repos/prosopo/captcha-private/dispatches diff --git a/.github/workflows/event_main_push.yml b/.github/workflows/event_main_push.yml new file mode 100644 index 0000000000..de28beaa14 --- /dev/null +++ b/.github/workflows/event_main_push.yml @@ -0,0 +1,69 @@ +# Send an event to other repos on push to main + +name: event_main_push + +on: + push: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + ENVIRONMENT: development + GH_TOKEN: ${{ github.token }} + +jobs: + event: + runs-on: ubuntu-latest + steps: + - name: Print contexts + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + ENV_CONTEXT: ${{ toJson(env) }} + VARS_CONTEXT: ${{ toJson(vars) }} + JOB_CONTEXT: ${{ toJson(job) }} + STEPS_CONTEXT: ${{ toJson(steps) }} + RUNNER_CONTEXT: ${{ toJson(runner) }} + SECRETS_CONTEXT: ${{ toJson(secrets) }} + STRATEGY_CONTEXT: ${{ toJson(strategy) }} + MATRIX_CONTEXT: ${{ toJson(matrix) }} + NEEDS_CONTEXT: ${{ toJson(needs) }} + INPUTS_CONTEXT: ${{ toJson(inputs) }} + run: | + echo "******************************" + echo "github:" "$GITHUB_CONTEXT" + echo "******************************" + echo "env:" "$ENV_CONTEXT" + echo "******************************" + echo "vars:" "$VARS_CONTEXT" + echo "******************************" + echo "job:" "$JOB_CONTEXT" + echo "******************************" + echo "steps:" "$STEPS_CONTEXT" + echo "******************************" + echo "runner:" "$RUNNER_CONTEXT" + echo "******************************" + echo "secrets:" "$SECRETS_CONTEXT" + echo "******************************" + echo "strategy:" "$STRATEGY_CONTEXT" + echo "******************************" + echo "matrix:" "$MATRIX_CONTEXT" + echo "******************************" + echo "needs:" "$NEEDS_CONTEXT" + echo "******************************" + echo "inputs:" "$INPUTS_CONTEXT" + echo "******************************" + + - name: Send event + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + curl -X POST \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.everest-preview+json" \ + -d '{"event_type": "captcha_main_push"}' \ + https://api.github.com/repos/prosopo/captcha-private/dispatches diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a52991d482..a70d12f218 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,8 +1,10 @@ +# Lint the codebase + name: lint on: pull_request: - branches: [main] + branches: [main, dev, release/*] workflow_dispatch: concurrency: @@ -18,6 +20,7 @@ jobs: check: name: check runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -67,6 +70,7 @@ jobs: - name: Restore cache uses: actions/cache/restore@v3 with: + # must restore all cache dirs, and they must exist ahead of this! path: | protocol/cargo-cache protocol/target @@ -77,7 +81,7 @@ jobs: # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` key: some-unused-cache-key restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- - uses: actions/setup-node@v3 with: @@ -90,6 +94,8 @@ jobs: - name: lint run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + # get the files which have changed in the PR files=$(curl -L -s -H "Authorization: Bearer ${{ github.token }}" -H "Accept: application/vnd.github.v3+json" "${{ github.event.pull_request.url }}/files" | jq -r '.[] | .filename') diff --git a/.github/workflows/lockstep_version.yml b/.github/workflows/lockstep_version.yml new file mode 100644 index 0000000000..913399f681 --- /dev/null +++ b/.github/workflows/lockstep_version.yml @@ -0,0 +1,89 @@ +# Workflow to check all versions of packages are the same, ensuring we move in lockstep. +# We made the decision to move in lockstep for greater dev speed at the detriment of more frequent version bumps than necessary to some packages. +# Lockstep versioning is simpler and doesn't require backwards compatibility headaches. + +name: lockstep_version + +on: + pull_request: + branches: [main, dev, release/*] + paths: + - '**/package.json' + - '**/Cargo.toml' + - '.github/workflows/lockstep_version.yml' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + ENVIRONMENT: development + GH_TOKEN: ${{ github.token }} + +jobs: + check: + runs-on: ubuntu-latest + if: github.event.pull_request.draft == false + steps: + - name: Print contexts + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + ENV_CONTEXT: ${{ toJson(env) }} + VARS_CONTEXT: ${{ toJson(vars) }} + JOB_CONTEXT: ${{ toJson(job) }} + STEPS_CONTEXT: ${{ toJson(steps) }} + RUNNER_CONTEXT: ${{ toJson(runner) }} + SECRETS_CONTEXT: ${{ toJson(secrets) }} + STRATEGY_CONTEXT: ${{ toJson(strategy) }} + MATRIX_CONTEXT: ${{ toJson(matrix) }} + NEEDS_CONTEXT: ${{ toJson(needs) }} + INPUTS_CONTEXT: ${{ toJson(inputs) }} + run: | + echo "******************************" + echo "github:" "$GITHUB_CONTEXT" + echo "******************************" + echo "env:" "$ENV_CONTEXT" + echo "******************************" + echo "vars:" "$VARS_CONTEXT" + echo "******************************" + echo "job:" "$JOB_CONTEXT" + echo "******************************" + echo "steps:" "$STEPS_CONTEXT" + echo "******************************" + echo "runner:" "$RUNNER_CONTEXT" + echo "******************************" + echo "secrets:" "$SECRETS_CONTEXT" + echo "******************************" + echo "strategy:" "$STRATEGY_CONTEXT" + echo "******************************" + echo "matrix:" "$MATRIX_CONTEXT" + echo "******************************" + echo "needs:" "$NEEDS_CONTEXT" + echo "******************************" + echo "inputs:" "$INPUTS_CONTEXT" + echo "******************************" + + - uses: actions/checkout@v3 + + - name: Check package versions are all moving in lockstep + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # find all package.json files, recursively + pkgJsons=$(find . -name package.json -prune -not -path '*/node_modules/*' -not -path '*/.next/*') + # extract version from package.json files + jsVers=$(xargs -I % sh -c "jq -r '.version' %" <<< "$pkgJsons") + + # find all Cargo.toml files + cargoTomls=$(find . -name Cargo.toml -prune -not -path '*/protocol/cargo-cache/*') + # extract the version out of all Cargo.toml files (we're assuming the version is the first version line encountered) + rustVers=$(xargs -I % sh -c "grep -m 1 'version' % | awk -F'\"' '{print \$2}'" <<< "$cargoTomls") + + # compare all versions detected, if they are not all the same, fail the workflow + vers=$(echo "$jsVers $rustVers" | tr ' ' '\n') + if [[ $(echo "$vers" | uniq | wc -l) -ne 1 ]]; then + echo "versions are not all the same: $vers" + exit 1 + fi diff --git a/.github/workflows/ls_cache.yml b/.github/workflows/ls_cache.yml index 65fed666a5..766a71bf38 100644 --- a/.github/workflows/ls_cache.yml +++ b/.github/workflows/ls_cache.yml @@ -1,3 +1,5 @@ +# This workflow will list the contents of the cache directories, useful for debugging cache issues. + name: ls_cache on: @@ -63,6 +65,7 @@ jobs: - name: Restore cache uses: actions/cache/restore@v3 with: + # must restore all cache dirs, and they must exist ahead of this! path: | protocol/cargo-cache protocol/target @@ -73,7 +76,7 @@ jobs: # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` key: some-unused-cache-key restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- - run: ls -la ~/.cache/Cypress || true - run: ls -la protocol/cargo-cache || true diff --git a/.github/workflows/prosoponator_bot.yml b/.github/workflows/prosoponator_bot.yml index d8486fced7..8f647257cf 100644 --- a/.github/workflows/prosoponator_bot.yml +++ b/.github/workflows/prosoponator_bot.yml @@ -1,3 +1,5 @@ +# Run prosoponator bot on any comments + name: prosoponator_bot on: issue_comment diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/protocol_lint.yml similarity index 87% rename from .github/workflows/rustfmt.yml rename to .github/workflows/protocol_lint.yml index c7b5917b13..cb94b6a865 100644 --- a/.github/workflows/rustfmt.yml +++ b/.github/workflows/protocol_lint.yml @@ -1,11 +1,13 @@ -name: rustfmt +# This workflow will run linting on the protocol workspace + +name: protocol_lint on: pull_request: - branches: [main] + branches: [main, dev, release/*] paths: - - '**.rs' - - '.github/workflows/rustfmt.yml' + - 'protocol/**' + - '.github/workflows/protocol_clippy.yml' workflow_dispatch: concurrency: @@ -20,6 +22,7 @@ env: jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -69,6 +72,7 @@ jobs: - name: Restore cache uses: actions/cache/restore@v3 with: + # must restore all cache dirs, and they must exist ahead of this! path: | protocol/cargo-cache protocol/target @@ -79,7 +83,7 @@ jobs: # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` key: some-unused-cache-key restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- - uses: actions/setup-node@v3 with: @@ -89,3 +93,5 @@ jobs: - run: npm ci - run: npm -w @prosopo/protocol run rustfmt + + - run: npm -w @prosopo/protocol run clippy diff --git a/.github/workflows/clippy.yml b/.github/workflows/protocol_tests.yml similarity index 85% rename from .github/workflows/clippy.yml rename to .github/workflows/protocol_tests.yml index 1cb08796e4..2ad541706c 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/protocol_tests.yml @@ -1,11 +1,13 @@ -name: clippy +# Run the protocol workspace tests + +name: protocol_tests on: pull_request: - branches: [main] + branches: [main, dev, release/*] paths: - - '**.rs' - - '.github/workflows/clippy.yml' + - 'protocol/**' + - '.github/workflows/protocol_tests.yml' workflow_dispatch: concurrency: @@ -14,12 +16,13 @@ concurrency: env: CARGO_TERM_COLOR: always - ENVIRONMENT: development GH_TOKEN: ${{ github.token }} + NODE_ENV: test jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -69,6 +72,7 @@ jobs: - name: Restore cache uses: actions/cache/restore@v3 with: + # must restore all cache dirs, and they must exist ahead of this! path: | protocol/cargo-cache protocol/target @@ -79,7 +83,7 @@ jobs: # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` key: some-unused-cache-key restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- - uses: actions/setup-node@v3 with: @@ -88,4 +92,6 @@ jobs: - run: npm ci - - run: npm -w @prosopo/protocol run clippy + - run: npm -w @prosopo/protocol run build:all + + - run: npm -w @prosopo/protocol run test:all diff --git a/.github/workflows/provider_image.yml b/.github/workflows/provider_image.yml index 60f67cd133..bd50f455f2 100644 --- a/.github/workflows/provider_image.yml +++ b/.github/workflows/provider_image.yml @@ -1,14 +1,10 @@ +# Build and publish the provider image + name: provider_image on: pull_request: - branches: [main] - paths: - - 'docker/**' - - 'dev/**' - - 'packages/**' - - 'contracts/**' - - '.github/workflows/provider_image.yml' + branches: [main, dev, release/*] workflow_dispatch: concurrency: @@ -22,6 +18,7 @@ env: jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -71,6 +68,7 @@ jobs: - name: Restore cache uses: actions/cache/restore@v3 with: + # must restore all cache dirs, and they must exist ahead of this! path: | protocol/cargo-cache protocol/target @@ -81,7 +79,7 @@ jobs: # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` key: some-unused-cache-key restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- - uses: actions/setup-node@v3 with: @@ -99,6 +97,8 @@ jobs: # build the cli production bundle - name: Build cli production bundle run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + cp ./dev/scripts/env.production ./packages/cli/.env.production cp ./dev/scripts/env.production ./.env.production NODE_ENV=production npm run -w @prosopo/cli bundle:prod @@ -152,6 +152,8 @@ jobs: # Check that the version command works when running the bundle in the provider image - name: Check provider bundle runs run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + CONTAINER=$(docker run -d -v "./.env.production:/usr/src/app/.env.production" prosopo/provider:dev /bin/sh -c 'NODE_ENV=production npx provider version') sleep 20s docker logs $CONTAINER >& provider.log diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index b4ee52c08b..0000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,584 +0,0 @@ -name: publish - -on: - push: - # only on the main branch - branches: - - main - paths: - # only when the package.json file changes - - 'package.json' - # or run manually - workflow_dispatch: - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - name: Print contexts - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - ENV_CONTEXT: ${{ toJson(env) }} - VARS_CONTEXT: ${{ toJson(vars) }} - JOB_CONTEXT: ${{ toJson(job) }} - STEPS_CONTEXT: ${{ toJson(steps) }} - RUNNER_CONTEXT: ${{ toJson(runner) }} - SECRETS_CONTEXT: ${{ toJson(secrets) }} - STRATEGY_CONTEXT: ${{ toJson(strategy) }} - MATRIX_CONTEXT: ${{ toJson(matrix) }} - NEEDS_CONTEXT: ${{ toJson(needs) }} - INPUTS_CONTEXT: ${{ toJson(inputs) }} - run: | - echo "******************************" - echo "github:" "$GITHUB_CONTEXT" - echo "******************************" - echo "env:" "$ENV_CONTEXT" - echo "******************************" - echo "vars:" "$VARS_CONTEXT" - echo "******************************" - echo "job:" "$JOB_CONTEXT" - echo "******************************" - echo "steps:" "$STEPS_CONTEXT" - echo "******************************" - echo "runner:" "$RUNNER_CONTEXT" - echo "******************************" - echo "secrets:" "$SECRETS_CONTEXT" - echo "******************************" - echo "strategy:" "$STRATEGY_CONTEXT" - echo "******************************" - echo "matrix:" "$MATRIX_CONTEXT" - echo "******************************" - echo "needs:" "$NEEDS_CONTEXT" - echo "******************************" - echo "inputs:" "$INPUTS_CONTEXT" - echo "******************************" - - - uses: actions/checkout@v3 - with: - # fetch all history + branches - fetch-depth: 0 - - - name: Dockerhub login - run: | - echo "Logging into Docker Hub." - echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin 2> /dev/null - - # fail-fast step to check if the version has been bumped - # when running manually, there won't be a version line change, so we need to skip this step in that case - - name: Detect version bump - id: next_version - run: | - if [[ "${{ github.event_name }}" == 'workflow_dispatch' ]]; then - echo "manual run, skipping version check" - exit 0 - fi - - # use git to look for differences in package.json between the before and after state - # before and after git sha's are passed in as env vars by github - diff=$(git show --pretty=format: --no-notes ${{ github.event.before }}..${{ github.event.after }} -- package.json | cat) - echo "diff:" - echo "$diff" - echo "" - - # grep for the version line - version_changes=$(echo "$diff" | grep -e "[-\+]\s*\"version\"" || true) - echo "version_changes:" - echo "$version_changes" - echo "" - - # if the version line has changed then we know there's been a version change. Not necessarily bumped up, though! - # the next version will be whatever is currently in the package.json file - # subsequent steps can choose whether the version has been bumped or not. All we know at this stage is the version has been changed, i.e. new_version != old_version, but we don't know whether new_version > old_version or new_version < old_version - if [[ -n "$version_changes" ]]; then - echo "version has changed" - echo "bump=true" >> $GITHUB_OUTPUT - else - echo "version has not changed" - # skip remaining steps which bump the version - echo "bump=false" >> $GITHUB_OUTPUT - exit 0 - fi - - VERSION=$(cat package.json | jq -r '.version' || echo "0.0.0") - # split into major, minor, patch - MAJOR=$(echo $VERSION | cut -d. -f1) - MINOR=$(echo $VERSION | cut -d. -f2) - PATCH=$(echo $VERSION | cut -d. -f3) - echo "version=$VERSION" - echo "major=$MAJOR" - echo "minor=$MINOR" - echo "patch=$PATCH" - - # export the next version numbers - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "major=$MAJOR" >> $GITHUB_OUTPUT - echo "minor=$MINOR" >> $GITHUB_OUTPUT - echo "patch=$PATCH" >> $GITHUB_OUTPUT - - # check for version bump against github release - - name: Check version github - id: check_version_github - if: steps.next_version.outputs.bump == 'true' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # get the current version number from latest release on gh - VERSION=$(gh release list --limit 1 | awk '{print $1}' | tr -d v) - - if [[ -z "$VERSION" ]]; then - echo "Failed to get current version" - exit 1 - fi - - MAJOR=$(echo $VERSION | cut -d. -f1) - MINOR=$(echo $VERSION | cut -d. -f2) - PATCH=$(echo $VERSION | cut -d. -f3) - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "major=$MAJOR" >> $GITHUB_OUTPUT - echo "minor=$MINOR" >> $GITHUB_OUTPUT - echo "patch=$PATCH" >> $GITHUB_OUTPUT - echo "version: $VERSION" - - if [[ "${{ steps.next_version.outputs.major }}" -gt "$MAJOR" ]]; then - echo "major version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.minor }}" -gt "$MINOR" ]]; then - echo "minor version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.patch }}" -gt "$PATCH" ]]; then - echo "patch version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - else - echo "no version bump detected" - echo "bump=false" >> $GITHUB_OUTPUT - fi - - - name: Check version npm - id: check_version_npm - if: steps.next_version.outputs.bump == 'true' - run: | - # get the current version number from latest release on npm (use procaptcha as the baseline, as workspace package is not published) - VERSION=$(npm view @prosopo/procaptcha version) - - if [[ -z "$VERSION" ]]; then - echo "Failed to get current version" - exit 1 - fi - - MAJOR=$(echo $VERSION | cut -d. -f1) - MINOR=$(echo $VERSION | cut -d. -f2) - PATCH=$(echo $VERSION | cut -d. -f3) - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "major=$MAJOR" >> $GITHUB_OUTPUT - echo "minor=$MINOR" >> $GITHUB_OUTPUT - echo "patch=$PATCH" >> $GITHUB_OUTPUT - echo "version: $VERSION" - - if [[ "${{ steps.next_version.outputs.major }}" -gt "$MAJOR" ]]; then - echo "major version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.minor }}" -gt "$MINOR" ]]; then - echo "minor version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.patch }}" -gt "$PATCH" ]]; then - echo "patch version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - else - echo "no version bump detected" - echo "bump=false" >> $GITHUB_OUTPUT - fi - - - name: Check version docker js_server - id: check_version_docker_js_server - if: steps.next_version.outputs.bump == 'true' - run: | - # get the current version number from latest release on docker - VERSION=$(curl -L -s 'https://registry.hub.docker.com/v2/repositories/prosopo/js_server/tags/' | jq ".results[].name" | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+" | head -n 1) - - if [[ -z "$VERSION" ]]; then - echo "Failed to get current version" - exit 1 - fi - - MAJOR=$(echo $VERSION | cut -d. -f1) - MINOR=$(echo $VERSION | cut -d. -f2) - PATCH=$(echo $VERSION | cut -d. -f3) - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "major=$MAJOR" >> $GITHUB_OUTPUT - echo "minor=$MINOR" >> $GITHUB_OUTPUT - echo "patch=$PATCH" >> $GITHUB_OUTPUT - echo "version: $VERSION" - - if [[ "${{ steps.next_version.outputs.major }}" -gt "$MAJOR" ]]; then - echo "major version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.minor }}" -gt "$MINOR" ]]; then - echo "minor version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.patch }}" -gt "$PATCH" ]]; then - echo "patch version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - else - echo "no version bump detected" - echo "bump=false" >> $GITHUB_OUTPUT - fi - - - name: Check version docker provider - id: check_version_docker_provider - if: steps.next_version.outputs.bump == 'true' - run: | - # get the current version number from latest release on docker - VERSION=$(curl -L -s 'https://registry.hub.docker.com/v2/repositories/prosopo/provider/tags/' | jq ".results[].name" | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+" | head -n 1) - - if [[ -z "$VERSION" ]]; then - echo "Failed to get current version" - exit 1 - fi - - MAJOR=$(echo $VERSION | cut -d. -f1) - MINOR=$(echo $VERSION | cut -d. -f2) - PATCH=$(echo $VERSION | cut -d. -f3) - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "major=$MAJOR" >> $GITHUB_OUTPUT - echo "minor=$MINOR" >> $GITHUB_OUTPUT - echo "patch=$PATCH" >> $GITHUB_OUTPUT - echo "version: $VERSION" - - if [[ "${{ steps.next_version.outputs.major }}" -gt "$MAJOR" ]]; then - echo "major version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.minor }}" -gt "$MINOR" ]]; then - echo "minor version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - elif [[ "${{ steps.next_version.outputs.patch }}" -gt "$PATCH" ]]; then - echo "patch version bump detected" - echo "bump=true" >> $GITHUB_OUTPUT - else - echo "no version bump detected" - echo "bump=false" >> $GITHUB_OUTPUT - fi - - - name: Should bump? - id: check_version_any - run: | - bump=false - # only bump if any of the version checks have detected a bump - if [[ "${{ steps.check_version_github.outputs.bump }}" == 'true' ]]; then - bump=true - echo "github bump required" - fi - if [[ "${{ steps.check_version_npm.outputs.bump }}" == 'true' ]]; then - bump=true - echo "npm bump required" - fi - if [[ "${{ steps.check_version_docker_js_server.outputs.bump }}" == 'true' ]]; then - bump=true - echo "docker js_server bump required" - fi - if [[ "${{ steps.check_version_docker_provider.outputs.bump }}" == 'true' ]]; then - bump=true - echo "docker provider bump required" - fi - if [[ "$bump" == 'true' ]]; then - echo "bump=true" >> $GITHUB_OUTPUT - echo "something needs bumping" - else - echo "bump=false" >> $GITHUB_OUTPUT - echo "nothing needs bumping" - fi - - # get the latest build from the cache produced in the post_pr workflow - - - run: mkdir -p protocol/cargo-cache - if: steps.check_version_any.outputs.bump == 'true' - - run: mkdir -p protocol/target - if: steps.check_version_any.outputs.bump == 'true' - - run: mkdir -p node_modules - if: steps.check_version_any.outputs.bump == 'true' - - run: mkdir -p ~/.cache/Cypress - if: steps.check_version_any.outputs.bump == 'true' - - - name: Restore cache - if: steps.check_version_any.outputs.bump == 'true' - uses: actions/cache/restore@v3 - with: - path: | - protocol/cargo-cache - protocol/target - node_modules - ~/.cache/Cypress - # note that restoring a cache in github is a pain. The trailing '-' matches any string after the '-', therefore 'abc-' would match a cache named 'abc-1234' or 'abc-5678', etc. - # the problem is 'abc-' will not match a cache named 'abc'! So if you're using wildcard cache name selectors like this, you need a field that changes as the suffix to become the wildcard - # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` - key: some-unused-cache-key - restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- - - - run: ls -la ~/.cache/Cypress || true - if: steps.check_version_any.outputs.bump == 'true' - - run: ls -la protocol/cargo-cache || true - if: steps.check_version_any.outputs.bump == 'true' - - run: ls -la protocol/target/ink || true - if: steps.check_version_any.outputs.bump == 'true' - - run: ls -la node_modules || true - if: steps.check_version_any.outputs.bump == 'true' - - - uses: actions/setup-node@v3 - if: steps.check_version_any.outputs.bump == 'true' - with: - node-version-file: '.nvmrc' - - run: npm i -g npm@$(cat package.json | jq -r .engines.npm) - if: steps.check_version_any.outputs.bump == 'true' - - - name: Install - if: steps.check_version_any.outputs.bump == 'true' - run: | - npm ci - - # at this point there should be a build in the cache, so we can begin building artifacts for the release - - - name: Build packages - if: steps.check_version_any.outputs.bump == 'true' - run: | - echo "Building packages..." - npm run build:all - npm run build:all:cjs - - - name: Build the contract sources - if: steps.check_version_any.outputs.bump == 'true' - run: npm -w @prosopo/protocol run build:contracts - - - name: Typedoc - run: | - npm run docs - - - name: Build JS bundle - if: steps.check_version_any.outputs.bump == 'true' - run: | - # Copy the rococo env file to production env file - echo "Copying the rococo env to production env file in procaptcha-bundle" - cp ./dev/scripts/env.production ./packages/procaptcha-bundle/.env.production - - # Navigate to the JS bundle directory and build - echo "Navigating to 'packages/procaptcha-bundle' and building JS bundle..." - cd packages/procaptcha-bundle - - NODE_ENV=production npm run bundle:prod - - - name: Build docker js_server - if: steps.check_version_any.outputs.bump == 'true' - run: | - # Set the JS location in the container - JS_FOLDER="/usr/share/nginx/html/js" - - # Get the most recent version of the js_server image - docker pull prosopo/js_server:${{ steps.check_version_docker_js_server.outputs.version }} - - # Create a temporary container from the latest image - echo "Building Docker image..." - OLD_CONTAINER_ID=$(docker create prosopo/js_server:${{ steps.check_version_docker_js_server.outputs.version }}) - - # Remove the old js temp folder - rm -rf ./js_bundles_host_temp - - # Copy out the old files - docker cp $OLD_CONTAINER_ID:$JS_FOLDER ./js_bundles_host_temp - - # Build the new image - docker build --file ./docker/images/js.server.dockerfile . -t prosopo/js_server:${{ steps.next_version.outputs.version }} --no-cache - - # Run the new image - NEW_CONTAINER_ID=$(docker create prosopo/js_server:${{ steps.next_version.outputs.version }}) - - # Copy the legacy files across - docker cp ./js_bundles_host_temp/ $NEW_CONTAINER_ID:$JS_FOLDER/ - - # Copy the new bundle files to the container into a folder with the version name - docker cp packages/procaptcha-bundle/dist/bundle/. $NEW_CONTAINER_ID:$JS_FOLDER - - # Start the new container - docker start $NEW_CONTAINER_ID - - # Move procaptcha.bundle.js - docker exec $NEW_CONTAINER_ID mv $JS_FOLDER/procaptcha.bundle.js $JS_FOLDER/procaptcha.bundle.${{ steps.next_version.outputs.version }}.js - - # Symlink JS_FOLDER/procaptcha.bundle.js to JS_FOLDER/procaptcha.bundle.VERSION.js - docker exec $NEW_CONTAINER_ID ln -sf $JS_FOLDER/procaptcha.bundle.${{ steps.next_version.outputs.version }}.js $JS_FOLDER/procaptcha.bundle.js - - # Commit the changes to the container - docker commit $NEW_CONTAINER_ID prosopo/js_server:${{ steps.next_version.outputs.version }} - - # Check this new docker image works locally - docker run -d -p 3080:80 prosopo/js_server:${{ steps.next_version.outputs.version }} - - # Start the bundle demo & run the cypress tests against the new bundle - # npx concurrently "npm run start:bundle" "npm run -w @prosopo/cypress-shared cypress:run:client-bundle-example:js_server" --success "first" --kill-others - - - name: Github release - continue-on-error: true - id: publish_github - if: steps.check_version_github.outputs.bump == 'true' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # do a gh release with the contract sources + bundle - gh release create --generate-notes "v${{ steps.next_version.outputs.version }}" "./protocol/target/ink/captcha/captcha.contract" "./protocol/target/ink/proxy/proxy.contract" "./protocol/target/ink/common/common.contract" "./packages/procaptcha-bundle/dist/bundle/procaptcha.bundle.js" - - - name: Github release notification - if: always() - run: | - if [[ "${{ steps.publish_github.outcome }}" == 'success' ]]; then - echo "Github release successful." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-passed: Github release has been published.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - elif [[ "${{ steps.publish_github.outcome }}" == 'failure' ]]; then - echo "Github release failed." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-failed: Github release <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> failed.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - else - echo "Github release skipped / cancelled." - fi - - - name: Npm release - continue-on-error: true - id: publish_release - if: steps.check_version_npm.outputs.bump == 'true' - run: | - if [[ "${{ vars.HOST_GITHUB_ACTIONS }}" == true ]]; then - echo "Running on GitHub Actions" - # Write the npm token to ~/.npmrc - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc - echo "Publishing to npm dry-run..." - npm run publish:dry-run - echo "Publishing to npm..." - npm run publish - else - echo "Running locally via act, skipping npm publish." - fi - - - name: Npm release notification - if: always() - run: | - if [[ "${{ steps.publish_release.outcome }}" == 'success' ]]; then - echo "Npm release successful." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-passed: Npm release has been published.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - elif [[ "${{ steps.publish_release.outcome }}" == 'failure' ]]; then - echo "Npm release failed." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-failed: Npm release <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> failed.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - else - echo "Npm release skipped / cancelled." - fi - - - name: Docker js_server release - continue-on-error: true - id: publish_docker_js_server - if: steps.check_version_docker_js_server.outputs.bump == 'true' - run: | - # Push the new image to Docker Hub - echo "Pushing Docker image..." - docker push prosopo/js_server:${{ steps.next_version.outputs.version }} - - # Push latest - docker tag prosopo/js_server:${{ steps.next_version.outputs.version }} prosopo/js_server:latest - docker push prosopo/js_server:latest - - - name: Docker js_server release notification - if: always() - run: | - if [[ "${{ steps.publish_docker_js_server.outcome }}" == 'success' ]]; then - echo "Docker js_server release successful." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-passed: Docker js_server release has been published.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - elif [[ "${{ steps.publish_docker_js_server.outcome }}" == 'failure' ]]; then - echo "Docker js_server release failed." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-failed: Docker js_server release <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> failed.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - else - echo "Docker js_server release skipped / cancelled." - fi - - - name: Redeploy flux docker js_server - id: redeploy_flux_docker_js_server - continue-on-error: true - if: always() - env: - PROSOPO_ZELCORE_PRIVATE_KEY: ${{ secrets.PROSOPO_ZELCORE_PRIVATE_KEY }} - PROSOPO_ZELCORE_PUBLIC_KEY: ${{ secrets.PROSOPO_ZELCORE_PUBLIC_KEY }} - run: | - if [[ "${{ steps.publish_docker_js_server.outcome }}" == 'success' ]]; then - echo "Installing @prosopo/flux..." - npm i -g @prosopo/flux - echo "Soft redeploying flux docker js_server." - npx flux redeploy --app ProcaptchaJavascriptServer - else - echo "Skipping flux redeploy." - fi - - - name: - if: always() - env: - PROSOPO_ZELCORE_PRIVATE_KEY: ${{ secrets.PROSOPO_ZELCORE_PRIVATE_KEY }} - PROSOPO_ZELCORE_PUBLIC_KEY: ${{ secrets.PROSOPO_ZELCORE_PUBLIC_KEY }} - run: | - if [[ "${{ steps.publish_docker_js_server.outcome }}" == 'success' ]]; then - if [[ "${{ steps.redeploy_flux_docker_js_server.outcome }}" == 'success' ]]; then - echo "Redeployed flux docker js_server." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-passed: Flux docker js_server redeploy <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> has been requested.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - elif [[ "${{ steps.redeploy_flux_docker_js_server.outcome }}" == 'failure' ]]; then - echo "Redeploying flux docker js_server failed." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-failed: Flux docker js_server redeploy <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> failed.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - else - echo "Redeploying flux docker js_server skipped / cancelled." - fi - else - echo "Skipping flux redeploy notification." - fi - - # Add support for more platforms with QEMU (optional) - # https://github.com/docker/setup-qemu-action - - name: Set up QEMU - if: steps.check_version_docker_js_server.outputs.bump == 'true' - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - if: steps.check_version_docker_js_server.outputs.bump == 'true' - uses: docker/setup-buildx-action@v3 - - - name: Build the production CLI package - if: steps.check_version_docker_js_server.outputs.bump == 'true' - run: | - echo "Building the production CLI package..." - # Copy the rococo env file to production env file - echo "Copying the rococo env to production env file in cli package" - cp ./dev/scripts/env.production ./packages/cli/.env.production - - # Navigate to the provider CLI directory and build - echo "Navigating to 'packages/cli' and bundling..." - cd packages/cli - NODE_ENV=production npm run build - NODE_ENV=production npm run bundle:prod - - # Navigate back to the project root - echo "Navigating back to project root..." - cd ../.. - - - name: Build and push the Provider Container - if: steps.check_version_docker_js_server.outputs.bump == 'true' - id: publish_docker_provider - continue-on-error: true - uses: docker/build-push-action@v5 - with: - context: ${{github.workspace}} - file: ${{github.workspace}}/docker/images/provider.dockerfile - platforms: linux/amd64,linux/arm64 - push: true - tags: prosopo/provider:${{ steps.next_version.outputs.version }},prosopo/provider:latest - - - name: Docker provider release notification - if: always() - run: | - if [[ "${{ steps.publish_docker_provider.outcome }}" == 'success' ]]; then - echo "Docker provider release successful." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-passed: Docker provider release has been published.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - elif [[ "${{ steps.publish_docker_provider.outcome }}" == 'failure' ]]; then - echo "Docker provider release failed." - curl -X POST -H 'Content-type: application/json' --data "{\"text\":\":check-failed: Docker provider release <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|v${{ steps.next_version.outputs.version }}> failed.\"}" ${{ secrets.SLACKBOT_DEVOPS }} - else - echo "Docker provider release skipped / cancelled." - fi diff --git a/.github/workflows/release_drafter.yml b/.github/workflows/release_drafter.yml deleted file mode 100644 index 9cc9990642..0000000000 --- a/.github/workflows/release_drafter.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: release_drafter - -on: - push: - # branches to consider in the event; optional, defaults to all - branches: - - main - # pull_request event is required only for autolabeler - pull_request: - # Only following types are handled by the action, but one can default to all as well - types: [opened, reopened, synchronize] - workflow_dispatch: - -permissions: - contents: read - -jobs: - update_release_draft: - permissions: - # write permission is required to create a github release - contents: write - # write permission is required for autolabeler - # otherwise, read permission is required at least - pull-requests: write - runs-on: ubuntu-latest - steps: - # (Optional) GitHub Enterprise requires GHE_HOST variable set - #- name: Set GHE_HOST - # run: | - # echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV - - # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v5 - # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml - # with: - # config-name: my-config.yml - # disable-autolabeler: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ced5235593..08c922933d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,15 +1,10 @@ +# Run tests for js packages + name: tests on: pull_request: - branches: [main] - paths: - - 'docker/**' - - 'packages/**' - - 'demos/**' - - 'dev/**' - - 'contracts/**' - - '.github/workflows/tests.yml' + branches: [main, dev, release/*] workflow_dispatch: concurrency: @@ -24,6 +19,7 @@ env: jobs: check: runs-on: ubuntu-latest + if: github.event.pull_request.draft == false steps: - name: Print contexts env: @@ -73,6 +69,7 @@ jobs: - name: Restore cache uses: actions/cache/restore@v3 with: + # must restore all cache dirs, and they must exist ahead of this! path: | protocol/cargo-cache protocol/target @@ -83,7 +80,7 @@ jobs: # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` key: some-unused-cache-key restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- + project-cache-${{ github.event.pull_request.head.ref || github.ref }}-${{ runner.os }}-${{ runner.arch }}- - uses: actions/setup-node@v3 with: @@ -96,8 +93,29 @@ jobs: - run: npm run build:all - run: npm run build:all:cjs + # bundle procaptcha-bundle using webpack + - name: Webpack Bundle procaptcha-bundle + run: | + npm run -w @prosopo/procaptcha-bundle bundle:dev:webpack + + - name: Build JS bundle + run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + + # Copy the rococo env file to production env file + echo "Copying the rococo env to production env file in procaptcha-bundle" + cp ./dev/scripts/env.production ./packages/procaptcha-bundle/.env.production + + # Navigate to the JS bundle directory and build + echo "Navigating to 'packages/procaptcha-bundle' and building JS bundle..." + cd packages/procaptcha-bundle + + NODE_ENV=production npm run bundle:prod + - name: Setup env run: | + set -euxo pipefail # stop on errors, print commands, fail on pipe fails + cp demos/client-example-server/env.development demos/client-example-server/.env.test cp demos/client-example/env.development demos/client-example/.env.test cp dev/scripts/env.test .env.test diff --git a/.github/workflows/tests_protocol.yml b/.github/workflows/tests_protocol.yml deleted file mode 100644 index dfa44af494..0000000000 --- a/.github/workflows/tests_protocol.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: tests_protocol - -on: - pull_request: - branches: - - 'main' - paths: - - 'protocol/**' - - '.github/workflows/tests_protocol.yml' - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - GH_TOKEN: ${{ github.token }} - NODE_ENV: test - -jobs: - check: - runs-on: ubuntu-latest - steps: - - name: Print contexts - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - ENV_CONTEXT: ${{ toJson(env) }} - VARS_CONTEXT: ${{ toJson(vars) }} - JOB_CONTEXT: ${{ toJson(job) }} - STEPS_CONTEXT: ${{ toJson(steps) }} - RUNNER_CONTEXT: ${{ toJson(runner) }} - SECRETS_CONTEXT: ${{ toJson(secrets) }} - STRATEGY_CONTEXT: ${{ toJson(strategy) }} - MATRIX_CONTEXT: ${{ toJson(matrix) }} - NEEDS_CONTEXT: ${{ toJson(needs) }} - INPUTS_CONTEXT: ${{ toJson(inputs) }} - run: | - echo "******************************" - echo "github:" "$GITHUB_CONTEXT" - echo "******************************" - echo "env:" "$ENV_CONTEXT" - echo "******************************" - echo "vars:" "$VARS_CONTEXT" - echo "******************************" - echo "job:" "$JOB_CONTEXT" - echo "******************************" - echo "steps:" "$STEPS_CONTEXT" - echo "******************************" - echo "runner:" "$RUNNER_CONTEXT" - echo "******************************" - echo "secrets:" "$SECRETS_CONTEXT" - echo "******************************" - echo "strategy:" "$STRATEGY_CONTEXT" - echo "******************************" - echo "matrix:" "$MATRIX_CONTEXT" - echo "******************************" - echo "needs:" "$NEEDS_CONTEXT" - echo "******************************" - echo "inputs:" "$INPUTS_CONTEXT" - echo "******************************" - - - uses: actions/checkout@v3 - - - run: mkdir -p protocol/cargo-cache - - run: mkdir -p protocol/target - - run: mkdir -p node_modules - - run: mkdir -p ~/.cache/Cypress - - - name: Restore cache - uses: actions/cache/restore@v3 - with: - path: | - protocol/cargo-cache - protocol/target - node_modules - ~/.cache/Cypress - # note that restoring a cache in github is a pain. The trailing '-' matches any string after the '-', therefore 'abc-' would match a cache named 'abc-1234' or 'abc-5678', etc. - # the problem is 'abc-' will not match a cache named 'abc'! So if you're using wildcard cache name selectors like this, you need a field that changes as the suffix to become the wildcard - # here we're setting the key to an unused cache key so it falls back to the wildcard selector in `restore-keys` - key: some-unused-cache-key - restore-keys: | - project-cache-${{ runner.os }}-${{ runner.arch }}- - - - uses: actions/setup-node@v3 - with: - node-version-file: '.nvmrc' - - run: npm i -g npm@$(cat package.json | jq -r .engines.npm) - - - run: npm ci - - - run: npm -w @prosopo/protocol run build:all - - - name: Check typechain is up-to-date - run: | - # check the output of typechain has a contract hash matching the current contract version - # this looks at the hash in the metadata for the contracts and matches typechain's metadata hash against protocol's metadata hash to detect differences - set -euo pipefail - typechain_contracts=$(find ./contracts -maxdepth 1 -mindepth 1 -type d) - protocol_contracts=$(find ./protocol/target/ink -maxdepth 1 -mindepth 1 -type d) - contracts=( "${typechain_contracts[@]}" "${protocol_contracts[@]}" ) - for contract_path in ${contracts[@]}; do - contract_name=$(basename $contract_path) - typechain_metadata="./contracts/$contract_name/src/$contract_name.json" - protocol_metadata="./protocol/target/ink/$contract_name/$contract_name.json" - typechain_hash=$(cat $typechain_metadata | jq -r '.source.hash') - protocol_hash=$(cat $protocol_metadata | jq -r '.source.hash') - if [ "$typechain_hash" != "$protocol_hash" ]; then - echo "Hash mismatch for $contract_name" - echo "Typechain: $typechain_hash" - echo "Protocol: $protocol_hash" - exit 1 - else - echo "Hash match for $contract_path" - fi - done - - - run: npm -w @prosopo/protocol run test diff --git a/dev/gh-actions/package.json b/dev/gh-actions/package.json index 5f7f9c8b3a..8cdeff380c 100644 --- a/dev/gh-actions/package.json +++ b/dev/gh-actions/package.json @@ -25,6 +25,7 @@ }, "dependencies": { "@octokit/graphql": "^7.0.2", + "axios": "^1.7.2", "node-fetch": "^3.3.2", "octokit": "^3.1.2" }, diff --git a/dev/gh-actions/src/dockerTags.ts b/dev/gh-actions/src/dockerTags.ts new file mode 100644 index 0000000000..181cfc9c56 --- /dev/null +++ b/dev/gh-actions/src/dockerTags.ts @@ -0,0 +1,61 @@ +// Copyright 2021-2024 Prosopo (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import axios from 'axios'; + +export async function fetchTags(namespace: string, repository: string): Promise { + const tags: string[] = []; + let page = 1; + let nextPageUrl: string | null = `https://hub.docker.com/v2/repositories/${namespace}/${repository}/tags/?page=${page}`; + + while (nextPageUrl) { + try { + const response: any = await axios.get(nextPageUrl); + const data = response.data; + tags.push(...data.results.map((tag: any) => tag.name)) + nextPageUrl = data.next; + page++; + } catch (error) { + console.error(`Error fetching tags: ${error}`); + break; + } + } + + tags.sort(semVerLt) + + return tags.reverse(); +} + +export const semVerLt = (a: string, b: string): number => { + const aParts = a.split('.').map((part) => parseInt(part, 10)); + const bParts = b.split('.').map((part) => parseInt(part, 10)); + + if (aParts.length !== bParts.length || aParts.length !== 3) { + // not semver, so compare lexicographically + return a.localeCompare(b); + } + + for (let i = 0; i < aParts.length; i++) { + if (aParts[i]! < bParts[i]!) { + return -1; + } else if (aParts[i]! > bParts[i]!) { + return 1; + } + } + + return 0; +} + +export const isSemVer = (tag: string): boolean => { + return /^\d+\.\d+\.\d+$/.test(tag); +} diff --git a/dev/gh-actions/src/listDockerTags.ts b/dev/gh-actions/src/listDockerTags.ts new file mode 100644 index 0000000000..df9687f965 --- /dev/null +++ b/dev/gh-actions/src/listDockerTags.ts @@ -0,0 +1,12 @@ +import { fetchTags } from "./dockerTags.js"; + + +const main = async () => { + // get args + const args = process.argv.slice(2); + const tags = await fetchTags(String(args[0]), String(args[1])) + console.log(tags) +} + + +main() diff --git a/dev/gh-actions/src/previousDockerTag.ts b/dev/gh-actions/src/previousDockerTag.ts new file mode 100644 index 0000000000..5c630adac5 --- /dev/null +++ b/dev/gh-actions/src/previousDockerTag.ts @@ -0,0 +1,36 @@ +// Copyright 2021-2024 Prosopo (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import axios from 'axios'; +import { fetchTags, isSemVer, semVerLt } from './dockerTags.js'; + +const main = async () => { + // get args + const args = process.argv.slice(2); + // tags will be sorted in descending order + const tags = await fetchTags(String(args[0]), String(args[1])) + // find the tag that is previous to the given tag + const target = String(args[2]); + for (const tag of tags) { + if (isSemVer(tag) === false) { + continue; + } + if (semVerLt(tag, target) === -1) { + // found the previous tag + console.log(tag); + return; + } + } +} + +main() diff --git a/package-lock.json b/package-lock.json index bc0ec6e6b4..9755d4ded2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,8 @@ "@typescript-eslint/parser": "^6.0.0", "@vitest/coverage-v8": "^1.3.1", "babel-plugin-import": "^1.13.6", + "concurrently": "^8.2.2", + "cypress": "^13.12.0", "depcheck": "^1.4.7", "eslint": "^8.55.0", "eslint-config-prettier": "^8.5.0", @@ -558,6 +560,7 @@ "license": "ISC", "dependencies": { "@octokit/graphql": "^7.0.2", + "axios": "^1.7.2", "node-fetch": "^3.3.2", "octokit": "^3.1.2" }, @@ -9866,6 +9869,34 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/axobject-query": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", @@ -11529,6 +11560,118 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/concurrently": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concurrently/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/confbox": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", @@ -12492,6 +12635,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -23935,6 +24094,12 @@ "memory-pager": "^1.0.2" } }, + "node_modules/spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true + }, "node_modules/spawn-please": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-1.0.0.tgz", @@ -24916,6 +25081,15 @@ "tslib": "2" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", diff --git a/package.json b/package.json index d4143a331c..32d5254e9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@prosopo/captcha", - "version": "1.0.2", + "version": "1.3.2", "stableVersion": "0.0.0", "author": "Prosopo", "type": "module", @@ -100,6 +100,8 @@ "@typescript-eslint/parser": "^6.0.0", "@vitest/coverage-v8": "^1.3.1", "babel-plugin-import": "^1.13.6", + "concurrently": "^8.2.2", + "cypress": "^13.12.0", "depcheck": "^1.4.7", "eslint": "^8.55.0", "eslint-config-prettier": "^8.5.0",