Skip to content

Instantly share code, notes, and snippets.

@apiraino
Last active August 17, 2019 09:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apiraino/5027c045b0a7f937032ac6af975e4724 to your computer and use it in GitHub Desktop.
Save apiraino/5027c045b0a7f937032ac6af975e4724 to your computer and use it in GitHub Desktop.
Rust stable CircleCI config file (with sccache + rustfmt + clippy)
version: 2.1
commands:
install-system-deps:
steps:
- run:
name: Apt get stuff
command: |
# for codecov
# sudo apt install -y libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc binutils-dev libiberty-dev
sudo apt install memcached -y
setup-proxy:
steps:
- run:
name: Install mitm
command: |
if [ ! -d "$HOME/bin" ]; then
mkdir "$HOME/bin"
export PATH=$PATH:$HOME/bin
fi
sh ./scripts/get-mitm.sh
setup-sccache:
steps:
- run:
name: Install sccache
command: |
if [ ! -d "$HOME/bin" ]; then
mkdir "$HOME/bin"
export PATH=$PATH:$HOME/bin
fi
sh ./scripts/get-sccache.sh
# This configures Rust to use sccache.
echo 'export "RUSTC_WRAPPER"="sccache"' >> $BASH_ENV
# This is the maximum space sccache cache will use on disk.
echo 'export "SCCACHE_CACHE_SIZE"="1G"' >> $BASH_ENV
restore-sccache-cache:
steps:
- restore_cache:
name: Restore sccache cache
key: sccache-cache-stable-{{ arch }}-{{ .Environment.CIRCLE_JOB }}
save-sccache-cache:
steps:
- save_cache:
name: Save sccache cache
# We use {{ epoch }} to always upload a fresh cache:
# Of course, restore_cache will not find this exact key,
# but it will fall back to the closest key (aka the most recent).
# See https://discuss.circleci.com/t/add-mechanism-to-update-existing-cache-key/9014/13
key: sccache-cache-stable-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ epoch }}
paths:
- "~/.cache/sccache"
run-code-coverage:
steps:
- run:
name: Running code coverage
command: |
./scripts/codecov.sh
jobs:
rust-tests:
docker:
- image: circleci/rust:latest
steps:
- checkout
- install-system-deps
- setup-proxy
- setup-sccache
- restore-sccache-cache
- save-sccache-cache
- run:
name: Version information
command: |
rustc --version
cargo --version
rustup --version
sccache --version
mitmdump --version
python --version
- run:
name: Run rustfmt
command: |
rustup component add rustfmt
cargo fmt -- --check
- run:
name: Run clippy
command: |
rustup component add clippy
cargo clippy --all
- run:
name: Run memcached
background: true
command: |
sudo /etc/init.d/memcached restart
- run:
name: Run mitm
background: true
command: |
cd tests/files && mitmdump --scripts send_reply_from_proxy.py
- run:
name: Run server
environment:
DEPLOY_MODE: test
RUST_BACKTRACE: 1
background: true
command: |
RUST_LOG=worker=debug nohup cargo run --features=proxy_requests
- run:
name: Check listening services
command: |
netstat -tan | grep LISTEN
- run:
name: Run tests
environment:
DEPLOY_MODE: test
RUST_BACKTRACE: 1
RUST_TEST_THREADS: 1
RUST_TEST_NOCAPTURE: 1
PROXY_HOST: http://localhost
PROXY_PORT: 8080
TEST_SERVER: http://localhost:3000
command: |
export PATH=$PATH:$HOME/bin
cargo test --features=proxy_requests --all
- run:
name: Post-mortem checks
command: |
sh ./scripts/post-mortem.sh
# - run-code-coverage
rust-coverage-docker:
docker:
- image: ragnaroek/kcov_head:latest
steps:
- run:
name: Run code coverage
command: |
ls target/debug/ || echo "notfound" &&
for file in $(ls -1 target/debug | grep "-" | grep -v "\.d$");
do
mkdir -p "target/cov/$(basename $file)";
kcov --exclude-pattern=/.cargo,/usr/lib
--verify "target/cov/$(basename $file)"
"target/debug/$file";
done
workflows:
version: 2
run-tests:
jobs:
- rust-tests
@apiraino
Copy link
Author

Lines 94-126 detail how I've included a proxy server to return mocked responses to API requests to external services

@apiraino
Copy link
Author

The client that performs external call has compile flag to use the proxy. Code looks like this

    pub fn new() -> Self {
        let http_connector = HttpConnector::new(4);
        let https_connector = HttpsConnector::new(4).expect("TLS initialization failed");
        let proxy = {
            let proxy_uri =
                format!("{}:{}", get_env!("PROXY_HOST"), get_env!("PROXY_PORT")).parse().unwrap();
            let proxy = Proxy::new(Intercept::All, proxy_uri);
            // My proxy is on plain HTTP
            let proxy_connector = ProxyConnector::from_proxy_unsecured(http_connector, proxy);
            proxy_connector
        };

        // When running tests and CI builds, the server is run with "--features=proxy_requests"
        #[cfg(feature = "proxy_requests")]
        let client = Client::builder().build::<_, hyper::Body>(proxy);

        // In real life, server is run without proxied connections
        #[cfg(not(feature = "proxy_requests"))]
        let client = Client::builder().build::<_, hyper::Body>(https_connector);

        MyClient { client }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment