🏡 index : ~doyle/gitlab-cargo-shim.git

author jordan <jordan@doyle.la> 2023-11-14 14:26:07.0 +00:00:00
committer GitHub <noreply@github.com> 2023-11-14 14:26:07.0 +00:00:00
commit
53ad5a6f3a5fbe74bd547eb1691919d912a8c8da [patch]
tree
1952c093e1c54ec7af2d3335d5ae3533167f069e
parent
6a50d80abbfcbdd844916769739dd432c8f4c80a
download
53ad5a6f3a5fbe74bd547eb1691919d912a8c8da.tar.gz

Add smoke test (#60)



Diff

 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);
    }
}