diff --git a/.github/workflows/contract.yaml b/.github/workflows/contract.yaml index 4e1abf005..1c50c1e99 100644 --- a/.github/workflows/contract.yaml +++ b/.github/workflows/contract.yaml @@ -8,6 +8,7 @@ jobs: FUZZBUCKET_SSH_KEY: ${{ secrets.FUZZBUCKET_SSH_KEY }} FUZZBUCKET_URL: ${{ secrets.FUZZBUCKET_URL }} FUZZBUCKET_CREDENTIALS: ${{ secrets.FUZZBUCKET_CREDENTIALS }} + CI: true strategy: fail-fast: false matrix: @@ -27,11 +28,20 @@ jobs: with: name: bin path: bin + - uses: actions/checkout@v4 + with: + repository: rstudio/connect-content + path: 'test/content' + sparse-checkout: bundles + sparse-checkout-cone-mode: false + token: ${{ secrets.CONNECT_PAT }} + - run: chmod -R +x ./bin - run: echo "${FUZZBUCKET_SSH_KEY}" > test/cy/fuzzbucket-ssh-key && chmod 600 test/cy/fuzzbucket-ssh-key - run: just cy install - run: just cy test - - run: just cy test-contract + # disable cypress contract tests until new deploy workflow + # - run: just cy test-contract - run: just bats install - run: just bats test - run: just bats test-contract diff --git a/test/bats/contract/accounts.bats b/test/bats/contract/accounts.bats new file mode 100644 index 000000000..145edf08e --- /dev/null +++ b/test/bats/contract/accounts.bats @@ -0,0 +1,22 @@ +#!/usr/bin/env bats + +load '../node_modules/bats-support/load' +load '../node_modules/bats-assert/load' + +# list-accounts should return the account from env +@test "list accounts" { + run ${EXE} list-accounts + assert_success + assert_output --partial "Nickname: \"env\"" + assert_output --partial "Configured via: CONNECT_SERVER environment variable" + assert_output --partial "Authentication: Connect API key" +} + +# test-account should pass with env +@test "test accounts" { + run ${EXE} test-account env + assert_success + assert_output --partial "Name: Administrator Smith" + assert_output --partial "Username: admin" + assert_output --partial "Email: rsc@example.com" +} \ No newline at end of file diff --git a/test/bats/contract/deploy.bats b/test/bats/contract/deploy.bats index 3a9f84e53..ee9fd00ab 100644 --- a/test/bats/contract/deploy.bats +++ b/test/bats/contract/deploy.bats @@ -2,28 +2,13 @@ load '../node_modules/bats-support/load' load '../node_modules/bats-assert/load' - -# list-accounts should return the account from env -@test "list accounts" { - run ${EXE} list-accounts - assert_success - assert_output --partial "Nickname: \"env\"" - assert_output --partial "Configured via: CONNECT_SERVER environment variable" - assert_output --partial "Authentication: Connect API key" -} - -# test-account should pass with env -@test "test accounts" { - run ${EXE} test-account env - assert_success - assert_output --partial "Name: Administrator Smith" - assert_output --partial "Username: admin" - assert_output --partial "Email: rsc@example.com" -} +source ../content/bundles/${CONTENT}/test/.publisher-env +CONTENT_PATH='../content/bundles/' # deploy content with the env account -@test "deploy content" { - run ${EXE} deploy ../sample-content/fastapi-simple/ -n ci_deploy +@test "deploy ${CONTENT}" { + + run ${EXE} deploy ${CONTENT_PATH}/${CONTENT} -n ci_deploy assert_success assert_output --partial "Test Deployment... [OK]" # now test the deployment via api @@ -33,12 +18,13 @@ load '../node_modules/bats-assert/load' run curl --silent --show-error -L --max-redirs 0 --fail \ -X GET \ -H "Authorization: Key ${CONNECT_API_KEY}" "${CONNECT_SERVER}/__api__/v1/content/${GUID}" - assert_output --partial "\"app_mode\":\"python-fastapi\"" + assert_output --partial "\"app_mode\":\"${CONTENT_TYPE}\"" } # redeploy content from previous test -@test "redeploy content" { - run ${EXE} redeploy ci_deploy ../sample-content/fastapi-simple/ +@test "redeploy ${CONTENT}" { + + run ${EXE} redeploy ci_deploy ${CONTENT_PATH}${CONTENT} assert_success assert_output --partial "Test Deployment... [OK]" # now test the deployment via api @@ -48,6 +34,7 @@ load '../node_modules/bats-assert/load' run curl --silent --show-error -L --max-redirs 0 --fail \ -X GET \ -H "Authorization: Key ${CONNECT_API_KEY}" "${CONNECT_SERVER}/__api__/v1/content/${GUID}" - assert_output --partial "\"app_mode\":\"python-fastapi\"" + assert_output --partial "\"app_mode\":\"${CONTENT_TYPE}\"" + # cleanup + run rm -rf ${CONTENT_PATH}${CONTENT}/.posit/ ${CONTENT_PATH}${CONTENT}/.positignore } - diff --git a/test/bats/justfile b/test/bats/justfile index 3335b671e..7b6a9236e 100644 --- a/test/bats/justfile +++ b/test/bats/justfile @@ -2,7 +2,10 @@ alias c := clean alias i := install alias t := test -_ci := env_var_or_default("CI", "false") +export CONTENT := env_var_or_default("CONTENT", "all") +export CONTENT_REPO := env_var_or_default("CONTENT_REPO", "/work/connect-content") + +export _ci := env_var_or_default("CI", "false") _debug := env_var_or_default("DEBUG", "false") @@ -47,22 +50,50 @@ run *args: # Executes bats deploy tests +# Content being tested lives in the connect-content githu repo test-contract: #!/usr/bin/env bash set -eou pipefail {{ _with_debug }} exe=$(just ../../executable-path) + + pip install -r ../setup/requirements.txt + export CONNECT_SERVER="$(python ../setup/connect_setup.py)" + export CONNECT_API_KEY="$(python ../setup/gen_apikey.py 'admin')" + if [ ! -f $exe ]; then echo "error: Missing executable $exe. Run \`just build\`." 1>&2 exit 1 fi - pip install -r ../setup/requirements.txt - export CONNECT_SERVER="$(python ../setup/connect_setup.py)" - export CONNECT_API_KEY="$(python ../setup/gen_apikey.py 'admin')" - - EXE=$exe npm run contract + + # run contract/accounts.bats + EXE=$exe npm run accounts + + # pull the content from connect-content repo + if [[ "${CONTENT}" == "all" ]]; then + if [[ ${_ci} == false ]]; then + mkdir -p ../content/bundles/ + cp -R ${HOME}${CONTENT_REPO}/bundles/ ../content/bundles/ + fi + + # content_list will contain all content in + content_list=$(find "../content/bundles" -maxdepth 1 -type d -exec basename {} \;) + # IFS=' ' read -ra my_array <<< "${content_list}" + for i in ${content_list} + do + # only test when we have a .publisher-env file for the content + if [[ -f ../content/bundles/${i}/test/.publisher-env ]]; then + export CONTENT=${i} + EXE=$exe npm run deploy + fi + done + # rm -rf ../content/ + else + cp -R "${HOME}${CONTENT_REPO}/bundles/${CONTENT}" ../content/ + EXE=$exe npm run deploy + fi # Executes bats local tests test: diff --git a/test/bats/package.json b/test/bats/package.json index 76698daf2..124eccfa8 100644 --- a/test/bats/package.json +++ b/test/bats/package.json @@ -1,7 +1,8 @@ { "private": true, "scripts": { - "contract": "bats -r -T -t ./contract", + "deploy": "bats -r -T -t ./contract/deploy.bats", + "accounts": "bats -r -T -t ./contract/accounts.bats", "cli": "bats -r -T -t ./cli" }, "devDependencies": { diff --git a/test/setup/connect_setup.py b/test/setup/connect_setup.py index 4a02c5b9b..78d03ff75 100644 --- a/test/setup/connect_setup.py +++ b/test/setup/connect_setup.py @@ -58,6 +58,7 @@ def get_ip(box_name): def connect_ready(box_name, max_attempts, interval): connect_box=get_ip(box_name) update_config="fuzzbucket-client ssh " + box_name + " " + ssh_options + " sudo sed -i 's/CONNECT_IP/" + connect_box + "/g' /etc/rstudio-connect/rstudio-connect.gcfg" + restart_connect = "fuzzbucket-client ssh " + box_name + " " + ssh_options + " sudo systemctl restart rstudio-connect" attempts = 0 while attempts < max_attempts: try: @@ -68,6 +69,7 @@ def connect_ready(box_name, max_attempts, interval): logging.info("Installing Connect on " + connect_box) subprocess.check_output(install_connect, shell=True, text=True) subprocess.check_output(update_config, shell=True, text=True) + subprocess.check_output(restart_connect, shell=True, text=True) return response.text except requests.RequestException: pass @@ -79,6 +81,7 @@ def connect_ready(box_name, max_attempts, interval): api_key=get_api_key('admin') connect_version=get_connect_version() install_connect = "fuzzbucket-client ssh " + box_name + " " + ssh_options + " sudo -E UNATTENDED=1 bash installer-ci.sh -d " + connect_version + response = connect_ready(box_name, 20, 5) if response: