Initial stable.
This commit is contained in:
parent
8fa11d79d3
commit
4815fa00a3
|
@ -1,6 +0,0 @@
|
|||
version: "3.9"
|
||||
services:
|
||||
well-known:
|
||||
build:
|
||||
context: docker/vault
|
||||
image: git.nixc.us/colin/vault:production
|
|
@ -0,0 +1,143 @@
|
|||
labels:
|
||||
hostname: "macmini7"
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
settings:
|
||||
partial: false
|
||||
depth: 1
|
||||
steps:
|
||||
# Build Step for staging Branch
|
||||
build-staging:
|
||||
name: build-staging
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- echo "Building application for staging branch"
|
||||
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||
- echo compose build
|
||||
- docker compose -f docker-compose.staging.yml build
|
||||
when:
|
||||
- branch: main
|
||||
- event: push
|
||||
- path:
|
||||
include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||
|
||||
deploy-new:
|
||||
name: deploy-new
|
||||
when:
|
||||
- branch: main
|
||||
- path:
|
||||
include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||
- echo compose push
|
||||
- docker compose -f docker-compose.staging.yml push
|
||||
# - docker stack deploy --with-registry-auth -c ./stack.staging.yml $${CI_REPO_NAME}-staging
|
||||
|
||||
# # Wait for Deploy to Complete
|
||||
# wait-for-deploy-staging:
|
||||
# name: wait-for-deploy-staging
|
||||
# image: woodpeckerci/plugin-git
|
||||
# commands:
|
||||
# - echo "Waiting for staging deploy step to complete rollout."
|
||||
# - sleep 60
|
||||
# when:
|
||||
# - branch: main
|
||||
# - event: push
|
||||
|
||||
# # Run Automated Tests on staging Branch
|
||||
# test-staging:
|
||||
# name: run-tests-staging
|
||||
# image: git.nixc.us/colin/playwright:latest
|
||||
# secrets: [ base_url ]
|
||||
# when:
|
||||
# - branch: main
|
||||
# - event: push
|
||||
# - path:
|
||||
# include: [ 'tests/', 'src/','docker-compose.staging.yml', 'docker-compose.production.yml', '*.tests.ts' ] # Specify paths relevant to tests
|
||||
# volumes:
|
||||
# - /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
|
||||
cleanup-staging:
|
||||
name: cleanup-staging
|
||||
when:
|
||||
- branch: main
|
||||
- path:
|
||||
include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
# - docker stack rm $${CI_REPO_NAME}-staging
|
||||
## added fault tolerance for docker stack rm
|
||||
# - for i in {1..5}; do docker stack rm ${CI_REPO_NAME}-staging && break || sleep 10; done
|
||||
- docker compose -f docker-compose.staging.yml down
|
||||
- docker compose -f docker-compose.staging.yml rm -f
|
||||
|
||||
# Build Step for staging Branch
|
||||
build-build-push-production:
|
||||
name: build-build-push-production
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- echo "Building application for staging branch"
|
||||
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||
- echo compose build
|
||||
- docker compose -f docker-compose.production.yml build
|
||||
- docker compose -f docker-compose.production.yml push
|
||||
when:
|
||||
- branch: production
|
||||
- event: push
|
||||
- path:
|
||||
include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||
|
||||
# Deploy to Production Branch
|
||||
deploy-production:
|
||||
name: deploy-production
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
|
||||
# - docker stack deploy --with-registry-auth -c ./stack.production.yml $${CI_REPO_NAME}
|
||||
when:
|
||||
- branch: production
|
||||
- event: push
|
||||
# - path:
|
||||
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
||||
|
||||
|
||||
# # Wait for Deploy to Complete
|
||||
# wait-for-deploy-production:
|
||||
# name: wait-for-deploy-production
|
||||
# image: woodpeckerci/plugin-git
|
||||
# commands:
|
||||
# - echo "Waiting for deploy step to complete rollout."
|
||||
# - sleep 60
|
||||
# when:
|
||||
# - branch: production
|
||||
# - event: push
|
||||
|
||||
# # Run Post-Deployment Smoke Tests
|
||||
# post-deploy-smoke-tests-git-nixc-us:
|
||||
# name: run-post-deploy-smoke-tests-git-nixc-us
|
||||
# image: git.nixc.us/colin/playwright:latest
|
||||
# # secrets: [TEST_USER, TEST_PASSWORD]
|
||||
# environment:
|
||||
# - BASE_URL=https://git.nixc.us
|
||||
# when:
|
||||
# - branch: production
|
||||
# - event: push
|
||||
# # - path:
|
||||
# # include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
|
|
@ -0,0 +1,61 @@
|
|||
<!-- #build4 -->
|
||||
# bench plugin
|
||||
|
||||
### Docker Run
|
||||
|
||||
Run the Docker image using the `docker run` command. I'll provide examples for different scenarios:
|
||||
|
||||
1. **Testing a Single URL:**
|
||||
|
||||
```bash
|
||||
docker run -e TARGET_URLS="http://example.com" -e MAX_TIME=1 -e VARIANCE=2 -e TEST_MODE="report" git.nixc.us/colin/bench:production
|
||||
```
|
||||
|
||||
2. **Testing Multiple URLs:**
|
||||
|
||||
```bash
|
||||
docker run -e TARGET_URLS="http://example.com,http://example2.com" -e MAX_TIME=1 -e VARIANCE=2 -e TEST_MODE="report" git.nixc.us/colin/bench:production
|
||||
```
|
||||
|
||||
3. **Using Fail-Fast Mode:**
|
||||
|
||||
```bash
|
||||
docker run -e TARGET_URLS="http://example.com" -e MAX_TIME=1 -e VARIANCE=2 -e TEST_MODE="fail-fast" git.nixc.us/colin/bench:production
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
Example `docker-compose.yml` file that sets up the same configuration:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
apachebench:
|
||||
image: git.nixc.us/colin/bench:production
|
||||
environment:
|
||||
TARGET_URLS: "http://example.com,http://example2.com" # Comma-separated list of URLs
|
||||
MAX_TIME: 1 # Maximum acceptable response time
|
||||
VARIANCE: 2 # Acceptable time variance
|
||||
TEST_MODE: "report" # Can be "report" or "fail-fast"
|
||||
NUM_REQUESTS: 500 # Number of requests to perform
|
||||
CONCURRENCY: 20 # Number of multiple requests to make at a time
|
||||
|
||||
```
|
||||
|
||||
Run the service defined in the `docker-compose.yml` file, use:
|
||||
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
### Customizing the Configuration
|
||||
|
||||
You can modify the `TARGET_URLS`, `MAX_TIME`, `VARIANCE`, and `TEST_MODE` environment variables to suit your specific testing needs. Here's what each variable represents:
|
||||
|
||||
- `TARGET_URLS`: A comma-separated list of URLs to test.
|
||||
- `MAX_TIME`: The target maximum response time in seconds.
|
||||
- `VARIANCE`: The acceptable variance in response time in seconds.
|
||||
- `TEST_MODE`: The mode of operation, either `report` to test all URLs regardless of individual results, or `fail-fast` to stop testing as soon as a URL fails the performance criteria.
|
||||
|
||||
This setup allows you to run performance tests in a Docker environment, providing an automated way to benchmark and analyze the performance of various web services.
|
|
@ -0,0 +1,6 @@
|
|||
version: "3.9"
|
||||
services:
|
||||
bench:
|
||||
build:
|
||||
context: docker/bench
|
||||
image: git.nixc.us/colin/bench:production
|
|
@ -0,0 +1,6 @@
|
|||
version: "3.9"
|
||||
services:
|
||||
bench:
|
||||
build:
|
||||
context: docker/bench
|
||||
image: git.nixc.us/colin/bench:staging
|
|
@ -0,0 +1,5 @@
|
|||
FROM alpine:latest
|
||||
RUN apk --no-cache add apache2-utils curl ca-certificates bash
|
||||
COPY run-ab.sh /run-ab.sh
|
||||
RUN chmod +x /run-ab.sh
|
||||
ENTRYPOINT ["/run-ab.sh"]
|
|
@ -0,0 +1,141 @@
|
|||
#!/bin/bash
|
||||
|
||||
DEFAULT_MAX_TIME=1
|
||||
DEFAULT_VARIANCE=2
|
||||
DEFAULT_TTFB_MAX=500
|
||||
DEFAULT_TEST_MODE="report"
|
||||
DEFAULT_NUM_REQUESTS=100
|
||||
DEFAULT_CONCURRENCY=10
|
||||
|
||||
TARGET_URLS=${TARGET_URLS:-""}
|
||||
MAX_TIME=${MAX_TIME:-$DEFAULT_MAX_TIME}
|
||||
VARIANCE=${VARIANCE:-$DEFAULT_VARIANCE}
|
||||
TTFB_MAX=${TTFB_MAX:-$DEFAULT_TTFB_MAX}
|
||||
TEST_MODE=${TEST_MODE:-$DEFAULT_TEST_MODE}
|
||||
NUM_REQUESTS=${NUM_REQUESTS:-$DEFAULT_NUM_REQUESTS}
|
||||
CONCURRENCY=${CONCURRENCY:-$DEFAULT_CONCURRENCY}
|
||||
|
||||
declare -a failed_urls
|
||||
|
||||
process_sitemap() {
|
||||
IFS=',' read -r -a domains <<< "$TARGET_URLS"
|
||||
for domain in "${domains[@]}"; do
|
||||
|
||||
domain="${domain%/}"
|
||||
sitemap=$(curl -s "${domain}/sitemap.xml")
|
||||
while IFS= read -r loc; do
|
||||
url=$(echo "$loc" | sed -e 's|<loc>||g' -e 's|</loc>||g' | xargs)
|
||||
if [[ "$url" =~ ^https?:// ]]; then
|
||||
new_url="$url"
|
||||
else
|
||||
url="${url#/}"
|
||||
new_url="${domain}/${url}"
|
||||
fi
|
||||
new_url=$(echo "$new_url" | sed -e 's|//|/|g' -e 's|:/|://|')
|
||||
if [[ ! "${TARGET_URLS}" =~ "${new_url}" ]]; then
|
||||
TARGET_URLS+=",${new_url}"
|
||||
fi
|
||||
done < <(echo "$sitemap" | grep -oE "<loc>.+?</loc>")
|
||||
done
|
||||
}
|
||||
|
||||
process_sitemap
|
||||
|
||||
measure_ttfb() {
|
||||
local url=$1
|
||||
local -a times=()
|
||||
local min max sum=0 mean ttfb mean_ttfb
|
||||
for i in {1..5}; do
|
||||
ttfb=$(curl -o /dev/null -s -w '%{time_starttransfer}\n' "$url" | awk '{print $1 * 1000}')
|
||||
times+=("$ttfb")
|
||||
sum=$(echo "$sum + $ttfb" | bc)
|
||||
done
|
||||
min=$(printf '%s\n' "${times[@]}" | sort -n | head -1)
|
||||
max=$(printf '%s\n' "${times[@]}" | sort -n | tail -1)
|
||||
mean=$(echo "scale=3; $sum / 5" | bc)
|
||||
|
||||
echo "$mean"
|
||||
}
|
||||
|
||||
run_ab() {
|
||||
local url=$1
|
||||
local result=$(ab -n $NUM_REQUESTS -c $CONCURRENCY "$url" 2>&1)
|
||||
local avg_time=$(echo "$result" | grep 'Time per request' | head -1 | awk '{print $4}')
|
||||
if [ -z "$avg_time" ] || [ "$(echo "$avg_time > ($MAX_TIME + $VARIANCE) * 1000" | bc)" -eq 1 ]; then
|
||||
echo "ApacheBench test failed for $url. Average time: ${avg_time:-N/A} milliseconds."
|
||||
return 1
|
||||
else
|
||||
echo "ApacheBench test passed for $url. Average time: $avg_time milliseconds."
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
log_file="/log/scan.log"
|
||||
mkdir -p $(dirname "$log_file")
|
||||
cat /dev/null > $"$log_file"
|
||||
|
||||
IFS=',' read -ra URLS <<< "$TARGET_URLS"
|
||||
for url in "${URLS[@]}"; do
|
||||
mean_ttfb=$(measure_ttfb "$url")
|
||||
if [ -z "$mean_ttfb" ] || [ "$(echo "$mean_ttfb > $TTFB_MAX" | bc)" -eq 1 ]; then
|
||||
echo "TTFB test failed for $url. Mean TTFB: ${mean_ttfb}ms exceeds maximum of ${TTFB_MAX}ms." | tee -a "$log_file"
|
||||
failed_urls+=("TTFB failure: $url")
|
||||
else
|
||||
echo "TTFB test passed for $url. Mean TTFB: ${mean_ttfb}ms." | tee -a "$log_file"
|
||||
fi
|
||||
run_ab_result=$(run_ab "$url")
|
||||
echo "$run_ab_result" | tee -a "$log_file"
|
||||
if [[ "$run_ab_result" == *"failed"* ]]; then
|
||||
failed_urls+=("ApacheBench failure: $url")
|
||||
fi
|
||||
if [ "$TEST_MODE" = "fail-fast" ] && [ ${#failed_urls[@]} -gt 0 ]; then
|
||||
echo "Exiting due to fail-fast mode with failures." | tee -a "$log_file"
|
||||
for failed_url in "${failed_urls[@]}"; do
|
||||
echo "- $failed_url" | tee -a "$log_file"
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#failed_urls[@]} -gt 0 ]; then
|
||||
echo "Summary of failed URLs:" | tee -a "$log_file"
|
||||
for failed_url in "${failed_urls[@]}"; do
|
||||
echo "- $failed_url" | tee -a "$log_file"
|
||||
done
|
||||
exit 1
|
||||
else
|
||||
echo "All URLs passed the performance and TTFB tests." | tee -a "$log_file"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
parse_to_csv() {
|
||||
local input="$1"
|
||||
local output="$2"
|
||||
: > "$output"
|
||||
grep -Eo 'https?://[^ ]+' "$input" | sort -u | while read -r url; do
|
||||
local ttfb_line=$(grep -m 1 "$url" "$input" | grep 'TTFB test passed' | awk -F'Mean TTFB: ' '{print $2}')
|
||||
local ab_line=$(grep -m 1 "$url" "$input" | grep 'ApacheBench test passed' | awk -F'Average time: ' '{print $2}')
|
||||
local ttfb_test=${ttfb_line%ms.*}
|
||||
local ab_test=${ab_line% milliseconds.*}
|
||||
if [[ -n "$ttfb_test" || -n "$ab_test" ]]; then
|
||||
if [[ -z "$ttfb_test" ]]; then ttfb_test="N/A"; fi
|
||||
if [[ -z "$ab_test" ]]; then ab_test="N/A"; fi
|
||||
echo "$url,$ttfb_test,$ab_test" >> "$output"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
parse_to_csv "/logs/scan.log" "/logs/scan.csv"
|
||||
|
||||
upload_to_hastebin() {
|
||||
local file=$1
|
||||
local haste_url="https://haste.nixc.us/documents"
|
||||
local response=$(curl -X POST -s --data-binary @"$file" $haste_url)
|
||||
local key=$(echo $response | awk -F '"' '{print $4}')
|
||||
if [[ ! -z "$key" ]]; then
|
||||
echo "Uploaded to hastebin: https://haste.nixc.us/$key"
|
||||
else
|
||||
echo "Failed to upload to hastebin."
|
||||
fi
|
||||
}
|
||||
upload_to_hastebin "/logs/scan.csv"
|
Loading…
Reference in New Issue