From 53ad5a6f3a5fbe74bd547eb1691919d912a8c8da Mon Sep 17 00:00:00 2001 From: jordan Date: Tue, 14 Nov 2023 14:26:07 +0000 Subject: [PATCH] Add smoke test (#60) --- test/config.toml | 5 +++++ test/create_pat.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/example-bin/.gitignore | 2 ++ test/example-bin/Cargo.toml | 9 +++++++++ test/example-bin/README | 1 + test/example-lib/.gitignore | 2 ++ test/example-lib/Cargo.toml | 8 ++++++++ test/example-lib/README | 2 ++ test/example-bin/.cargo/config.toml | 2 ++ test/example-bin/src/main.rs | 3 +++ test/example-lib/src/lib.rs | 14 ++++++++++++++ 12 files changed, 191 insertions(+) diff --git a/test/config.toml b/test/config.toml new file mode 100644 index 0000000..e9bba61 100644 --- /dev/null +++ a/test/config.toml @@ -1,0 +1,5 @@ +listen-address = "0.0.0.0:2233" +state-directory = "/tmp/state" + +[gitlab] +uri = "http://127.0.0.1" diff --git a/test/create_pat.py b/test/create_pat.py new file mode 100644 index 0000000..4ee3234 100644 --- /dev/null +++ a/test/create_pat.py @@ -1,0 +1,65 @@ +# Creates a personal access token using the GitLab UI, given only a username + password combination. This is required +# when using the spawned instance of GitLab in smoke tests, as we only get back a password from the logs, and there's +# no way for us to authenticate with the GitLab API using just a password. +# +# Adapted from https://gist.github.com/gpocentek/bd4c3fbf8a6ce226ebddc4aad6b46c0a + +import re +import sys +import os +import requests +import bs4 + +BASE_URL = "http://127.0.0.1" +SIGN_IN_URL = BASE_URL + "/users/sign_in" +PAT_URL = BASE_URL + "/-/profile/personal_access_tokens" + +session = requests.Session() + +# fetch CSRF for sign-in page +print('Fetching CSRF token from sign in page', file=sys.stderr) +sign_in_page = session.get(SIGN_IN_URL) +root = bs4.BeautifulSoup(sign_in_page.text, "html5lib") +csrf = root.find_all("meta", attrs={'name': 'csrf-token'})[0]['content'] + +if not csrf: + print('Unable to find csrf token on sign in page', file=sys.stderr) + sys.exit(1) + +# login to gitlab using the ROOT_PASSWORD env var, storing the session token in our session object +sign_in_res = session.post(SIGN_IN_URL, data={ + 'user[login]': 'root', + 'user[password]': os.environ['ROOT_PASSWORD'].strip(), + 'authenticity_token': csrf, +}) + +if sign_in_res.status_code != 200: + print('Failed to login to GitLab instance', file=sys.stderr) + sys.exit(1) + +print('Successfully logged into GitLab, fetching CSRF token for PAT page', file=sys.stderr) + +# fetch the csrf token for PAT creation +pat_page = session.get(PAT_URL) +root = bs4.BeautifulSoup(pat_page.text, "html5lib") +csrf = root.find_all("meta", attrs={'name': 'csrf-token'})[0]['content'] + +if not csrf: + print('Unable to find csrf token on PAT creation page', file=sys.stderr) + sys.exit(1) + +print('Found CSRF token, creating PAT', file=sys.stderr) + +# create the personal access token +response = session.post(PAT_URL, data={ + "personal_access_token[name]": "apitoken", + "personal_access_token[scopes][]": "api", + "authenticity_token": csrf, +}) + +personal_access_token = response.json()['new_token'] +if not personal_access_token: + print('Failed to find personal access token in response', file=sys.stderr) + sys.exit(1) + +print(personal_access_token) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..061797e 100644 --- /dev/null +++ a/.github/workflows/test.yml @@ -1,0 +1,78 @@ +on: [push, pull_request] + +name: Test + +jobs: + smoke: + name: Smoke Test + runs-on: ubuntu-latest + services: + gitlab: + image: gitlab/gitlab-ee:latest + options: --shm-size 256m + ports: + - 80:80 + - 443:443 + steps: + - uses: actions/checkout@v4 + - name: Start gitlab-cargo-shim + run: | + docker build . -t gitlab-cargo-shim + docker run --detach \ + --name gitlab-cargo-shim \ + --mount type=bind,source=$(pwd)/test/config.toml,target=/app/config.toml \ + --network host \ + gitlab-cargo-shim \ + -c /app/config.toml + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y python3-pip jq openssh-client + pip3 install requests beautifulsoup4 html5lib + - name: Wait for GitLab to boot + run: timeout 20m bash -c 'until curl -s http://127.0.0.1/users/sign_in | grep csrf-token; do sleep 5; done' + - name: Create GitLab package + run: | + export GITLAB_CONTAINER=$(docker ps --format "{{.ID}}" --no-trunc --filter "ancestor=gitlab/gitlab-ee:latest") + export ROOT_PASSWORD=$(docker exec $GITLAB_CONTAINER grep 'Password:' /etc/gitlab/initial_root_password | sed 's/Password: //') + export ROOT_PAT=$(python3 ./test/create_pat.py) + curl -s --request POST --header "PRIVATE-TOKEN: $ROOT_PAT" --header "Content-Type: application/json" \ + --data '{"name": "example-lib"}' \ + --url 'http://127.0.0.1/api/v4/projects/' + echo "ROOT_PAT=$ROOT_PAT" >> "$GITHUB_ENV" + - name: Packaging example-lib + run: | + cd test/example-lib + cargo package + cargo metadata --format-version 1 > metadata.json + - name: Uploading example-lib to GitLab + run: | + curl --header "PRIVATE-TOKEN: $ROOT_PAT" --upload-file test/example-lib/target/package/example-lib-0.1.0.crate http://127.0.0.1/api/v4/projects/root%2Fexample-lib/packages/generic/example-lib/0.1.0/example-lib-0.1.0.crate + curl --header "PRIVATE-TOKEN: $ROOT_PAT" --upload-file test/example-lib/metadata.json http://127.0.0.1/api/v4/projects/root%2Fexample-lib/packages/generic/example-lib/0.1.0/metadata.json + - name: Creating SSH key to identify with gitlab-cargo-shim + run: | + ssh-keygen -t ed25519 -C testkey -N '' -f ~/.ssh/id_ed25519 + - name: Fetching public keys from gitlab-cargo-shim and storing in known_hosts + run: | + ssh-keyscan -p 2233 127.0.0.1 > ~/.ssh/known_hosts + - name: Write PAT to .config + run: | + echo -e "Host *\n User personal-token:$ROOT_PAT" > ~/.ssh/config + - name: Building example-bin using example-lib from registry + run: | + cd test/example-bin + CARGO_NET_GIT_FETCH_WITH_CLI=true cargo check + - name: Collect docker logs on failure + if: failure() + uses: jwalton/gh-docker-logs@v2 + with: + dest: './logs' + - name: Tar logs + if: failure() + run: tar cvzf ./logs.tgz ./logs + - name: Upload logs as artifacts + if: failure() + uses: actions/upload-artifact@master + with: + name: logs.tgz + path: ./logs.tgz diff --git a/test/example-bin/.gitignore b/test/example-bin/.gitignore new file mode 100644 index 0000000..2c96eb1 100644 --- /dev/null +++ a/test/example-bin/.gitignore @@ -1,0 +1,2 @@ +target/ +Cargo.lock diff --git a/test/example-bin/Cargo.toml b/test/example-bin/Cargo.toml new file mode 100644 index 0000000..3dae8f8 100644 --- /dev/null +++ a/test/example-bin/Cargo.toml @@ -1,0 +1,9 @@ +[package] +name = "example-bin" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +example-lib = { version = "0.1", registry = "my-group-example-lib" } diff --git a/test/example-bin/README b/test/example-bin/README new file mode 100644 index 0000000..46d706a 100644 --- /dev/null +++ a/test/example-bin/README @@ -1,0 +1,1 @@ +This crate is built in CI to ensure example-lib can be fetched via gitlab-cargo-shim diff --git a/test/example-lib/.gitignore b/test/example-lib/.gitignore new file mode 100644 index 0000000..2c96eb1 100644 --- /dev/null +++ a/test/example-lib/.gitignore @@ -1,0 +1,2 @@ +target/ +Cargo.lock diff --git a/test/example-lib/Cargo.toml b/test/example-lib/Cargo.toml new file mode 100644 index 0000000..dee3428 100644 --- /dev/null +++ a/test/example-lib/Cargo.toml @@ -1,0 +1,8 @@ +[package] +name = "example-lib" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/test/example-lib/README b/test/example-lib/README new file mode 100644 index 0000000..a47c1fe 100644 --- /dev/null +++ a/test/example-lib/README @@ -1,0 +1,2 @@ +This crate is published to the created GitLab instance, and fetched +by example-bin. diff --git a/test/example-bin/.cargo/config.toml b/test/example-bin/.cargo/config.toml new file mode 100644 index 0000000..530a402 100644 --- /dev/null +++ a/test/example-bin/.cargo/config.toml @@ -1,0 +1,2 @@ +[registries] +my-group-example-lib = { index = "ssh://127.0.0.1:2233/root/example-lib" } diff --git a/test/example-bin/src/main.rs b/test/example-bin/src/main.rs new file mode 100644 index 0000000..6a2cb75 100644 --- /dev/null +++ a/test/example-bin/src/main.rs @@ -1,0 +1,3 @@ +fn main() { + eprintln!("{}", example_lib::add(2, 3)); +} diff --git a/test/example-lib/src/lib.rs b/test/example-lib/src/lib.rs new file mode 100644 index 0000000..7d12d9a 100644 --- /dev/null +++ a/test/example-lib/src/lib.rs @@ -1,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} -- rgit 0.1.3