wip #8363
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This describes all the tests we run on the canister code (various builds, | |
# integration tests, selenium tests). The canister code is built in docker and the | |
# wasm is then reused by subsequent build steps. We build various flavors of | |
# the code, see `docker-build-...` for more info. | |
name: Canister tests | |
on: | |
push: | |
jobs: | |
##################### | |
# The docker builds # | |
##################### | |
# The image shared by all builds, containing pre-built rust deps | |
docker-build-base: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v3 | |
# We use buildx and its GitHub Actions caching support `type=gha`. For | |
# more information, see | |
# https://github.com/docker/build-push-action/issues/539 | |
- name: Set up docker buildx | |
uses: docker/setup-buildx-action@v2 | |
- name: Build base Docker image | |
uses: docker/build-push-action@v3 | |
with: | |
context: . | |
file: Dockerfile | |
cache-from: type=gha,scope=cached-stage | |
cache-to: type=gha,scope=cached-stage,mode=max | |
outputs: type=cacheonly | |
target: deps | |
docker-build-ii: | |
runs-on: ubuntu-latest | |
needs: docker-build-base | |
strategy: | |
# NOTE: the 'name' in the matrix should match the asset filename, because it is used in | |
# .github/actions/release to figure out the job ID. | |
# | |
# NOTE: if you modify the flavors, update the #flavors table in README.md | |
matrix: | |
include: | |
# The production build | |
- name: internet_identity_production.wasm.gz | |
II_FETCH_ROOT_KEY: 0 | |
II_DUMMY_CAPTCHA: 0 | |
II_DUMMY_AUTH: 0 | |
II_INSECURE_REQUESTS: 0 | |
# No captcha and fetching the root key, used in (our) tests, backend and | |
# selenium. | |
- name: internet_identity_test.wasm.gz | |
II_FETCH_ROOT_KEY: 1 | |
II_DUMMY_CAPTCHA: 1 | |
II_DUMMY_AUTH: 0 | |
II_INSECURE_REQUESTS: 0 | |
# Everything disabled, used by third party developers who only care | |
# about the login flow | |
- name: internet_identity_dev.wasm.gz | |
II_FETCH_ROOT_KEY: 1 | |
II_DUMMY_CAPTCHA: 1 | |
II_DUMMY_AUTH: 1 | |
II_INSECURE_REQUESTS: 1 | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Infer version | |
id: version | |
run: | | |
version="$(./scripts/version)" | |
echo "Inferred version: '$version'" | |
echo "version=$version" >> "$GITHUB_OUTPUT" | |
- name: Set up docker buildx | |
uses: docker/setup-buildx-action@v2 | |
- name: Build ${{ matrix.name }} | |
uses: docker/build-push-action@v3 | |
with: | |
context: . | |
file: Dockerfile | |
build-args: | | |
II_FETCH_ROOT_KEY=${{ matrix.II_FETCH_ROOT_KEY }} | |
II_DUMMY_AUTH=${{ matrix.II_DUMMY_AUTH }} | |
II_DUMMY_CAPTCHA=${{ matrix.II_DUMMY_CAPTCHA }} | |
II_INSECURE_REQUESTS=${{ matrix.II_INSECURE_REQUESTS }} | |
II_VERSION=${{ steps.version.outputs.version }} | |
cache-from: type=gha,scope=cached-stage | |
# Exports the artefacts from the final stage | |
outputs: ./out | |
target: scratch_internet_identity | |
- run: mv out/internet_identity.wasm.gz ${{ matrix.name }} | |
- run: sha256sum ${{ matrix.name }} | |
- name: 'Upload ${{ matrix.name }}' | |
uses: actions/upload-artifact@v3 | |
with: | |
# name is the name used to display and retrieve the artifact | |
name: ${{ matrix.name }} | |
# path is the name used as the file to upload and the name of the | |
# downloaded file | |
path: ${{ matrix.name }} | |
docker-build-archive: | |
runs-on: ubuntu-latest | |
needs: docker-build-base | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Set up docker buildx | |
uses: docker/setup-buildx-action@v2 | |
- name: Build Archive Canister | |
uses: docker/build-push-action@v3 | |
with: | |
context: . | |
file: Dockerfile | |
cache-from: type=gha,scope=cached-stage | |
# Exports the artefacts from the final stage | |
outputs: ./out | |
target: scratch_archive | |
- run: mv out/archive.wasm.gz archive.wasm.gz | |
- run: sha256sum archive.wasm.gz | |
- name: 'Upload archive.wasm.gz' | |
uses: actions/upload-artifact@v3 | |
with: | |
# name is the name used to display and retrieve the artifact | |
name: archive.wasm.gz | |
# path is the name used as the file to upload and the name of the | |
# downloaded file | |
path: archive.wasm.gz | |
wasm-size: | |
runs-on: ubuntu-latest | |
needs: docker-build-ii | |
steps: | |
- uses: actions/checkout@v3 | |
- name: 'Download wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_production.wasm.gz | |
path: . | |
- id: record-size | |
uses: ./.github/actions/file-size | |
with: | |
file: internet_identity_production.wasm.gz | |
save: ${{ github.ref == 'refs/heads/main' }} | |
- name: "Check canister size" | |
run: | | |
max_size=2097152 # maximum canister size, in bytes | |
actual_size=${{ steps.record-size.outputs.size }} | |
if (( actual_size > max_size )) | |
then | |
echo "Canister size too big" | |
echo "($actual_size > $max_size)" | |
exit 1 | |
fi | |
test-app-build: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v3 | |
- uses: actions/cache@v3 | |
with: | |
path: | | |
~/.cargo/registry | |
~/.cargo/git | |
demos/test-app/target | |
key: ${{ runner.os }}-cargo-${{ hashFiles('demos/test-app/Cargo.lock', 'rust-toolchain.toml') }} | |
- uses: ./.github/actions/bootstrap | |
- uses: ./.github/actions/setup-node | |
- name: "Build test app canister" | |
working-directory: demos/test-app | |
run: ./build.sh | |
- name: 'Upload test app' | |
uses: actions/upload-artifact@v3 | |
with: | |
# name is the name used to display and retrieve the artifact | |
name: test_app.wasm | |
# path is the name used as the file to upload and the name of the | |
# downloaded file | |
path: ./demos/test-app/test_app.wasm | |
########################### | |
# The Rust canister tests # | |
########################### | |
# Run the tests, user the output of the docker build as Wasm module | |
# (note: this runs _all_ cargo tests) | |
canister-tests-build: | |
runs-on: ${{ matrix.os }} | |
strategy: | |
matrix: | |
os: [ ubuntu-latest, macos-latest ] | |
steps: | |
- uses: actions/checkout@v3 | |
# Attempt to restore the pre-built test binaries from cache. | |
# The test binaries are only dependent on rust code, because the front-end code is bundled in the `wasm` file | |
# that is loaded by the test binaries. | |
# If the binary can be restored from cache, we skip the build step, including even setting up the toolchain etc. | |
- uses: actions/cache@v3 | |
id: cache-test-archive | |
with: | |
path: /tmp/test-archive | |
key: ${{ runner.os }}-rust-test-archive-${{ hashFiles('src/**/*.rs', 'Cargo.*', 'src/*/*.toml', 'rust-toolchain.toml') }} | |
- uses: ./.github/actions/bootstrap | |
if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
- uses: actions/cache@v3 | |
if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
with: | |
path: | | |
~/.cargo | |
target | |
key: ${{ runner.os }}-rust-test-cache-${{ hashFiles('Cargo.toml', 'rust-toolchain.toml', 'Cargo.lock') }} | |
- name: Install nextest | |
if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
run: | | |
curl -LsSf https://get.nexte.st/latest/${{ matrix.os == 'macos-latest' && 'mac' || 'linux' }} | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin | |
# Rustup only installs cargo on the first call, so we use a dedicated step to get a good idea of how | |
# time is spent in each step separately | |
- if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
run: cargo check --help | |
- name: Create dummy assets | |
if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
run: | | |
mkdir dist | |
touch dist/index.html | |
touch dist/index.js.gz | |
# Build the tests | |
- name: Build test archive | |
if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
run: | | |
git checkout ${{ steps.git_info.outputs.commit_now }} | |
cargo nextest archive --archive-file canister-tests-${{ matrix.os }}.tar.zst --release | |
mkdir -p /tmp/test-archive/ | |
cp canister-tests-${{ matrix.os }}.tar.zst /tmp/test-archive | |
- name: Restore test archive | |
if: steps.cache-test-archive.outputs.cache-hit == 'true' | |
run: | | |
mv /tmp/test-archive/canister-tests-${{ matrix.os }}.tar.zst . | |
- name: 'Upload canister test archive' | |
uses: actions/upload-artifact@v3 | |
with: | |
# name is the name used to display and retrieve the artifact | |
name: canister-tests-${{ matrix.os }}.tar.zst | |
# path is the name used as the file to upload and the name of the | |
# downloaded file | |
path: ./canister-tests-${{ matrix.os }}.tar.zst | |
canister-tests-run: | |
runs-on: ${{ matrix.os }} | |
needs: [canister-tests-build, docker-build-ii, docker-build-archive] | |
strategy: | |
matrix: | |
os: [ ubuntu-latest, macos-latest ] | |
partition: ['1/3', '2/3', '3/3'] | |
steps: | |
- uses: actions/checkout@v3 | |
# Required by the ic-test-state-machine | |
- name: Install openssl (macos) | |
if: ${{ matrix.os == 'macos-latest' }} | |
run: | | |
brew install openssl@3 | |
- name: Download nextest | |
run: | | |
curl -LsSf https://get.nexte.st/latest/${{ matrix.os == 'macos-latest' && 'mac' || 'linux' }} | tar zxf - | |
- name: 'Download nextest test archive' | |
uses: actions/download-artifact@v3 | |
with: | |
name: canister-tests-${{ matrix.os }}.tar.zst | |
path: . | |
- name: Download ic-test-state-machine binary | |
run: | | |
uname_sys=$(uname -s | tr '[:upper:]' '[:lower:]') | |
echo "uname_sys: $uname_sys" | |
commit_sha=$(sed <.ic-commit 's/#.*$//' | sed '/^$/d') | |
echo "commit sha: $commit_sha" | |
curl -sLO "https://download.dfinity.systems/ic/$commit_sha/binaries/x86_64-$uname_sys/ic-test-state-machine.gz" | |
gzip -d ic-test-state-machine.gz | |
chmod a+x ic-test-state-machine | |
./ic-test-state-machine --version | |
- name: 'Download II wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_test.wasm.gz | |
path: . | |
- name: 'Download archive wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: archive.wasm.gz | |
path: . | |
- name: Run Tests | |
run: | | |
mv internet_identity_test.wasm.gz internet_identity.wasm.gz | |
# NOTE: Here we download changing assets (i.e. the latest release) meaning that in some rare cases (after a new release) | |
# PRs that used to be green may become red (if the new release broke something). While this is not CI best practice, it's | |
# a relatively small price to pay to make sure PRs are always tested against the latest release. | |
curl -sSL https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity_test.wasm.gz -o internet_identity_previous.wasm.gz | |
curl -sSL https://github.com/dfinity/internet-identity/releases/latest/download/archive.wasm.gz -o archive_previous.wasm.gz | |
# We are using --partition hash instead of count, because it makes sure that the tests partition is stable across runs | |
# even if tests are added or removed. The tradeoff is that the balancing might be slightly worse, but we have enough | |
# tests that it should not be a big issue. | |
./cargo-nextest nextest run --archive-file canister-tests-${{ matrix.os }}.tar.zst --partition hash:${{ matrix.partition }} | |
env: | |
RUST_BACKTRACE: 1 | |
###################### | |
# The selenium tests # | |
###################### | |
selenium: | |
runs-on: ubuntu-latest | |
needs: [docker-build-ii, test-app-build] | |
strategy: | |
matrix: | |
device: [ 'desktop', 'mobile' ] | |
# We run the integration tests on both the official and legacy domains, to make sure | |
# the webapp (routes, csp, etc) works on both. | |
domain: [ 'https://identity.internetcomputer.org', 'https://identity.ic0.app' ] | |
# Specify some shards for jest (a jest instance will only run a subset of files | |
# based on the shard assigned to it) | |
# The jest parameter is actually 1/N, 2/N etc but we use a artifact-friendly | |
# version here (with underscore). | |
shard: [ '1_4', '2_4', '3_4', '4_4' ] | |
# Make sure that one failing test does not cancel all other matrix jobs | |
fail-fast: false | |
steps: | |
- uses: actions/checkout@v3 | |
- uses: ./.github/actions/setup-node | |
- uses: ./.github/actions/setup-dfx | |
# Helps with debugging | |
- name: Show versions | |
run: | | |
echo dfx --version | |
dfx --version | |
echo node --version | |
node --version | |
echo docker --version | |
docker --version | |
- name: 'Run dfx' | |
run: dfx start --background | |
- name: 'Download II wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_test.wasm.gz | |
path: . | |
- name: 'Download test app wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: test_app.wasm | |
path: demos/test-app | |
- name: Deploy Internet Identity | |
run: | | |
dfx canister create --all | |
dfx canister install internet_identity --wasm internet_identity_test.wasm.gz | |
- name: Deploy test app | |
working-directory: demos/test-app | |
run: | | |
dfx canister create --all | |
dfx canister install test_app --wasm test_app.wasm | |
- name: Start docker compose | |
run: scripts/start-selenium-env --no-hot-reload | |
- run: npm ci | |
- run: npm test | |
- run: "II_URL=${{ matrix.domain }} SCREEN=${{ matrix.device }} npm run test:e2e -- --shard=$(tr <<<'${{ matrix.shard }}' -s _ /)" # replace 1_N with 1/N | |
- name: Collect docker logs | |
working-directory: docker-test-env | |
if: ${{ always() }} | |
run: docker compose logs > ../docker-compose.log | |
- name: Stop dfx | |
run: dfx stop | |
- name: Shut down docker services | |
working-directory: docker-test-env | |
run: docker compose down | |
- name: Archive test logs | |
if: ${{ always() }} | |
uses: actions/upload-artifact@v3 | |
with: | |
name: e2e-test-log-${{ matrix.device }}-${{ matrix.shard }} | |
path: ./*.log | |
- name: Archive test failures | |
if: ${{ always() }} | |
uses: actions/upload-artifact@v3 | |
with: | |
name: e2e-test-failures-${{ matrix.device }}-${{ matrix.shard }} | |
path: test-failures/* | |
if-no-files-found: ignore | |
using-dev-build: | |
runs-on: ubuntu-latest | |
needs: docker-build-ii | |
steps: | |
- uses: actions/checkout@v3 | |
- run: | | |
sudo apt-get update | |
sudo apt-get --only-upgrade install google-chrome-stable | |
google-chrome --version | |
- uses: ./.github/actions/setup-node | |
- uses: ./.github/actions/setup-dfx | |
# Helps with debugging | |
- name: Show versions | |
run: | | |
echo dfx --version | |
dfx --version | |
- name: Start replica | |
run: | | |
dfx start --background | |
- name: 'Download wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_dev.wasm.gz | |
path: . | |
- name: Deploy II and run tests | |
run: | | |
set -euo pipefail | |
# Copy example to make sure it does not rely on living inside the II repo | |
builddir=$(mktemp -d) | |
cp -r ./demos/using-dev-build/. "$builddir" | |
ii_wasm="$PWD/internet_identity_dev.wasm.gz" | |
ii_did="$PWD/src/internet_identity/internet_identity.did" | |
pushd "$builddir" | |
# Install npm deps | |
npm ci | |
sed -i "s;https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity_dev.wasm.gz;$ii_wasm;" ./dfx.json | |
sed -i "s;https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity.did;$ii_did;" ./dfx.json | |
dfx deploy --no-wallet | |
npm run test | |
popd | |
rm -rf "$builddir" | |
- name: Stop replica | |
run: | | |
dfx stop | |
# This deploys the production build to mainnet, to a canister that we use for release testing. | |
deploy: | |
runs-on: ubuntu-latest | |
if: startsWith(github.ref, 'refs/tags/release-') | |
needs: [docker-build-ii, docker-build-archive] | |
steps: | |
- uses: actions/checkout@v3 | |
- uses: ./.github/actions/setup-dfx | |
- name: 'Download II wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_production.wasm.gz | |
path: . | |
- name: 'Download archive wasm' | |
uses: actions/download-artifact@v3 | |
with: | |
name: archive.wasm.gz | |
path: . | |
- name: 'Install key' | |
env: | |
DFX_DEPLOY_KEY: ${{ secrets.DFX_DEPLOY_KEY }} | |
run: | | |
key_pem=$(mktemp) | |
printenv "DFX_DEPLOY_KEY" > "$key_pem" | |
dfx identity import --disable-encryption --force default "$key_pem" | |
rm "$key_pem" | |
- name: "Deploy II" | |
run: | | |
wallet="cvthj-wyaaa-aaaad-aaaaq-cai" | |
sha=$(shasum -a 256 ./archive.wasm.gz | cut -d ' ' -f1 | sed 's/../\\&/g') | |
dfx canister --network ic --wallet "$wallet" install --mode upgrade \ | |
--argument "(opt record {archive_config = record { module_hash = blob \"$sha\"; entries_buffer_limit = 10000:nat64; entries_fetch_limit = 1000:nat16; polling_interval_ns = 60000000000:nat64}; canister_creation_cycles_cost = opt (1000000000000:nat64); })" \ | |
--wasm internet_identity_production.wasm.gz \ | |
fgte5-ciaaa-aaaad-aaatq-cai | |
- name: "Deploy archive" | |
run: scripts/deploy-archive --wasm archive.wasm.gz --canister-id fgte5-ciaaa-aaaad-aaatq-cai --network ic | |
# This ... releases | |
release: | |
runs-on: ubuntu-latest | |
if: startsWith(github.ref, 'refs/tags/release-') | |
needs: [docker-build-ii, docker-build-archive] | |
steps: | |
- uses: actions/checkout@v3 | |
- name: 'Download wasm.gz' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_test.wasm.gz | |
path: . | |
- name: 'Download wasm.gz' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_dev.wasm.gz | |
path: . | |
- name: 'Download wasm.gz' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_production.wasm.gz | |
path: . | |
- name: 'Download wasm.gz' | |
uses: actions/download-artifact@v3 | |
with: | |
name: archive.wasm.gz | |
path: . | |
- name: Prepare release | |
uses: ./.github/actions/release | |
id: prepare-release | |
with: | |
assets: | | |
internet_identity_production.wasm.gz | |
internet_identity_dev.wasm.gz | |
internet_identity_test.wasm.gz | |
archive.wasm.gz | |
production_asset: internet_identity_production.wasm.gz | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Publish release | |
run: | | |
./scripts/release \ | |
--tag ${{ github.ref }} \ | |
--notes-file ${{ steps.prepare-release.outputs.notes-file }} \ | |
-- \ | |
internet_identity_production.wasm.gz \ | |
internet_identity_dev.wasm.gz \ | |
internet_identity_test.wasm.gz \ | |
src/internet_identity/internet_identity.did \ | |
archive.wasm.gz | |
env: | |
# populated by GitHub Actions | |
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
clean-build: | |
runs-on: ${{ matrix.os }} | |
needs: docker-build-ii | |
strategy: | |
matrix: | |
# On main, we run the checks across all platforms. On other branches, in order to speed up checks (on PRs) we skip most platforms | |
# (in particular the slow macos builds). A single ubuntu build is not long and gives us some signal. | |
# XXX: GHA does not support proper if/else so we implement a workaround: https://github.com/actions/runner/issues/409 | |
# XXX: GHA fails if we return the matrix object directly, so we have to pretend it's JSON | |
os: ${{ github.ref == 'refs/heads/main' && fromJson('[ "ubuntu-22.04", "ubuntu-20.04", "macos-11", "macos-12" ]') || fromJson('[ "ubuntu-22.04" ]') }} | |
steps: | |
- uses: actions/checkout@v3 | |
- name: 'Download wasm.gz' | |
uses: actions/download-artifact@v3 | |
with: | |
name: internet_identity_production.wasm.gz | |
path: . | |
- run: | | |
sha256=$(shasum -a 256 ./internet_identity_production.wasm.gz | cut -d ' ' -f1) | |
echo "sha256=$sha256" >> "$GITHUB_OUTPUT" | |
id: sha256 | |
- uses: ./.github/actions/check-build | |
with: | |
# we check that ubuntu builds match the docker build | |
sha256: ${{ startsWith(matrix.os, 'ubuntu') && steps.sha256.outputs.sha256 || '' }} | |
interface-compatibility: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v3 | |
- uses: ./.github/actions/setup-didc | |
- name: "Check canister interface compatibility" | |
run: | | |
curl -sSL https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity.did -o internet_identity_previous.did | |
didc check src/internet_identity/internet_identity.did internet_identity_previous.did |