├── .gitattributes
├── .github
├── assets
│ └── images
│ │ └── inputs.png
├── dependabot.yml
└── workflows
│ ├── ci-auto-rerun-failed-jobs-action.yml
│ ├── ci-check-for-new-release-tag.yml
│ ├── ci-checks.yml
│ ├── ci-docker.yml
│ ├── ci-linux-crossbuild.yml
│ ├── ci-linux-emulation.yml
│ ├── ci-main-reusable-caller.yml
│ ├── ci-osx.yml
│ ├── ci-release.yml
│ ├── ci-windows.yml
│ └── test.yml
├── .gitignore
├── Dockerfile
├── LICENSE.txt
├── README.md
├── ci-cygwin-installer-packages.cmd
├── ci-cygwin-installer.cmd
├── ci-linux-crossbuild.sh
├── ci-release-body.md
├── ci-windows-cygwin-build.sh
├── pwsh-here.cmd
└── zizmor.yml
/.gitattributes:
--------------------------------------------------------------------------------
1 | * -text
--------------------------------------------------------------------------------
/.github/assets/images/inputs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/userdocs/iperf3-static/34a4877ff16b717a88d732d648d261475c6798f2/.github/assets/images/inputs.png
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependencies for GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "daily"
8 |
--------------------------------------------------------------------------------
/.github/workflows/ci-auto-rerun-failed-jobs-action.yml:
--------------------------------------------------------------------------------
1 | name: ci - auto rerun failed jobs
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | run_id:
7 | description: "The run id of the workflow to rerun"
8 | required: true
9 | attempts:
10 | description: "The number of attempts to rerun the workflow"
11 | required: true
12 | retries:
13 | description: "The number of retries to rerun the workflow"
14 | required: true
15 | github_repo:
16 | description: "The repository to rerun the workflow"
17 | required: false
18 | distinct_id:
19 | description: "The distinct id of the workflow to rerun"
20 | required: false
21 |
22 | run-name: ci auto rerun failed jobs - attempt ${{ inputs.attempts }}
23 |
24 | jobs:
25 | gh-cli-rerun:
26 | name: rerun - attempt ${{ inputs.attempts }}
27 | permissions:
28 | actions: write
29 | runs-on: ubuntu-24.04-arm
30 | env:
31 | GH_TOKEN: "${{ secrets.AUTO_RERUN || github.token }}"
32 | steps:
33 | - name: Host - Checkout action ${{ inputs.distinct_id }}
34 | uses: actions/checkout@v4
35 | with:
36 | persist-credentials: false
37 |
38 | - uses: userdocs/gh-cli-workflow-reruns/actions/auto-rerun-failed@main
39 | with:
40 | run_id: ${{ inputs.run_id }}
41 | attempts: ${{ inputs.attempts }}
42 | retries: ${{ inputs.retries }}
43 | github_repo: ${{ inputs.github_repo || github.repository }}
44 | distinct_id: ${{ inputs.distinct_id || github.run_id }}
45 |
--------------------------------------------------------------------------------
/.github/workflows/ci-check-for-new-release-tag.yml:
--------------------------------------------------------------------------------
1 | name: ci - check for new iperf3 release tag
2 |
3 | on:
4 | workflow_call:
5 | outputs:
6 | continue_build:
7 | value: ${{ jobs.check_release.outputs.continue_build }}
8 | iperf3_tag:
9 | value: ${{ jobs.check_release.outputs.iperf3_tag }}
10 |
11 | env:
12 | GH_TOKEN: "${{ github.TOKEN }}"
13 |
14 | jobs:
15 | check_release:
16 | outputs:
17 | continue_build: ${{ steps.continue_build_check.outputs.continue_build_choice }}
18 | iperf3_tag: ${{ steps.continue_build_check.outputs.iperf3_tag }}
19 | runs-on: ubuntu-24.04-arm
20 |
21 | steps:
22 | # Checkout the code
23 | - name: Checkout code
24 | uses: actions/checkout@v4
25 | with:
26 | persist-credentials: false
27 |
28 | - name: Get latest esnet/iperf tag
29 | run: printf '%s\n' "upstream_iperf3_tag=$(git ls-remote -q -t --refs "https://github.com/esnet/iperf.git" | awk '{sub("refs/tags/", ""); if ($2 ~ /^[0-9]+(\.[0-9]+)*$/) print $2 }' | sort -rV | awk '!/^$/' | head -n 1)" >> $GITHUB_ENV
30 |
31 | - name: Get latest ${{ github.repository }} tag
32 | run: printf '%s\n' "local_iperf3_tag=$(git ls-remote -q -t --refs "https://github.com/${{ github.repository }}.git" | awk '{sub("refs/tags/", ""); if ($2 ~ /^[0-9]+(\.[0-9]+)*$/) print $2 }' | sort -rV | awk '!/^$/' | head -n 1)" >> $GITHUB_ENV
33 |
34 | - name: Test values - latest upstream vs local tags
35 | id: continue_build_check
36 | run: |
37 | ver() {
38 | local test_array
39 | read -ra test_array < <(printf "%s" "${@//./ }")
40 | printf "%d%03d%03d%03d" "${test_array[@]}"
41 | }
42 |
43 | local_iperf3_tag="${{ env.local_iperf3_tag }}"
44 |
45 | if [[ "$(ver "${{ env.upstream_iperf3_tag }}")" -gt "$(ver "${local_iperf3_tag//+/}")" ]]; then
46 | printf "%-14s remote:%-10s local:%-10s %s\n" "$iray" "${{ env.upstream_iperf3_tag }}" "${local_iperf3_tag//+/}" "< New version available - workflow will be triggered"
47 | printf '%s\n' "continue_build_choice=yes" >> $GITHUB_OUTPUT
48 | printf '%s\n' "iperf3_tag=${{ env.upstream_iperf3_tag }}" >> $GITHUB_OUTPUT
49 | else
50 | printf "%-14s remote:%-10s local:%-10s\n" "$iray" "${{ env.upstream_iperf3_tag }}" "${local_iperf3_tag//+/}"
51 | fi
52 |
--------------------------------------------------------------------------------
/.github/workflows/ci-checks.yml:
--------------------------------------------------------------------------------
1 | name: ci - checks
2 | on:
3 | push:
4 | pull_request:
5 | workflow_dispatch:
6 |
7 | concurrency:
8 | group: ${{ github.workflow }}-${{ github.ref }}
9 | cancel-in-progress: true
10 |
11 | jobs:
12 | sh-checker:
13 | runs-on: ubuntu-24.04-arm
14 | permissions:
15 | contents: read
16 | steps:
17 | - uses: actions/checkout@v4
18 | with:
19 | persist-credentials: false
20 |
21 | - name: Run the sh-checker
22 | uses: luizm/action-sh-checker@v0.9.0
23 | env:
24 | GITHUB_TOKEN: ${{ github.token }}
25 | SHELLCHECK_OPTS: -e SC2034,SC1091 # It is possible to exclude some shellcheck warnings.
26 | SHFMT_OPTS: -ci -sr -i 0 # It is possible to pass arguments to shftm
27 | with:
28 | sh_checker_comment: true
29 | sh_checker_exclude: ""
30 |
31 | zizmor-checker:
32 | runs-on: ubuntu-24.04-arm
33 | permissions:
34 | contents: read
35 | steps:
36 | - uses: actions/checkout@v4
37 | with:
38 | persist-credentials: false
39 |
40 | - name: Check GitHub Action workflows
41 | shell: bash {0}
42 | run: |
43 | pip install zizmor
44 |
45 | zizmor="$(zizmor . --gh-token "${{ github.token }}")"
46 | exit_code="$?"
47 |
48 | printf '%s\n' "$zizmor"
49 |
50 | printf '%b\n' "\`\`\`" >> $GITHUB_STEP_SUMMARY
51 | printf '%s\n' "$zizmor" >> $GITHUB_STEP_SUMMARY
52 | printf '%b' "\`\`\`" >> $GITHUB_STEP_SUMMARY
53 |
54 | exit "$exit_code"
55 |
56 | editorconfig-checker:
57 | runs-on: ubuntu-24.04-arm
58 | permissions:
59 | contents: read
60 | steps:
61 | - uses: actions/checkout@v4
62 | with:
63 | persist-credentials: false
64 |
65 | - name: editorconfig-checker
66 | env:
67 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
68 | run: |
69 | curl -Lo- "https://github.com/editorconfig-checker/editorconfig-checker/releases/latest/download/ec-linux-amd64.tar.gz" | tar xzf - --strip-components=1
70 |
71 | printf '%b\n' "\`\`\`" >> $GITHUB_STEP_SUMMARY
72 | ./ec-linux-amd64 --exclude '^(docs/.*|patches/.*)$' | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" >> $GITHUB_STEP_SUMMARY
73 | exit_code=("${PIPESTATUS[0]}")
74 | printf '%b' "\`\`\`" >> $GITHUB_STEP_SUMMARY
75 |
76 | # exit "${exit_code}"
77 |
--------------------------------------------------------------------------------
/.github/workflows/ci-docker.yml:
--------------------------------------------------------------------------------
1 | name: ci - linux docker build
2 |
3 | on:
4 | workflow_call:
5 |
6 | env:
7 | DOCKERHUB_REPO: ${{ github.repository }}
8 | GHCR_REPO: ghcr.io/${{ github.repository }}
9 | SET_IMAGE_TAG: latest
10 | GH_TOKEN: ${{ github.token }}
11 |
12 | jobs:
13 | build:
14 | runs-on: ubuntu-24.04-arm
15 | outputs:
16 | latest_tag: ${{ steps.gh_latest_tag.outputs.latest_tag }}
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | arch: [amd64, arm32v6, arm32v7, arm64v8, i386, ppc64le, riscv64, s390x]
21 | include:
22 | - arch: amd64
23 | platform: linux/amd64
24 | - arch: arm32v6
25 | platform: linux/arm/v6
26 | - arch: arm32v7
27 | platform: linux/arm/v7
28 | - arch: arm64v8
29 | platform: linux/arm64
30 | - arch: i386
31 | platform: linux/386
32 | - arch: ppc64le
33 | platform: linux/ppc64le
34 | - arch: riscv64
35 | platform: linux/riscv64
36 | - arch: s390x
37 | platform: linux/s390x
38 |
39 | steps:
40 | - name: Checkout code
41 | uses: actions/checkout@v4
42 | with:
43 | persist-credentials: false
44 |
45 | - name: Fetch latest GitHub tag
46 | id: gh_latest_tag
47 | run: |
48 | latest_tag="$(gh release list --json tagName -L 1 -q '.[0].tagName')"
49 | printf '%s\n' "latest_tag=${latest_tag//+/-dev}" >> "$GITHUB_ENV"
50 | printf '%s\n' "latest_tag=${latest_tag//+/-dev}" >> "$GITHUB_OUTPUT"
51 |
52 | - name: Prepare
53 | run: |
54 | platform=${{ matrix.platform }}
55 | printf '%s\n' "matrix_platform_hypens=${platform//\//-}" >> $GITHUB_ENV
56 |
57 | - name: Docker meta
58 | id: meta
59 | uses: docker/metadata-action@v5
60 | with:
61 | images: ${{ env.GHCR_REPO }}
62 |
63 | - name: Login to GHCR
64 | uses: docker/login-action@v3
65 | with:
66 | registry: ghcr.io
67 | username: ${{ github.repository_owner }}
68 | password: ${{ github.token }}
69 |
70 | - name: Set up QEMU
71 | uses: docker/setup-qemu-action@v3
72 |
73 | - name: Set up Docker Buildx
74 | uses: docker/setup-buildx-action@v3
75 | with:
76 | cache-binary: false
77 |
78 | - name: Build and push by digest
79 | id: build
80 | uses: docker/build-push-action@v6
81 | with:
82 | context: .
83 | platforms: ${{ matrix.platform }}
84 | provenance: false
85 | push: true
86 | tags: ${{ env.GHCR_REPO }}:${{ steps.meta.outputs.version }}
87 | labels: ${{ steps.meta.outputs.labels }}
88 | no-cache: true
89 | build-args: |
90 | ARCH=${{ matrix.arch }}
91 | REPO=${{ github.repository }}
92 |
93 | - name: Export digest
94 | env:
95 | digest: ${{ steps.build.outputs.digest }}
96 | run: |
97 | mkdir -p ${{ runner.temp }}/digests
98 | digest="${digest}"
99 | touch "${{ runner.temp }}/digests/${digest#sha256:}"
100 |
101 | - name: Upload digest
102 | uses: actions/upload-artifact@v4
103 | with:
104 | name: digests-${{ env.matrix_platform_hypens }}
105 | path: ${{ runner.temp }}/digests/*
106 | if-no-files-found: error
107 |
108 | merge:
109 | runs-on: ubuntu-24.04-arm
110 | needs: build
111 | env:
112 | latest_tag: ${{ needs.build.outputs.latest_tag }}
113 | steps:
114 | - name: Download digests
115 | uses: actions/download-artifact@v4
116 | with:
117 | path: ${{ runner.temp }}/digests
118 | pattern: digests-*
119 | merge-multiple: true
120 |
121 | - name: Login to GHCR
122 | uses: docker/login-action@v3
123 | with:
124 | registry: ghcr.io
125 | username: ${{ github.repository_owner }}
126 | password: ${{ github.token }}
127 |
128 | - name: Set up Docker Buildx
129 | uses: docker/setup-buildx-action@v3
130 | with:
131 | cache-binary: false
132 |
133 | - name: Docker meta
134 | id: meta
135 | uses: docker/metadata-action@v5
136 | with:
137 | images: ${{ env.GHCR_REPO }}
138 |
139 | - name: Create manifest list and push latest
140 | working-directory: ${{ runner.temp }}/digests
141 | run: |
142 | ghcr_digests=$(for digest in *; do printf '%s@sha256:%s ' "${GHCR_REPO}" "${digest}"; done)
143 | docker buildx imagetools create -t ${GHCR_REPO}:latest ${ghcr_digests}
144 |
145 | - name: Create manifest list and push (version)
146 | working-directory: ${{ runner.temp }}/digests
147 | run: |
148 | ghcr_digests=$(for digest in *; do printf '%s@sha256:%s ' "${GHCR_REPO}" "${digest}"; done)
149 | docker buildx imagetools create -t ${GHCR_REPO}:${latest_tag} ${ghcr_digests}
150 |
151 | - name: Inspect image
152 | run: |
153 | docker buildx imagetools inspect ${GHCR_REPO}:latest
154 | docker buildx imagetools inspect ${GHCR_REPO}:${latest_tag}
155 |
--------------------------------------------------------------------------------
/.github/workflows/ci-linux-crossbuild.yml:
--------------------------------------------------------------------------------
1 | name: ci - linux binary cross build
2 |
3 | on:
4 | workflow_call:
5 | outputs:
6 | release_tags:
7 | value: ${{ jobs.build.outputs.release_tags }}
8 | inputs:
9 | source_repo:
10 | type: string
11 | required: true
12 | source_branch:
13 | type: string
14 | required: true
15 | secrets:
16 | VT_API_KEY:
17 | required: false
18 |
19 | env:
20 | GH_TOKEN: "${{ github.TOKEN }}"
21 |
22 | jobs:
23 | build:
24 | runs-on: ubuntu-24.04-arm
25 | outputs:
26 | release_tags: ${{ steps.release_tags.outputs.release_tag }}
27 | strategy:
28 | fail-fast: false
29 | matrix:
30 | name: [iperf3]
31 | os_id: [alpine]
32 | os_version_id: [edge]
33 | arch: [x86, x86_64, armhf, armv7, aarch64, ppc64le, riscv64, s390x]
34 | include:
35 | - arch: x86
36 | qbt-musl-cross-make: "i686-linux-musl"
37 | release_name: i386
38 | - arch: x86_64
39 | qbt-musl-cross-make: "x86_64-linux-musl"
40 | release_name: amd64
41 | - arch: armhf
42 | qbt-musl-cross-make: "armv6-linux-musleabihf"
43 | release_name: arm32v6
44 | - arch: armv7
45 | qbt-musl-cross-make: "armv6-linux-musleabihf"
46 | release_name: arm32v7
47 | - arch: armv7
48 | qbt-musl-cross-make: "armv7l-linux-musleabihf"
49 | - arch: aarch64
50 | qbt-musl-cross-make: "aarch64-linux-musl"
51 | release_name: arm64v8
52 | - arch: ppc64le
53 | qbt-musl-cross-make: "powerpc64le-linux-musl"
54 | release_name: ppc64le
55 | - arch: riscv64
56 | qbt-musl-cross-make: "riscv64-linux-musl"
57 | release_name: riscv64
58 | - arch: s390x
59 | qbt-musl-cross-make: "s390x-linux-musl"
60 | release_name: s390x
61 |
62 | name: ${{ matrix.name }} ${{ matrix.os_id }}:${{ matrix.os_version_id }} ${{ matrix.arch }}
63 |
64 | env:
65 | CDN: http://dl-cdn.alpinelinux.org/alpine/edge/main/
66 | CXXFLAGS: "--static -static"
67 | CPPFLAGS: "--static -static"
68 | LDFLAGS: "--static -static"
69 | source_repo: ${{ inputs.source_repo }}
70 | source_branch: ${{ inputs.source_branch }}
71 | container_name: mcm
72 |
73 | steps:
74 | - name: Checkout
75 | uses: actions/checkout@v4
76 | with:
77 | persist-credentials: false
78 |
79 | - name: Host - Bootstrap qemu
80 | uses: userdocs/actions/qemu@main
81 |
82 | - name: Create docker ${{ env.container_name }} ${{ matrix.platform }} container
83 | run: >
84 | docker run --name ${container_name} -it -d -w /home/gh -v ${{ github.workspace }}:/home/gh
85 | -e CXXFLAGS="${{ env.CXXFLAGS }}"
86 | -e CPPFLAGS="${{ env.CPPFLAGS }}"
87 | -e LDFLAGS="${{ env.LDFLAGS }}"
88 | ghcr.io/userdocs/qbt-musl-cross-make:${{ matrix.qbt-musl-cross-make }}
89 |
90 | - name: Run apk update
91 | run: docker exec ${container_name} apk update
92 |
93 | - name: Run apk upgrade
94 | run: docker exec ${container_name} apk upgrade
95 |
96 | - name: run ci-linux-crossbuild.sh
97 | run: docker exec -u gh:gh ${container_name} /bin/bash /home/gh/ci-linux-crossbuild.sh ${source_repo} ${source_branch} ${{ matrix.qbt-musl-cross-make }} ${{ matrix.arch }}
98 |
99 | - name: Rename ${{ matrix.name }} to ${{ matrix.name }}-${{ matrix.release_name }}
100 | run: docker exec -u gh:gh ${container_name} mv -f /home/gh/local/bin/${{ matrix.name }} /home/gh/${{ matrix.name }}-${{ matrix.release_name }}
101 |
102 | - name: Create path to binary env
103 | run: printf '%s\n' "binary_path=${{ github.workspace }}/${{ matrix.name }}-${{ matrix.release_name }}" >> $GITHUB_ENV
104 |
105 | - name: VirusTotal Scan
106 | id: virustotal
107 | uses: crazy-max/ghaction-virustotal@v4
108 | with:
109 | vt_api_key: ${{ secrets.VT_API_KEY }}
110 | files: ${{ env.binary_path }}
111 |
112 | - name: sha256sum
113 | run: |
114 | printf '%s' https://www.virustotal.com/gui/file/$(sha256sum ${{ env.binary_path }} | awk '{print $1}') > ${{ matrix.name }}-${{ matrix.release_name }}.url
115 | cat ${{ matrix.name }}-${{ matrix.release_name }}.url
116 |
117 | - name: Create tag env
118 | run: printf '%s\n' "release_tag=$(sed -rn 's|(.*)\[(.*)],\[https://github.com/esnet/iperf],(.*)|\2|p' ${{ matrix.name }}/configure.ac)" >> $GITHUB_ENV
119 |
120 | - name: Set tag env to output
121 | id: release_tags
122 | run: printf '%s\n' "release_tag=${{ env.release_tag }}" >> "$GITHUB_OUTPUT"
123 |
124 | - name: Generate artifact attestation
125 | uses: actions/attest-build-provenance@v2
126 | with:
127 | subject-path: ${{ env.binary_path }}
128 |
129 | - name: "Create artifact"
130 | uses: actions/upload-artifact@v4
131 | with:
132 | name: ${{ matrix.name }}-${{ matrix.release_name }}
133 | path: |
134 | ${{ env.binary_path }}
135 | ${{ matrix.name }}-${{ matrix.release_name }}.url
136 |
--------------------------------------------------------------------------------
/.github/workflows/ci-linux-emulation.yml:
--------------------------------------------------------------------------------
1 | name: ci - linux binary emulation build
2 |
3 | on:
4 | workflow_call:
5 | outputs:
6 | release_tags:
7 | value: ${{ jobs.build.outputs.release_tags }}
8 | inputs:
9 | source_repo:
10 | type: string
11 | required: true
12 | source_branch:
13 | type: string
14 | required: true
15 | secrets:
16 | VT_API_KEY:
17 | required: false
18 |
19 | env:
20 | GH_TOKEN: "${{ github.TOKEN }}"
21 |
22 | jobs:
23 | build:
24 | runs-on: ubuntu-24.04-arm
25 | outputs:
26 | release_tags: ${{ steps.release_tags.outputs.release_tag }}
27 | strategy:
28 | fail-fast: false
29 | matrix:
30 | name: [iperf3]
31 | os_id: [alpine]
32 | os_version_id: [edge]
33 | arch: [amd64, arm32v6, arm32v7, arm64v8, i386, ppc64le, riscv64, s390x]
34 | include:
35 | - arch: amd64
36 | platform: linux/amd64
37 | - arch: arm32v6
38 | platform: linux/arm/v6
39 | - arch: arm32v7
40 | platform: linux/arm/v7
41 | - arch: arm64v8
42 | platform: linux/arm64
43 | - arch: i386
44 | platform: linux/i386
45 | - arch: ppc64le
46 | platform: linux/ppc64le
47 | - arch: riscv64
48 | platform: linux/riscv64
49 | - arch: s390x
50 | platform: linux/s390x
51 |
52 | name: ${{ matrix.name }} ${{ matrix.os_id }}:${{ matrix.os_version_id }} ${{ matrix.arch }}
53 |
54 | env:
55 | CDN: http://dl-cdn.alpinelinux.org/alpine/edge/main/
56 | CXXFLAGS: "--static -static"
57 | CPPFLAGS: "--static -static"
58 | LDFLAGS: "--static -static"
59 | source_repo: ${{ inputs.source_repo }}
60 | source_branch: ${{ inputs.source_branch }}
61 | container_name: mcm
62 |
63 | steps:
64 | - name: Checkout
65 | uses: actions/checkout@v4
66 | with:
67 | persist-credentials: false
68 |
69 | - name: Host - Bootstrap qemu
70 | uses: userdocs/actions/qemu@main
71 |
72 | - name: Create docker ${{ env.container_name }} ${{ matrix.platform }} container
73 | run: >
74 | docker run --name ${container_name} -it -d -w /home/gh -v ${{ github.workspace }}:/home/gh --platform ${{ matrix.platform }}
75 | -e CXXFLAGS="${{ env.CXXFLAGS }}"
76 | -e CPPFLAGS="${{ env.CPPFLAGS }}"
77 | -e LDFLAGS="${{ env.LDFLAGS }}"
78 | ${{ matrix.arch }}/${{ matrix.os_id }}:${{ matrix.os_version_id }}
79 |
80 | docker exec ${container_name} sh -c 'adduser -h /home/gh -Ds /bin/bash -u 1001 gh && apk add sudo'
81 | docker exec ${container_name} sh -c 'printf "%s" "gh ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/gh'
82 |
83 | - name: Run apk update
84 | run: docker exec ${container_name} apk update
85 |
86 | - name: Run apk upgrade
87 | run: docker exec ${container_name} apk upgrade
88 |
89 | - name: Run apk to install the core build dependencies
90 | run: docker exec ${container_name} apk add build-base pkgconf autoconf automake curl libtool git tar curl perl openssl-dev openssl-libs-static linux-headers
91 |
92 | - name: Git clone ${{ matrix.name }}
93 | run: docker exec -u gh:gh ${container_name} git clone --no-tags --single-branch --branch "${source_branch}" --shallow-submodules --recurse-submodules -j"$(nproc)" --depth 1 "${source_repo}" /home/gh/${{ matrix.name }}
94 |
95 | - name: Configure ${{ matrix.name }}
96 | run: docker exec -u gh:gh -w /home/gh/${{ matrix.name }} ${container_name} ./configure --disable-shared --with-openssl=/usr --enable-static-bin --prefix=/home/gh
97 |
98 | - name: Make Build ${{ matrix.name }}
99 | run: docker exec -u gh:gh -w /home/gh/${{ matrix.name }} ${container_name} make -j$(nproc)
100 |
101 | - name: Make Install Build ${{ matrix.name }}
102 | run: docker exec -u gh:gh -w /home/gh/${{ matrix.name }} ${container_name} make install
103 |
104 | - name: Rename ${{ matrix.name }} to ${{ matrix.name }}-${{ matrix.arch }}
105 | run: docker exec -u gh:gh ${container_name} mv -f /home/gh/bin/${{ matrix.name }} /home/gh/${{ matrix.name }}-${{ matrix.arch }}
106 |
107 | - name: Create path to binary env
108 | run: printf '%s\n' "binary_path=${{ github.workspace }}/${{ matrix.name }}-${{ matrix.arch }}" >> $GITHUB_ENV
109 |
110 | - name: VirusTotal Scan
111 | id: virustotal
112 | uses: crazy-max/ghaction-virustotal@v4
113 | with:
114 | vt_api_key: ${{ secrets.VT_API_KEY }}
115 | files: ${{ env.binary_path }}
116 |
117 | - name: sha256sum
118 | run: |
119 | printf '%s' https://www.virustotal.com/gui/file/$(sha256sum ${{ env.binary_path }} | awk '{print $1}') > ${{ matrix.name }}-${{ matrix.arch }}.url
120 | cat ${{ matrix.name }}-${{ matrix.arch }}.url
121 |
122 | - name: Create tag env
123 | run: printf '%s\n' "release_tag=$(sed -rn 's|(.*)\[(.*)],\[https://github.com/esnet/iperf],(.*)|\2|p' ${{ matrix.name }}/configure.ac)" >> $GITHUB_ENV
124 |
125 | - name: Set tag env to output
126 | id: release_tags
127 | run: printf '%s\n' "release_tag=${{ env.release_tag }}" >> "$GITHUB_OUTPUT"
128 |
129 | - name: Generate artifact attestation
130 | uses: actions/attest-build-provenance@v2
131 | with:
132 | subject-path: ${{ env.binary_path }}
133 |
134 | - name: "Create artifact"
135 | uses: actions/upload-artifact@v4
136 | with:
137 | name: ${{ matrix.name }}-${{ matrix.arch }}
138 | path: |
139 | ${{ env.binary_path }}
140 | ${{ matrix.name }}-${{ matrix.arch }}.url
141 |
--------------------------------------------------------------------------------
/.github/workflows/ci-main-reusable-caller.yml:
--------------------------------------------------------------------------------
1 | name: ci - main reusable caller
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | source_repo:
7 | description: "Define the git repo used for the build"
8 | required: true
9 | default: "https://github.com/esnet/iperf.git"
10 | source_branch:
11 | description: "Specify the branch or tag to build"
12 | required: true
13 | default: "master"
14 | skip_new_tag_check:
15 | description: "Bypass new tag check to force build?"
16 | required: true
17 | default: false
18 | type: boolean
19 | linux_build_type:
20 | description: "Build Linux iperf3 via crossbuild"
21 | required: true
22 | default: false
23 | type: boolean
24 | artifacts_only:
25 | description: "Skip release - artifacts only"
26 | required: true
27 | default: false
28 | type: boolean
29 | linux:
30 | description: "Skip Linux build"
31 | type: boolean
32 | required: true
33 | default: false
34 | windows:
35 | description: "Skip Windows build"
36 | type: boolean
37 | required: true
38 | default: false
39 | osx:
40 | description: "Skip OSX builds"
41 | type: boolean
42 | required: true
43 | default: false
44 | skip_rerun:
45 | description: "Skip rerun?"
46 | required: true
47 | default: false
48 | type: boolean
49 | retries:
50 | description: "Number of rerun retries"
51 | required: true
52 | default: "2"
53 | type: choice
54 | options: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
55 |
56 | schedule:
57 | - cron: "*/5 * * * *" # every 5 minutes
58 |
59 | permissions: {}
60 |
61 | env:
62 | GH_TOKEN: "${{ github.TOKEN }}"
63 |
64 | jobs:
65 | skip_duplicate_job:
66 | runs-on: ubuntu-24.04-arm
67 | permissions:
68 | actions: write
69 | contents: read
70 | outputs:
71 | should_skip: ${{ steps.skip_check.outputs.should_skip }}
72 | steps:
73 | - id: skip_check
74 | uses: fkirc/skip-duplicate-actions@v5
75 | with:
76 | concurrent_skipping: "always"
77 | cancel_others: "false"
78 | skip_after_successful_duplicate: false
79 | do_not_skip: ""
80 |
81 | scheduled_defaults:
82 | if: needs.skip_duplicate_job.outputs.should_skip != 'true'
83 | needs: skip_duplicate_job
84 | runs-on: ubuntu-24.04-arm
85 | permissions:
86 | contents: read
87 | outputs:
88 | source_repo: ${{ github.event.inputs.source_repo || 'https://github.com/esnet/iperf.git' }}
89 | source_branch: ${{ github.event.inputs.source_branch || 'master' }}
90 | artifacts_only: ${{ github.event.inputs.artifacts_only || 'false' }}
91 | skip_new_tag_check: ${{ github.event.inputs.skip_new_tag_check || 'false' }}
92 | linux_build_type: ${{ github.event.inputs.linux_build_type || 'false' }}
93 | linux: ${{ github.event.inputs.linux || 'false' }}
94 | windows: ${{ github.event.inputs.windows || 'false' }}
95 | osx: ${{ github.event.inputs.osx || 'false' }}
96 | skip_rerun: ${{ github.event.inputs.skip_rerun || 'false' }}
97 | retries: ${{ github.event.inputs.retries || '1' }}
98 | steps:
99 | - name: Setting Outputs from inputs
100 | run: |
101 | printf '%b\n\n' "Setting Outputs from Inputs"
102 |
103 | printf '%b\n\n' "Checking required secrets are set" >> $GITHUB_STEP_SUMMARY
104 |
105 | if [[ -z "${{ secrets.VT_API_KEY }}" ]]; then
106 | printf '%b\n\n' "VT_API_KEY is not set. Exiting..." >> $GITHUB_STEP_SUMMARY
107 | exit 1
108 | fi
109 |
110 | show_outputs:
111 | if: needs.skip_duplicate_job.outputs.should_skip != 'true'
112 | needs: scheduled_defaults
113 | runs-on: ubuntu-24.04-arm
114 | env:
115 | source_repo: ${{ needs.scheduled_defaults.outputs.source_repo }}
116 | source_branch: ${{ needs.scheduled_defaults.outputs.source_branch }}
117 | artifacts_only: ${{ needs.scheduled_defaults.outputs.artifacts_only }}
118 | skip_new_tag_check: ${{ needs.scheduled_defaults.outputs.skip_new_tag_check }}
119 | linux_build_type: ${{ needs.scheduled_defaults.outputs.linux_build_type }}
120 | linux: ${{ needs.scheduled_defaults.outputs.linux }}
121 | windows: ${{ needs.scheduled_defaults.outputs.windows }}
122 | osx: ${{ needs.scheduled_defaults.outputs.osx }}
123 | skip_rerun: ${{ needs.scheduled_defaults.outputs.skip_rerun }}
124 | retries: ${{ needs.scheduled_defaults.outputs.retries }}
125 | steps:
126 | - name: Set output
127 | run: |
128 | printf '%b\n' "# Scheduled Defaults Outputs Summary" >> $GITHUB_STEP_SUMMARY
129 | printf '\n%b\n' ":octocat: Here is a summary of inputs set as string outputs that are used in workflows." >> $GITHUB_STEP_SUMMARY
130 |
131 | printf '\n%b\n' "source_repo: \`${source_repo}\`" >> $GITHUB_STEP_SUMMARY
132 | printf '\n%b\n' "source_branch: \`${source_branch}\`" >> $GITHUB_STEP_SUMMARY
133 | printf '\n%b\n' "artifacts_only: \`${artifacts_only}\`" >> $GITHUB_STEP_SUMMARY
134 | printf '\n%b\n' "skip_new_tag_check: \`${skip_new_tag_check}\`" >> $GITHUB_STEP_SUMMARY
135 | printf '\n%b\n' "linux_build_type: \`${linux_build_type}\`" >> $GITHUB_STEP_SUMMARY
136 | printf '\n%b\n' "linux: \`${linux}\`" >> $GITHUB_STEP_SUMMARY
137 | printf '\n%b\n' "windows: \`${windows}\`" >> $GITHUB_STEP_SUMMARY
138 | printf '\n%b\n' "osx: \`${osx}\`" >> $GITHUB_STEP_SUMMARY
139 | printf '\n%b\n' "skip_rerun: \`${skip_rerun}\`" >> $GITHUB_STEP_SUMMARY
140 | printf '\n%b\n' "retries: \`${retries}\`" >> $GITHUB_STEP_SUMMARY
141 |
142 | iperf3_tag:
143 | needs: scheduled_defaults
144 | if: needs.scheduled_defaults.outputs.skip_new_tag_check == 'false' && needs.skip_duplicate_job.outputs.should_skip != 'true'
145 | uses: ./.github/workflows/ci-check-for-new-release-tag.yml
146 |
147 | linux_emulation:
148 | needs: [scheduled_defaults, iperf3_tag]
149 | if: >
150 | always() && !failure() && !cancelled() &&
151 | ( needs.iperf3_tag.outputs.continue_build == 'yes' || needs.scheduled_defaults.outputs.skip_new_tag_check == 'true' ) &&
152 | ( needs.scheduled_defaults.outputs.linux == 'false' && needs.scheduled_defaults.outputs.linux_build_type == 'false' && needs.skip_duplicate_job.outputs.should_skip != 'true' )
153 | permissions:
154 | id-token: write
155 | attestations: write
156 | contents: read
157 | uses: ./.github/workflows/ci-linux-emulation.yml
158 | secrets:
159 | VT_API_KEY: ${{ secrets.VT_API_KEY || '' }}
160 | with:
161 | source_repo: ${{ needs.scheduled_defaults.outputs.source_repo }}
162 | source_branch: ${{ needs.iperf3_tag.outputs.iperf3_tag || needs.scheduled_defaults.outputs.source_branch }}
163 |
164 | linux_crossbuild:
165 | needs: [scheduled_defaults, iperf3_tag]
166 | if: >
167 | always() && !failure() && !cancelled() &&
168 | ( needs.iperf3_tag.outputs.continue_build == 'yes' || needs.scheduled_defaults.outputs.skip_new_tag_check == 'true' ) &&
169 | ( needs.scheduled_defaults.outputs.linux == 'false' && needs.scheduled_defaults.outputs.linux_build_type == 'true' && needs.skip_duplicate_job.outputs.should_skip != 'true' )
170 | permissions:
171 | id-token: write
172 | attestations: write
173 | contents: read
174 | uses: ./.github/workflows/ci-linux-crossbuild.yml
175 | secrets:
176 | VT_API_KEY: ${{ secrets.VT_API_KEY || '' }}
177 | with:
178 | source_repo: ${{ needs.scheduled_defaults.outputs.source_repo }}
179 | source_branch: ${{ needs.iperf3_tag.outputs.iperf3_tag || needs.scheduled_defaults.outputs.source_branch }}
180 |
181 | windows:
182 | needs: [scheduled_defaults, iperf3_tag]
183 | if: >
184 | always() && !failure() && !cancelled() &&
185 | ( needs.iperf3_tag.outputs.continue_build == 'yes' || needs.scheduled_defaults.outputs.skip_new_tag_check == 'true' ) &&
186 | ( needs.scheduled_defaults.outputs.windows == 'false' && needs.skip_duplicate_job.outputs.should_skip != 'true' )
187 | permissions:
188 | id-token: write
189 | attestations: write
190 | contents: read
191 | uses: ./.github/workflows/ci-windows.yml
192 | secrets:
193 | VT_API_KEY: ${{ secrets.VT_API_KEY || '' }}
194 | with:
195 | source_repo: ${{ needs.scheduled_defaults.outputs.source_repo }}
196 | source_branch: ${{ needs.iperf3_tag.outputs.iperf3_tag || needs.scheduled_defaults.outputs.source_branch }}
197 | artifacts_only: ${{ needs.scheduled_defaults.outputs.artifacts_only }}
198 |
199 | osx:
200 | needs: [scheduled_defaults, iperf3_tag]
201 | if: >
202 | always() && !failure() && !cancelled() &&
203 | ( needs.iperf3_tag.outputs.continue_build == 'yes' || needs.scheduled_defaults.outputs.skip_new_tag_check == 'true' ) &&
204 | ( needs.scheduled_defaults.outputs.osx == 'false' && needs.skip_duplicate_job.outputs.should_skip != 'true' )
205 | permissions:
206 | id-token: write
207 | attestations: write
208 | contents: read
209 | strategy:
210 | matrix:
211 | target: [macos-13, macos-latest]
212 | include:
213 | - target: macos-13
214 | binary_filename: amd64-osx-13
215 | brew_cellar: "/usr/local/Cellar"
216 | brew_install: "brew install automake"
217 | - target: macos-latest
218 | binary_filename: arm64-osx-14
219 | brew_cellar: "/opt/homebrew/Cellar"
220 | brew_install: "brew install autoconf automake libtool"
221 | uses: ./.github/workflows/ci-osx.yml
222 | secrets:
223 | VT_API_KEY: ${{ secrets.VT_API_KEY }}
224 | with:
225 | brew_cellar: ${{ matrix.brew_cellar }}
226 | brew_install: ${{ matrix.brew_install }}
227 | target: ${{ matrix.target }}
228 | source_repo: ${{ needs.scheduled_defaults.outputs.source_repo }}
229 | source_branch: ${{ needs.iperf3_tag.outputs.iperf3_tag || needs.scheduled_defaults.outputs.source_branch }}
230 | binary_filename: ${{ matrix.binary_filename }}
231 |
232 | release:
233 | needs: [scheduled_defaults, linux_emulation, linux_crossbuild, windows, osx]
234 | if: >
235 | always() && !failure() && !cancelled() &&
236 | ( needs.linux_emulation.result == 'success' || needs.linux_crossbuild.result == 'success' || needs.windows.result == 'success' || needs.osx.result == 'success' ) &&
237 | !contains(needs.*.result, 'failure') &&
238 | needs.scheduled_defaults.outputs.artifacts_only == 'false' &&
239 | needs.skip_duplicate_job.outputs.should_skip != 'true'
240 | permissions:
241 | contents: write
242 | uses: ./.github/workflows/ci-release.yml
243 | with:
244 | release_tags: ${{ needs.linux_emulation.outputs.release_tags || needs.linux_crossbuild.outputs.release_tags || needs.windows.outputs.release_tags || needs.osx.outputs.release_tags }}
245 | test_linux_emulation: ${{ needs.linux_emulation.result }}
246 | test_linux_crossbuild: ${{ needs.linux_crossbuild.result }}
247 | test_windows: ${{ needs.windows.result }}
248 | test_osx: ${{ needs.osx.result }}
249 |
250 | docker:
251 | needs: [scheduled_defaults, linux_emulation, linux_crossbuild, release]
252 | if: >
253 | always() && !failure() && !cancelled() &&
254 | ( needs.linux_emulation.result == 'success' || needs.linux_crossbuild.result == 'success' ) &&
255 | !contains(needs.*.result, 'failure') &&
256 | needs.scheduled_defaults.outputs.linux == 'false' &&
257 | needs.scheduled_defaults.outputs.artifacts_only == 'false' &&
258 | needs.skip_duplicate_job.outputs.should_skip != 'true'
259 | permissions:
260 | packages: write
261 | uses: ./.github/workflows/ci-docker.yml
262 |
263 | rerun_on_failure:
264 | needs:
265 | [
266 | skip_duplicate_job,
267 | scheduled_defaults,
268 | show_outputs,
269 | iperf3_tag,
270 | linux_emulation,
271 | linux_crossbuild,
272 | windows,
273 | osx,
274 | release,
275 | docker,
276 | ]
277 | if: >
278 | failure() &&
279 | ( needs.scheduled_defaults.outputs.skip_rerun == 'false' && needs.skip_duplicate_job.outputs.should_skip != 'true' )
280 | concurrency:
281 | group: ci-auto-rerun-failed-jobs
282 | cancel-in-progress: true
283 | permissions:
284 | actions: write
285 | runs-on: ubuntu-24.04-arm
286 | env:
287 | GH_TOKEN: "${{ secrets.AUTO_RERUN || github.token }}"
288 | github_repo: "" # To use ci-auto-rerun-failed-jobs.yml hosted in a remote repository else default to the current repository. Requires PAT token AUTO_RERUN
289 | retries: ${{ github.event.inputs.retries || '1' }}
290 | distinct_id: ${{ github.event.inputs.distinct_id }}
291 | steps:
292 | - uses: actions/checkout@v4
293 | with:
294 | persist-credentials: false
295 | - name: ci-auto-rerun-failed-jobs via ${{ env.github_repo || github.repository }}
296 | run: >
297 | gh workflow run ci-auto-rerun-failed-jobs-action.yml
298 | --repo "${github_repo:-$GITHUB_REPOSITORY}"
299 | -f github_repo=${GITHUB_REPOSITORY}
300 | -f run_id=${GITHUB_RUN_ID}
301 | -f attempts=${GITHUB_RUN_ATTEMPT}
302 | -f retries=${retries}
303 | -f distinct_id=${distinct_id}
304 |
--------------------------------------------------------------------------------
/.github/workflows/ci-osx.yml:
--------------------------------------------------------------------------------
1 | name: ci - osx
2 |
3 | on:
4 | workflow_call:
5 | outputs:
6 | release_tags:
7 | value: ${{ jobs.build.outputs.release_tags }}
8 | inputs:
9 | source_repo:
10 | type: string
11 | required: true
12 | source_branch:
13 | type: string
14 | required: true
15 | brew_cellar:
16 | type: string
17 | required: true
18 | brew_install:
19 | type: string
20 | required: true
21 | target:
22 | type: string
23 | required: true
24 | binary_filename:
25 | type: string
26 | required: true
27 | secrets:
28 | VT_API_KEY:
29 | required: false
30 |
31 | env:
32 | GH_TOKEN: "${{ github.TOKEN }}"
33 | binary_filename: ${{ inputs.binary_filename }}
34 | source_repo: ${{ inputs.source_repo }}
35 | source_branch: ${{ inputs.source_branch }}
36 | brew_cellar: ${{ inputs.brew_cellar }}
37 | brew_install: ${{ inputs.brew_install }}
38 | target: ${{ inputs.target }}
39 |
40 | jobs:
41 | build:
42 | runs-on: ${{ inputs.target }}
43 | outputs:
44 | release_tags: ${{ steps.release_tags.outputs.release_tag }}
45 | steps:
46 | - name: Clone repository
47 | uses: actions/checkout@v4
48 | with:
49 | persist-credentials: false
50 |
51 | - name: Install packages
52 | run: |
53 | brew update || brew update-reset
54 | ${brew_install}
55 |
56 | - name: Check openssl
57 | run: ls -la ${brew_cellar}/openssl@3/*/lib
58 |
59 | - name: Copy Openssl Static Libraries to openssl_libs
60 | run: |
61 | mkdir -p ${{ github.workspace }}/openssl_libs
62 | cp -fv ${brew_cellar}/openssl@3/*/lib/libcrypto.a ${{ github.workspace }}/openssl_libs/
63 | cp -fv ${brew_cellar}/openssl@3/*/lib/libssl.a ${{ github.workspace }}/openssl_libs/
64 |
65 | - name: Check openssl_libs
66 | run: ls -la openssl_libs
67 |
68 | - name: Clone iperf3 repository
69 | run: git clone --no-tags --single-branch --branch ${source_branch} --shallow-submodules --recurse-submodule --depth 1 ${source_repo} iperf3
70 |
71 | - name: Bootstrap
72 | working-directory: iperf3
73 | run: ./bootstrap.sh
74 |
75 | - name: Set CC
76 | run: printf '%s\n' "LDFLAGS=-L${{ github.workspace }}/openssl_libs" >> "$GITHUB_ENV"
77 |
78 | - name: Configure
79 | working-directory: iperf3
80 | run: ./configure --enable-shared=no --disable-silent-rules --disable-profiling --prefix=${{ github.workspace }}/build
81 |
82 | - name: Make
83 | working-directory: iperf3
84 | run: make -j"$(sysctl -n hw.logicalcpu)"
85 |
86 | - name: Make install
87 | working-directory: iperf3
88 | run: make install
89 |
90 | - name: Test iperf3 build
91 | run: |
92 | printf '\n%b\n\n' "🟦"
93 | ${{ github.workspace }}/build/bin/iperf3 --version
94 | printf '\n%b\n\n' "🟦"
95 | file ${{ github.workspace }}/build/bin/iperf3
96 | printf '\n%b\n\n' "🟦"
97 | otool -L ${{ github.workspace }}/build/bin/iperf3
98 |
99 | - name: Process iperf3 build
100 | run: mv -f ${{ github.workspace }}/build/bin/iperf3 ${{ github.workspace }}/iperf3-${binary_filename}
101 |
102 | - name: Create path to binary env
103 | run: printf '%s\n' "binary_path=${{ github.workspace }}/iperf3-${binary_filename}" >> $GITHUB_ENV
104 |
105 | - name: VirusTotal Scan
106 | id: virustotal
107 | uses: crazy-max/ghaction-virustotal@v4
108 | with:
109 | vt_api_key: ${{ secrets.VT_API_KEY }}
110 | files: ${{ env.binary_path }}
111 |
112 | - name: sha256sum
113 | run: |
114 | printf '%s' https://www.virustotal.com/gui/file/$(shasum -a 256 ${{ env.binary_path }} | awk '{print $1}') > iperf3-${binary_filename}.url
115 | cat iperf3-${binary_filename}.url
116 |
117 | - name: Create tag env
118 | run: printf '%s\n' "release_tag=$(sed -rn 's|(.*)\[(.*)],\[https://github.com/esnet/iperf],(.*)|\2|p' iperf3/configure.ac)" >> $GITHUB_ENV
119 |
120 | - name: Set tag env to output
121 | id: release_tags
122 | run: printf '%s\n' "release_tag=${{ env.release_tag }}" >> "$GITHUB_OUTPUT"
123 |
124 | - name: Generate artifact attestation
125 | uses: actions/attest-build-provenance@v2
126 | with:
127 | subject-path: ${{ env.binary_path }}
128 |
129 | - name: Upload artifact
130 | uses: actions/upload-artifact@v4
131 | with:
132 | name: iperf3-${{ inputs.binary_filename }}
133 | path: |
134 | ${{ env.binary_path }}
135 | iperf3-${binary_filename}.url
136 |
137 | - name: Upload artifact
138 | if: failure()
139 | uses: actions/upload-artifact@v4
140 | with:
141 | name: iperf3-${{ inputs.binary_filename }}-config.log
142 | path: ${{ github.workspace }}/iperf3/config.log
143 |
--------------------------------------------------------------------------------
/.github/workflows/ci-release.yml:
--------------------------------------------------------------------------------
1 | name: ci - release
2 |
3 | on:
4 | workflow_call:
5 | inputs:
6 | release_tags:
7 | type: string
8 | test_linux_emulation:
9 | type: string
10 | test_linux_crossbuild:
11 | type: string
12 | test_windows:
13 | type: string
14 | test_osx:
15 | type: string
16 |
17 | env:
18 | GH_TOKEN: "${{ github.TOKEN }}"
19 | release_tags: ${{ inputs.release_tags }}
20 | test_linux_emulation: ${{ inputs.test_linux_emulation }}
21 | test_linux_crossbuild: ${{ inputs.test_linux_crossbuild }}
22 | test_windows: ${{ inputs.test_windows }}
23 | test_osx: ${{ inputs.test_osx }}
24 |
25 | jobs:
26 | release:
27 | runs-on: ubuntu-24.04-arm
28 | steps:
29 | - name: Checkout
30 | uses: actions/checkout@v4
31 | with:
32 | persist-credentials: false
33 |
34 | - name: Summary - needs results
35 | run: |
36 | printf '%s\n\n' "## Summary - needs results"
37 | printf '%s\n\n' "release_tags: \`${release_tags}\`" >> $GITHUB_STEP_SUMMARY
38 | printf '\n%s\n' "test_linux_emulation: \`${test_linux_emulation}\`" >> $GITHUB_STEP_SUMMARY
39 | printf '\n%s\n' "test_linux_crossbuild: \`${test_linux_crossbuild}\`" >> $GITHUB_STEP_SUMMARY
40 | printf '\n%s\n' "test_windows: \`${test_windows}\`" >> $GITHUB_STEP_SUMMARY
41 | printf '\n%s\n' "test_osx: \`${test_osx}\`" >> $GITHUB_STEP_SUMMARY
42 |
43 | - name: Download artifacts
44 | uses: actions/download-artifact@v4
45 | with:
46 | path: "release-artifacts"
47 | pattern: iperf3-*
48 | merge-multiple: true
49 |
50 | - name: Virustotal scan results
51 | run: |
52 | pushd release-artifacts || exit 1
53 |
54 | for virus_total_urls in iperf3-*\.url; do
55 | dependency_version+=("${virus_total_urls}")
56 | done
57 |
58 | readarray -t release_sorted < <(printf '%s\n' "${dependency_version[@]}" | sort)
59 |
60 | if command_output="$(gh release view "${release_tags}" --repo "${{ github.repository }}" --json body -q .body 2>&1)"; then
61 | if [[ -n "${command_output}" ]]; then
62 | sed '// {q}' ${{ github.workspace }}/ci-release-body.md > ci-release-body.md
63 | printf '%s\n' "$command_output" | sed -n '//,$p' >> ci-release-body.md
64 | else
65 | cp -f ${{ github.workspace }}/ci-release-body.md ci-release-body.md
66 | fi
67 | else
68 | cp -f ${{ github.workspace }}/ci-release-body.md ci-release-body.md
69 | fi
70 |
71 | for filenames in "${release_sorted[@]}"; do
72 | virustotal_url="$(head -1 "${filenames}" | tr -d '\n' | tr -d '\r' | tr -d '\r\n')"
73 | sed -i -r 's|(\['${filenames//\.url/}'\])\((.*)\)|\1('${virustotal_url}')|' ci-release-body.md
74 | done
75 |
76 | - name: "Publish release ${{ inputs.release_tags }}"
77 | uses: ncipollo/release-action@v1
78 | with:
79 | prerelease: false
80 | artifacts: release-artifacts/iperf3-*[!\.url]
81 | replacesArtifacts: true
82 | tag: ${{ inputs.release_tags }}
83 | name: iperf3 ${{ inputs.release_tags }}
84 | allowUpdates: true
85 | bodyFile: release-artifacts/ci-release-body.md
86 | token: ${{ github.token }}
87 |
--------------------------------------------------------------------------------
/.github/workflows/ci-windows.yml:
--------------------------------------------------------------------------------
1 | name: ci - windows binary build
2 |
3 | on:
4 | workflow_call:
5 | outputs:
6 | release_tags:
7 | value: ${{ jobs.build.outputs.release_tags }}
8 | inputs:
9 | source_repo:
10 | type: string
11 | required: true
12 | source_branch:
13 | type: string
14 | required: true
15 | artifacts_only:
16 | type: string
17 | required: true
18 | secrets:
19 | VT_API_KEY:
20 | required: false
21 |
22 | env:
23 | GH_TOKEN: "${{ github.TOKEN }}"
24 |
25 | jobs:
26 | build:
27 | runs-on: windows-latest
28 | outputs:
29 | release_tags: ${{ steps.release_tags.outputs.release_tag }}
30 | strategy:
31 | fail-fast: false
32 | matrix:
33 | name: [iperf3]
34 | build: [basic, openssl]
35 | arch: [amd64]
36 | include:
37 | - build: "basic"
38 | filename: ""
39 | openssl: "no"
40 | - build: "openssl"
41 | filename: "-openssl"
42 | openssl: "yes"
43 |
44 | name: ${{ matrix.name }}-${{ matrix.arch }}-win${{ matrix.filename }}.zip
45 |
46 | env:
47 | cygwin_path: "cygwin"
48 | source_branch: ${{ inputs.source_branch }}
49 | source_repo: ${{ inputs.source_repo }}
50 |
51 | steps:
52 | - run: git config --global core.autocrlf input
53 |
54 | - name: Checkout
55 | uses: actions/checkout@v4
56 | with:
57 | persist-credentials: false
58 |
59 | - name: Install ci-cygwin-installer.cmd
60 | run: .\ci-cygwin-installer.cmd
61 |
62 | - name: Build static
63 |
64 | run: .\cygwin\bin\bash.exe -l ci-windows-cygwin-build.sh "${{ matrix.openssl }}" "$env:cygwin_path" "$env:source_repo" "$env:source_branch"
65 |
66 | - name: VirusTotal Scan
67 | id: virustotal
68 | uses: crazy-max/ghaction-virustotal@v4
69 | with:
70 | vt_api_key: ${{ secrets.VT_API_KEY }}
71 | files: |
72 | ${{ matrix.name }}/bin/iperf3.exe
73 | ${{ matrix.name }}/bin/cygwin1.dll
74 |
75 | - name: sha256sum
76 | run: |
77 | printf '%s' https://www.virustotal.com/gui/file/$(sha256sum ${{ matrix.name }}/bin/iperf3.exe | awk '{print $1}') > ${{ matrix.name }}-${{ matrix.arch }}-win${{ matrix.filename }}.url
78 | cat ${{ matrix.name }}-${{ matrix.arch }}-win${{ matrix.filename }}.url
79 |
80 | - name: Archive build
81 | run: Compress-Archive -Path "${{ matrix.name }}/bin/*" -DestinationPath "${{ matrix.name }}-${{ matrix.arch }}-win${{ matrix.filename }}.zip"
82 |
83 | - name: Generate artifact attestation
84 | uses: actions/attest-build-provenance@v2
85 | with:
86 | subject-path: |
87 | ${{ matrix.name }}-${{ matrix.arch }}-win${{ matrix.filename }}.zip
88 | ${{ matrix.name }}/bin/iperf3.exe
89 | ${{ matrix.name }}/bin/cygwin1.dll
90 |
91 | - name: Create tag env
92 | run: printf '%s\n' "release_tag=$(Get-Content -Path iperf3_version)" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
93 |
94 | - name: Set tag env to output
95 | id: release_tags
96 | run: printf '%s\n' "release_tag=${{ env.release_tag }}" >> $env:GITHUB_OUTPUT
97 |
98 | - name: "Release - Create artifacts"
99 | if: inputs.artifacts_only == 'false'
100 | uses: actions/upload-artifact@v4
101 | with:
102 | name: "${{ matrix.name }}-amd64-win${{ matrix.filename }}"
103 | path: |
104 | ${{ matrix.name }}-${{ matrix.arch }}-win${{ matrix.filename }}.zip
105 | ${{ matrix.name }}-${{ matrix.arch }}-win${{ matrix.filename }}.url
106 |
107 | - name: "Dev - Create artifacts"
108 | if: inputs.artifacts_only == 'true'
109 | uses: actions/upload-artifact@v4
110 | with:
111 | name: "${{ matrix.name }}-amd64-win${{ matrix.filename }}"
112 | path: "${{ matrix.name }}"
113 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: test iperf3 release binaries for windows and osx
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | permissions: {}
7 |
8 | jobs:
9 | test-osx-amd64:
10 | runs-on: macos-13
11 | permissions:
12 | contents: read
13 |
14 | steps:
15 | - name: brew install
16 | run: brew install coreutils
17 |
18 | - name: test iperf3 version
19 | run: |
20 | wget -O ~/iperf3 "https://github.com/${{ github.repository }}/releases/latest/download/iperf3-amd64-osx-13"
21 | chmod +x ~/iperf3
22 |
23 | printf '\n%b\n\n' "🟦"
24 | file ~/iperf3
25 |
26 | printf '\n%b\n\n' "🟦"
27 | otool -L ~/iperf3
28 |
29 | printf '\n%b\n\n' "🟦"
30 | ~/iperf3 --version
31 |
32 | - name: test iperf3 servers
33 | run: |
34 | ~/$(wget -qO- https://db.iperf3serverlist.net/api/v1/db/public/shared-view/b111407c-43c4-48af-a828-301b698064a3/rows/export/csv | awk -F, 'NR>1 { print $1 }' | shuf -n1)
35 |
36 | test-osx-arm64:
37 | runs-on: macos-latest
38 | permissions:
39 | contents: read
40 |
41 | steps:
42 | - name: brew install
43 | run: brew install coreutils
44 |
45 | - name: test iperf3 version
46 | run: |
47 | wget -O ~/iperf3 "https://github.com/${{ github.repository }}/releases/latest/download/iperf3-arm64-osx-14"
48 | chmod +x ~/iperf3
49 |
50 | printf '\n%b\n\n' "🟦"
51 | file ~/iperf3
52 |
53 | printf '\n%b\n\n' "🟦"
54 | otool -L ~/iperf3
55 |
56 | printf '\n%b\n\n' "🟦"
57 | ~/iperf3 --version
58 |
59 | - name: test iperf3 servers
60 | run: |
61 | ~/$(wget -qO- https://db.iperf3serverlist.net/api/v1/db/public/shared-view/b111407c-43c4-48af-a828-301b698064a3/rows/export/csv | awk -F, 'NR>1 { print $1 }' | shuf -n1)
62 |
63 | test-windows:
64 | runs-on: windows-latest
65 | permissions:
66 | contents: read
67 | defaults:
68 | run:
69 | shell: bash
70 |
71 | steps:
72 | - name: test iperf3 version
73 | run: |
74 | curl -sL "https://github.com/${{ github.repository }}/releases/latest/download/iperf3-amd64-win.zip" -o iperf3.zip
75 | unzip iperf3.zip
76 | ls -la
77 | chmod +x iperf3.exe
78 | ./iperf3.exe --version
79 |
80 | - name: test iperf3 servers
81 | run: ./$(curl -sL https://db.iperf3serverlist.net/api/v1/db/public/shared-view/b111407c-43c4-48af-a828-301b698064a3/rows/export/csv | awk -F, 'NR>1 { print $1 }' | shuf -n1)
82 |
83 | test-windows-openssl:
84 | runs-on: windows-latest
85 | defaults:
86 | run:
87 | shell: bash
88 |
89 | steps:
90 | - name: Download iperf3
91 | run: |
92 | curl -sL "https://github.com/${{ github.repository }}/releases/latest/download/iperf3-amd64-win-openssl.zip" -o iperf3.zip
93 | unzip iperf3.zip
94 | ls -la
95 | chmod +x iperf3.exe
96 | ./iperf3.exe --version
97 |
98 | - name: test iperf3 servers
99 | run: ./$(curl -sL https://db.iperf3serverlist.net/api/v1/db/public/shared-view/b111407c-43c4-48af-a828-301b698064a3/rows/export/csv | awk -F, 'NR>1 { print $1 }' | shuf -n1)
100 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | package-lock.json
3 | package.json
4 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:latest AS builder
2 |
3 | ARG ARCH="amd64"
4 | ARG REPO="userdocs/iperf3-static"
5 |
6 | RUN apk update \
7 | && apk upgrade \
8 | && apk add sudo \
9 | && adduser -Ds /bin/bash -u 1000 username \
10 | && printf '%s' 'username ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/github
11 |
12 | ADD --chown=username:username --chmod=700 "https://github.com/${REPO}/releases/latest/download/iperf3-${ARCH}" /usr/local/bin/iperf3
13 |
14 | USER username
15 |
16 | WORKDIR /home/username
17 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # iperf3 static builds
2 |
3 | - iperf3 windows builds
4 | - iperf3 linux builds
5 | - iperf3 macosx builds
6 |
7 | The only resource providing multiplatform distro independent iperf3 latest releases that has a 100% transparent build process from end to end. Complete accountability and verified chain of custody. No hidden parts.
8 |
9 | - [Chain of custody and build provenance](https://github.com/userdocs/iperf3-static?tab=readme-ov-file#gh-attestation-verify) - easily verify the archive or binary was created here.
10 | - [Transparent build process from source code to binary](https://github.com/userdocs/iperf3-static/actions) - source code > workflow > verification > release.
11 | - [Virustotal scan and details during the build process](https://github.com/userdocs/iperf3-static?tab=readme-ov-file#gh-attestation-verify) - scanned before release.
12 | - [Zizmor workflow auditing](https://github.com/woodruffw/zizmor) - helping ensure the worklow itself is not poisoned.
13 | - Powerful build system with ability to specify repo and branches to easily build patches or custom builds.
14 |
15 | 
16 |
17 | ## Build Platforms
18 |
19 | - [Alpine linux](https://alpinelinux.org) edge using [qemu emulation](https://www.qemu.org)
20 | - Windows on [Github Actions runners](https://github.com/actions/runner-images?tab=readme-ov-file#available-images) for x86_64 using a custom [Cywgin installer script](https://github.com/userdocs/iperf3-static/blob/master/cygwin-installer.cmd)
21 | - MacOS on [Github Actions runners](https://github.com/actions/runner-images?tab=readme-ov-file#available-images) for amd64 (mmacos-13) and arm64 (macos-14) with static openssl and iperf libraries.
22 |
23 | ## Available architectures
24 |
25 | Linux:
26 |
27 | - Arch: `amd64` `arm32v6` `arm32v7` `arm64v8` `i386` `ppc64le` `riscv64` `s390x`
28 | - Docker: yes
29 | - Static binaries: yes
30 | - Openssl latest release - https://github.com/openssl/openssl/releases/latest
31 |
32 | Windows:
33 |
34 | - Arch: `amd64`
35 | - Docker: no
36 | - Static binaries: yes
37 | - Openssl 3.1.x - Releases after this don't work with cygwin / iperf3 for windows builds.
38 |
39 | MacOS:
40 |
41 | - Arch: `amd64` `arm64`
42 | - Docker: no
43 | - Static binaries: yes
44 | - Openssl@3 - https://formulae.brew.sh/formula/openssl@3
45 |
46 | > [!NOTE]
47 | > Windows and MacOS binaries are not fully static in terms of their dependency and `cygwin1.dll` (Windows) `libSystem.B.dylib` (MasOS).
48 | > They are statically linked with `libcrypo.a` `libssl.a` (openssl) and `iperf3.a` (iperf3) so there should be no other system dependency required to run them on the target hosts.
49 | >
50 | > On Windows openssl is built from Github source to get static libs and on MacOS we get them from the brew cellar installation of `openssl@3`
51 |
52 | ## Download - Static Binaries
53 |
54 | Static binaries for Linux and Windows are available here: https://github.com/userdocs/iperf3-static/releases/latest
55 |
56 | Example:
57 |
58 | ```
59 | curl -sLo- iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-amd64
60 | chmod +x iperf3
61 | iperf3 --version
62 | ```
63 |
64 | ## Download - Docker
65 |
66 | Multiarch Docker images are available via https://github.com/users/userdocs/packages/container/package/iperf3-static
67 |
68 | Example:
69 |
70 | ```bash
71 | docker pull ghcr.io/userdocs/iperf3-static:latest
72 | ```
73 |
74 | To used the image dynamically
75 |
76 | ```bash
77 | docker run -it ghcr.io/userdocs/iperf3-static:latest iperf3 --version
78 | ```
79 |
80 | ## Alpine multiarch info
81 |
82 |
83 | Expand for details
84 |
85 | | Alpine Arch | Docker platform arch | Source of Build Dockers | ghcr.io image |
86 | | :---------: | :------------------: | :-------------------------------------: | :-----------------: |
87 | | armhf | linux/arm/v6 | https://hub.docker.com/r/arm32v6/alpine | arm32v6/alpine:edge |
88 | | armv7 | linux/arm/v7 | https://hub.docker.com/r/arm32v7/alpine | arm32v7/alpine:edge |
89 | | aarch64 | linux/arm64 | https://hub.docker.com/r/arm64v8/alpine | arm64v8/alpine:edge |
90 | | ppc64le | linux/ppc64le | https://hub.docker.com/r/ppc64le/alpine | ppc64le/alpine:edge |
91 | | s390x | linux/s390x | https://hub.docker.com/r/s390x/alpine | s390x/alpine:edge |
92 | | riscv64 | linux/riscv64 | https://hub.docker.com/r/riscv64/alpine | riscv64/alpine:edge |
93 | | x86 | linux/i386 | https://hub.docker.com/r/i386/alpine | i386/alpine:edge |
94 | | x86_64 | linux/amd64 | https://hub.docker.com/r/amd64/alpine | amd64/alpine:edge |
95 |
96 |
97 |
98 | ## Windows x86_64 info
99 |
100 |
101 | Expand for details
102 |
103 | Static Cygwin builds created via cygwin64 using this custom installer
104 |
105 | https://github.com/userdocs/iperf3-static/blob/master/cygwin-installer.cmd
106 |
107 |
108 |
109 | ## Generic Build dependencies
110 |
111 |
112 | Expand for details
113 |
114 | ```
115 | apk add build-base pkgconf autoconf automake curl libtool git perl openssl-libs-static openssl-dev linux-headers
116 | ```
117 |
118 | #### Debian linux
119 |
120 | ```
121 | apt install -y build-essential pkg-config automake libtool libssl-dev git perl
122 | ```
123 |
124 | #### Cygwin packages
125 |
126 | Without openssl
127 |
128 | ```bash
129 | automake,gcc-core,gcc-g++,git,libtool,make,pkg-config
130 | ```
131 |
132 | With openssl
133 |
134 | ```bash
135 | automake,gcc-core,gcc-g++,git,libtool,make,pkg-config,libssl-devel,zlib-devel
136 | ```
137 |
138 | ### Generic Build Instructions
139 |
140 | Clone the git repo - linux + Cygwin
141 |
142 | ```bash
143 | git clone https://github.com/esnet/iperf.git ~/iperf3 && cd ~/iperf3
144 | ```
145 |
146 | Bootstrap - If you cloned the repo
147 |
148 | ```bash
149 | ./bootstrap.sh
150 | ```
151 |
152 | Configure - linux + Cygwin
153 |
154 | Note: Cygwin requires requires compiling openssl and zlib static libs to link statically. Otherwise you compile dynamically
155 |
156 | Static
157 |
158 | ```bash
159 | ./configure --disable-shared --enable-static-bin --prefix=$HOME
160 | ```
161 |
162 | Dynamic
163 |
164 | ```bash
165 | ./configure --prefix=$HOME
166 | ```
167 |
168 | Cygwin openssl requires compiling openssl and zlib
169 |
170 | Build - linux + Cygwin
171 |
172 | ```
173 | make -j$(nproc)
174 | make install
175 | ```
176 |
177 | ### Check the linking was done properly
178 |
179 | ```
180 | ldd ~/bin/iperf3
181 | ```
182 |
183 | ### Version
184 |
185 | Use this command to check the version.
186 |
187 | ```
188 | ~/bin/iperf3 -v
189 | ```
190 |
191 | Will show something like this.
192 |
193 | ```
194 | iperf 3.10.1 (cJSON 1.7.13)
195 | Optional features available: CPU affinity setting, IPv6 flow label, TCP congestion algorithm setting, sendfile / zerocopy, socket pacing, authentication, bind to device, support IPv4 don't fragment
196 | ```
197 |
198 | ### Use the static binaries from this repo
199 |
200 | Download and install to the bin directory of your local user (for root this may not be in the `$PATH`)
201 |
202 | Pick the platform URL you need:
203 |
204 | i386 / x86
205 |
206 | ```bash
207 | mkdir -p ~/bin && source ~/.profile
208 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-i386
209 | chmod 700 ~/bin/iperf3
210 | ```
211 |
212 | amd64
213 |
214 | ```bash
215 | mkdir -p ~/bin && source ~/.profile
216 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-amd64
217 | chmod 700 ~/bin/iperf3
218 | ```
219 |
220 | arm32v6
221 |
222 | ```bash
223 | mkdir -p ~/bin && source ~/.profile
224 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-arm32v6
225 | chmod 700 ~/bin/iperf3
226 | ```
227 |
228 | arm32v7
229 |
230 | ```bash
231 | mkdir -p ~/bin && source ~/.profile
232 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-arm32v7
233 | chmod 700 ~/bin/iperf3
234 | ```
235 |
236 | aarch64 / arm64
237 |
238 | ```bash
239 | mkdir -p ~/bin && source ~/.profile
240 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-arm64v8
241 | chmod 700 ~/bin/iperf3
242 | ```
243 |
244 | ppc64le
245 |
246 | ```bash
247 | mkdir -p ~/bin && source ~/.profile
248 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-ppc64le
249 | chmod 700 ~/bin/iperf3
250 | ```
251 |
252 | s390x
253 |
254 | ```bash
255 | mkdir -p ~/bin && source ~/.profile
256 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-s390x
257 | chmod 700 ~/bin/iperf3
258 | ```
259 |
260 | Windows builds required being bundled with Cygwin dlls to work so these are not single static binaries. They have a directory structure like this.
261 |
262 | ```
263 | iperf3.exe
264 | cygwin1.dll
265 | ```
266 |
267 | Windows x64 no openssl
268 |
269 | https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-amd64-win.zip
270 |
271 | Windows x64 with openssl
272 |
273 | https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-amd64-win-openssl.zip
274 |
275 | Check the version:
276 |
277 | ```
278 | ~/bin/iperf3 -v
279 | ```
280 |
281 |
282 |
283 | ## MacOS amd64 and arm64 info
284 |
285 |
286 | Expand for details
287 |
288 | amd64 macos-13 intel
289 |
290 | ```bash
291 | mkdir -p ~/bin && source ~/.profile
292 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-amd64-osx-13
293 | chmod 700 ~/bin/iperf3
294 | ```
295 |
296 | arm64 macos-14 apple M1
297 |
298 | ```bash
299 | mkdir -p ~/bin && source ~/.profile
300 | wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-arm64-osx-14
301 | chmod 700 ~/bin/iperf3
302 | ```
303 |
304 |
305 |
306 | ## gh attestation verify
307 |
308 |
309 | Expand for details
310 |
311 | Binaries built from the release of `3.17.1+` use [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance)
312 |
313 | Verify the integrity and provenance of an artifact using its associated cryptographically signed attestations.
314 |
315 | https://cli.github.com/manual/gh_attestation_verify
316 |
317 | For example:
318 |
319 | ```bash
320 | gh attestation verify iperf3-amd64 -o userdocs
321 | ```
322 |
323 | Will give you this result for the `release-5.0.0_v2.0.10` revision `1` binary.
324 |
325 | ```bash
326 | Loaded digest sha256:84f9851d0647d3d618c66d64cac10ed1eb37583b3aaf3bb0baac88bf446fb10a for file://iperf3-amd64
327 | Loaded 6 attestations from GitHub API
328 | ✓ Verification succeeded!
329 |
330 | sha256:84f9851d0647d3d618c66d64cac10ed1eb37583b3aaf3bb0baac88bf446fb10a was attested by:
331 | REPO PREDICATE_TYPE WORKFLOW
332 | userdocs/iperf3-static https://slsa.dev/provenance/v1 .github/workflows/alpine_multi.yml@refs/heads/master
333 | ```
334 |
335 |
336 |
337 | ## Virustotal scanning
338 |
339 |
340 | Expand for details
341 |
342 | All binaries and dlls are scanned by virus total and the results uploaded using this action
343 |
344 | https://github.com/crazy-max/ghaction-virustotal
345 |
346 | The results url is uploaded to the release body and you can see them here https://github.com/userdocs/iperf3-static/releases/latest
347 |
348 |
349 |
350 | ### Credits and acknowledgements
351 |
352 |
353 | Expand for details
354 |
355 | Other contributions have helped inspire the creation of a GitHub action for a Windows build and release.
356 |
357 | [www.neowin.net](https://www.neowin.net/forum/topic/1234695-iperf-313-windows-build) via [budman](https://www.neowin.net/forum/profile/14624-budman/)
358 |
359 | https://github.com/ar51an/iperf3-win-builds via [cryptanalyst](https://www.neowin.net/forum/profile/170754-cryptanalyst/)
360 |
361 |
362 |
363 | ## Forking and using this repo
364 |
365 |
366 | Expand for details
367 |
368 | Step 1: Fork the repo: https://github.com/userdocs/iperf3-static/fork
369 |
370 | Step 2: Under the repo `/settings/secrets/actions` you will need to set a the `VT_API_KEY` using your
371 |
372 | You can find it here if you have created an account: https://www.virustotal.com/gui/my-apikey
373 |
374 | Step 3: Under the Actions tab, enable workflows. The `check_new_release.yml` defaults to a scheduled check but can be run manually.
375 |
376 | https://github.com/userdocs/iperf3-static/blob/0571ce60cba18d2b67303b71d31009f83bae36c8/.github/workflows/check_new_release.yml#L11-L12
377 |
378 |
379 |
380 | ## Test Servers
381 |
382 | https://github.com/R0GGER/public-iperf3-servers?tab=readme-ov-file#servers-per-continent
383 |
384 | Linux one liner for an example output of `./iperf3 -c speedtest.ip-projects.de` for a random Europe server
385 |
386 | ```shell
387 | ./$(curl -sL https://db.iperf3serverlist.net/api/v1/db/public/shared-view/b111407c-43c4-48af-a828-301b698064a3/rows/export/csv | awk -F, 'NR>1 { print $1 }' | shuf -n1)
388 | ```
389 |
--------------------------------------------------------------------------------
/ci-cygwin-installer-packages.cmd:
--------------------------------------------------------------------------------
1 | automake,curl,gcc-core,gcc-g++,git,libtool,make,pkg-config,tar
--------------------------------------------------------------------------------
/ci-cygwin-installer.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | :: Copyright 2023 by userdocs and contributors for LFTP4WIN installer derived from https://github.com/vegardit/cygwin-portable-installer
4 | :: Copyright 2017-2023 by Vegard IT GmbH (https://vegardit.com) and the cygwin-portable-installer contributors.
5 | ::
6 | :: LFTP4WIN installer derived from cygwin-portable-installer
7 | :: SPDX-FileCopyrightText: © userdocs and contributors
8 | :: SPDX-FileContributor: userdocs
9 | :: SPDX-License-Identifier: Apache-2.0
10 | ::
11 | :: cygwin-portable-installer
12 | :: SPDX-FileCopyrightText: © Vegard IT GmbH (https://vegardit.com) and contributors
13 | :: SPDX-FileContributor: Sebastian Thomschke, Vegard IT GmbH
14 | :: SPDX-License-Identifier: Apache-2.0
15 |
16 | :: ABOUT
17 | :: =====
18 | :: LFTP4WIN installer
19 | ::
20 | :: A heavily modified and re-targeted version of this project https://github.com/vegardit/cygwin-portable-installer
21 | :: Original code has been 1: removed where not relevant 2: Modified to work with LFTP4WIN CORE 3: Unmodified where applicable.
22 | :: It installs a portable Cygwin installation to be used specifically with the https://github.com/userdocs/LFTP4WIN-CORE skeleton.
23 | :: The LFTP4WIN-CORE is applied to the Cygwin installation with minimal modification to the Cygwin environment or core files.
24 | :: This provides a a fully functional Cygwin portable platform for use with the LFTP4WIN project.
25 | :: Environment customization is no longer designed to be fully self contained and is partially provided via the LFTP4WIN-CORE
26 | :: There are still some critical configuration options available below for the installation.
27 | :: if executed with "--debug" print all executed commands
28 | for %%a in (%*) do (
29 | if [%%~a]==[--debug] echo on
30 | )
31 |
32 | :: ============================================================================================================
33 | :: CONFIG CUSTOMIZATION START
34 | :: ============================================================================================================
35 |
36 | :: You can customize the following variables to your needs before running the batch file:
37 |
38 | :: set proxy if required (unfortunately Cygwin setup.exe does not have commandline options to specify proxy user credentials)
39 | set PROXY_HOST=
40 | set PROXY_PORT=8080
41 |
42 | :: Choose a user name that will be used to configure Cygwin. This user will be a clone of the account running the installation script renamed as the setting chosen.
43 | set LFTP4WIN_USERNAME=IPERF3_BUILD
44 |
45 | :: Show the packet manager if you need to specify a program version during installation instead of using the current release (default), like openssh 7.9 instead of 8.0 for Lftp.
46 | set CYGWIN_PACKET_MANAGER=
47 |
48 | :: Packages are loaded from the packages_basic.cmd and packages_openssl.cmd. The action matrix copies the one it needs to ci-cygwin-installer-packages.cmd
49 | echo Loading package dependencies from ci-cygwin-installer-packages.cmd
50 | set /p CYGWIN_PACKAGES= "%LFTP4WIN_ROOT%\etc\fstab"
165 |
166 | :: Configure our Cygwin Environment
167 | "%LFTP4WIN_ROOT%\bin\mkgroup.exe" -c > cygwin/etc/group || goto :fail
168 | "%LFTP4WIN_ROOT%\bin\bash.exe" -c "echo ""$USERNAME:*:1001:$(cygwin/bin/mkpasswd -c | cygwin/bin/cut -d':' -f 4):$(cygwin/bin/mkpasswd -c | cygwin/bin/cut -d':' -f 5):$(cygwin/bin/cygpath.exe -u ""%~dp0""):/bin/bash""" > cygwin/etc/passwd || goto :fail
169 | :: Fix a symlink bug in Cygwin
170 | "%LFTP4WIN_ROOT%\bin\ln.exe" -fsn '../usr/share/terminfo' '/lib/terminfo' || goto :fail
171 |
172 | if "%INSTALL_LFTP4WIN_CORE%" == "yes" (
173 | "%LFTP4WIN_ROOT%\bin\bsdtar.exe" -xmf "%INSTALL_TEMP%\lftp4win_core.zip" --strip-components=1 -C "%LFTP4WIN_BASE%\" || goto :fail
174 | "%LFTP4WIN_ROOT%\bin\touch.exe" "%LFTP4WIN_ROOT%\.core-installed"
175 | )
176 |
177 | set Init_sh=%LFTP4WIN_ROOT%\portable-init.sh
178 | echo Creating [%Init_sh%]
179 | echo.
180 | (
181 | echo #!/usr/bin/env bash
182 | echo.
183 | echo ## Map Current Windows User to root user
184 | echo.
185 | echo unset HISTFILE
186 | echo.
187 | echo rm -f /etc/{passwd,group}
188 | echo sed -ri "s@# db_home: (.*)@db_home: ${HOME}@" /etc/nsswitch.conf
189 | echo.
190 | echo ## Adjust the Cygwin packages cache path
191 | echo.
192 | echo pkg_cache_dir=$(cygpath -w "$LFTP4WIN_ROOT/.pkg-cache"^)
193 | echo.
194 | echo sed -ri 's#(.*^)\.pkg-cache$#'"\t${pkg_cache_dir//\\/\\\\}"'#' /etc/setup/setup.rc
195 | echo.
196 | echo set HISTFILE
197 | ) > "%Init_sh%" || goto :fail
198 |
199 | "%LFTP4WIN_ROOT%\bin\sed" -i 's/\r$//' "%Init_sh%" || goto :fail
200 |
201 | IF EXIST "%LFTP4WIN_ROOT%\etc\fstab" "%LFTP4WIN_ROOT%\bin\sed" -i 's/\r$//' "%LFTP4WIN_ROOT%\etc\fstab"
202 |
203 | IF EXIST "%LFTP4WIN_ROOT%\portable-init.sh" "%LFTP4WIN_ROOT%\bin\bash" -li "%LFTP4WIN_ROOT%\portable-init.sh"
204 |
205 | echo ###########################################################
206 | echo # Installing [LFTP4WIN Portable] succeeded.
207 | echo ###########################################################
208 | echo.
209 |
210 | del /q "%INSTALL_TEMP%\%CYGWIN_SETUP_EXE%" "%LFTP4WIN_ROOT%\Cygwin.bat" "%LFTP4WIN_ROOT%\Cygwin.ico" "%LFTP4WIN_ROOT%\Cygwin-Terminal.ico"
211 |
212 | if "%INSTALL_LFTP4WIN_CORE%" == "yes" (
213 | DEL /Q "%LFTP4WIN_BASE%\.gitattributes" "%LFTP4WIN_BASE%\README.md" "%LFTP4WIN_BASE%\LICENSE.txt" "%INSTALL_TEMP%\lftp4win_core.zip"
214 | RMDIR /S /Q "%LFTP4WIN_BASE%\docs"
215 | )
216 |
217 | goto :eof
218 |
219 | :fail
220 | set exit_code=%ERRORLEVEL%
221 | if exist "%DOWNLOADER%" (
222 | del "%DOWNLOADER%"
223 | )
224 | echo.
225 | echo ###########################################################
226 | echo # Installing [LFTP4WIN Portable] FAILED!
227 | echo ###########################################################
228 | echo.
229 | exit /B %exit_code%
230 |
231 | :download
232 | if exist "%2" (
233 | echo Deleting existing [%2]
234 | del "%2" || goto :fail
235 | )
236 |
237 | where /q curl
238 | if %ERRORLEVEL% EQU 0 (
239 | call :download_with_curl "%1" "%2"
240 | )
241 |
242 | if errorlevel 1 (
243 | call :download_with_powershell "%1" "%2"
244 | )
245 |
246 | if errorlevel 1 (
247 | call :download_with_vbs "%1" "%2" || goto :fail
248 | )
249 |
250 | exit /B 0
251 |
252 | :download_with_curl
253 | if "%PROXY_HOST%" == "" (
254 | set "http_proxy="
255 | set "https_proxy="
256 | ) else (
257 | set http_proxy=http://%PROXY_HOST%:%PROXY_PORT%
258 | set https_proxy=http://%PROXY_HOST%:%PROXY_PORT%
259 | )
260 | echo Downloading %1 to %2 using curl
261 | curl -sL %1 -# -o %2 || exit /B 1
262 | exit /B 0
263 |
264 | :download_with_vbs
265 | :: create VB script that can download files
266 | :: not using PowerShell which may be blocked by group policies
267 | set DOWNLOADER=%INSTALL_ROOT%downloader.vbs
268 | echo Creating [%DOWNLOADER%] script
269 | if "%PROXY_HOST%" == "" (
270 | set DOWNLOADER_PROXY=.
271 | ) else (
272 | set DOWNLOADER_PROXY= req.SetProxy 2, "%PROXY_HOST%:%PROXY_PORT%", ""
273 | )
274 |
275 | (
276 | echo url = Wscript.Arguments(0^)
277 | echo target = Wscript.Arguments(1^)
278 | echo On Error Resume Next
279 | echo reqType = "WinHttp.WinHttpRequest.5.1"
280 | echo Set req = CreateObject(reqType^)
281 | echo If req Is Nothing Then
282 | echo reqType = "MSXML2.XMLHTTP.6.0"
283 | echo Set req = CreateObject(reqType^)
284 | echo End If
285 | echo WScript.Echo "Downloading '" ^& url ^& "' to '" ^& target ^& "' using '" ^& reqType ^& "'"
286 | echo%DOWNLOADER_PROXY%
287 | echo req.Open "GET", url, False
288 | echo req.Send
289 | echo If Err.Number ^<^> 0 Then
290 | echo WScript.Quit 1
291 | echo End If
292 | echo If req.Status ^<^> 200 Then
293 | echo WScript.Echo "FAILED to download: HTTP Status " ^& req.Status
294 | echo WScript.Quit 1
295 | echo End If
296 | echo Set buff = CreateObject("ADODB.Stream"^)
297 | echo buff.Open
298 | echo buff.Type = 1
299 | echo buff.Write req.ResponseBody
300 | echo buff.Position = 0
301 | echo buff.SaveToFile target
302 | echo buff.Close
303 | echo.
304 | ) >"%DOWNLOADER%" || goto :fail
305 |
306 | cscript //Nologo "%DOWNLOADER%" %1 %2 || exit /B 1
307 | del "%DOWNLOADER%"
308 | exit /B 0
309 |
310 | :download_with_powershell
311 | if "%PROXY_HOST%" == "" (
312 | set "http_proxy="
313 | set "https_proxy="
314 | ) else (
315 | set http_proxy=http://%PROXY_HOST%:%PROXY_PORT%
316 | set https_proxy=http://%PROXY_HOST%:%PROXY_PORT%
317 | )
318 | echo Downloading %1 to %2 using powershell
319 | powershell "[Net.ServicePointManager]::SecurityProtocol = 'tls12, tls11, tls'; (New-Object Net.WebClient).DownloadFile('%1', '%2')" || exit /B 1
320 | exit /B 0
321 |
--------------------------------------------------------------------------------
/ci-linux-crossbuild.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # A very simple script to cross-compile iperf3 with openssl for variety of targets using ghcr.io/userdocs/qbt-musl-cross-make docker images
4 | #
5 | # Example - to cross-compile iperf3 for aarch64-linux-musl save the script in ~/iperf3 then use the following command:
6 | #
7 | # docker run -it -w /home/gh -v ~/iperf3:/home/gh ghcr.io/userdocs/qbt-musl-cross-make:aarch64-linux-musl /bin/bash crossbuild.sh
8 |
9 | github_repo="${1:-"https://github.com/esnet/iperf.git"}"
10 | github_branch="${2:-"master"}"
11 | crossbuild_target="${3:-${CC/-gcc/}}"
12 | arch="${4:-x86_64}"
13 |
14 | printf '\n%s\n' "Building iperf3 for $crossbuild_target"
15 | printf '%s\n\n' "repo: $github_repo branch:$github_branch"
16 |
17 | sudo apk update
18 |
19 | CXXFLAGS="--static -static -I/home/gh/local/include"
20 | LDFLAGS="--static -static -L/home/gh/local/lib"
21 |
22 | cd || exit
23 | mkdir -p /home/gh/local
24 |
25 | repo="$(cat /etc/apk/repositories | sed -rn 's|https://dl-cdn.alpinelinux.org/alpine/(.*)/(.*)|\1|p' | head -1)"
26 | openssl_libs_static="$(apk info openssl-libs-static | head -1 | awk '{ print $1 }')"
27 | openssl_dev="$(apk info openssl-dev | head -1 | awk '{ print $1 }')"
28 |
29 | curl -sLO "https://dl-cdn.alpinelinux.org/alpine/${repo}/main/${arch}/${openssl_dev}.apk"
30 | curl -sLO "https://dl-cdn.alpinelinux.org/alpine/${repo}/main/${arch}/${openssl_libs_static}.apk"
31 | tar -xzf "${openssl_dev}.apk" --strip-components=1 -C /home/gh/local
32 | tar -xzf "${openssl_libs_static}.apk" --strip-components=1 -C /home/gh/local
33 |
34 | rm -rf /home/gh/iperf3
35 | git clone --no-tags --single-branch --branch "${github_branch}" --shallow-submodules --recurse-submodules -j"$(nproc)" --depth 1 "${github_repo}" /home/gh/iperf3
36 | cd /home/gh/iperf3 || exit
37 |
38 | ./configure --with-openssl="/home/gh/local" --disable-shared --enable-static-bin --prefix="/home/gh/local"
39 | make -j$(nproc)
40 | make install
41 |
--------------------------------------------------------------------------------
/ci-release-body.md:
--------------------------------------------------------------------------------
1 | ## Software provenance
2 |
3 | > [!NOTE]
4 | > These release assets were transparently built for easy verification of their provenance.
5 |
6 | Using GitHub actions and workflows, binaries are verified using GitHub attestation and VirusTotal scanning, at build time, so that you can be certain the release assets you are using were transparently built from the source code.
7 |
8 | - GitHub attestation will show where when and how the binary was built - [example](https://github.com/userdocs/iperf3-static/attestations/2474371)
9 | - VirusTotal scanning will show the binary is malware free before release - [example](https://www.virustotal.com/gui/file/42647b55aae08c3b581e78e1a6bcadf2c7715d4edfc2c842ecbb194b0b47b084)
10 |
11 | > [!TIP]
12 | > The sha256sum of the GitHub attestations and VirusTotal scan should be the same for any release assets.
13 |
14 | ## GitHub artifact-attestations
15 |
16 |
17 | Expand for details
18 |
19 | Binaries built from the release of `3.17.1+` use [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) - [Github Docs](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds#verifying-artifact-attestations-with-the-github-cli)
20 |
21 | For example: using `gh` cli - [manual](https://cli.github.com/manual/gh_attestation_verify)
22 |
23 | ```bash
24 | gh attestation verify iperf3-amd64 -o userdocs
25 | ```
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | ## VirusTotal scan results
36 |
37 |
38 | Expand for details
39 |
40 | Links to scan results
41 |
42 | [iperf3-amd64]()
43 |
44 | [iperf3-amd64-win]()
45 |
46 | [iperf3-amd64-win-openssl]()
47 |
48 | [iperf3-amd64-osx-13]()
49 |
50 | [iperf3-arm64-osx-14]()
51 |
52 | [iperf3-arm32v6]()
53 |
54 | [iperf3-arm32v7]()
55 |
56 | [iperf3-arm64v8]()
57 |
58 | [iperf3-i386]()
59 |
60 | [iperf3-ppc64le]()
61 |
62 | [iperf3-riscv64]()
63 |
64 | [iperf3-s390x]()
65 |
66 |
67 |
--------------------------------------------------------------------------------
/ci-windows-cygwin-build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | HOME="$(pwd)"
4 | with_openssl="${1:-no}"
5 | if [[ "${2}" =~ ^/ ]]; then
6 | cygwin_path="${2}"
7 | else
8 | cygwin_path="${HOME}/${2:-cygwin}"
9 | fi
10 | source_repo="${3:-https://github.com/esnet/iperf.git}"
11 | source_branch="${4:-master}"
12 |
13 | printf '\n%b\n' " \e[93m\U25cf\e[0m With openssl = ${with_openssl}"
14 | printf '%b\n' " \e[93m\U25cf\e[0m Build path = ${HOME}"
15 | printf '%b\n' " \e[93m\U25cf\e[0m Cygwin path = ${cygwin_path}"
16 |
17 | printf '\n%b\n' " \e[93m\U25cf\e[0m parameters = ${*}"
18 |
19 | printf '\n%b\n' " \e[93m\U25cf\e[0m with_openssl = ${with_openssl}"
20 | printf '\n%b\n' " \e[93m\U25cf\e[0m cygwin_path = ${cygwin_path}"
21 | printf '\n%b\n' " \e[93m\U25cf\e[0m source_repo = ${source_repo}"
22 | printf '\n%b\n' " \e[93m\U25cf\e[0m source_branch = ${source_branch}"
23 |
24 | if [[ "${with_openssl}" == 'yes' ]]; then
25 | printf '\n%b\n' " \e[94m\U25cf\e[0m Downloading zlib"
26 | curl -sLO "https://github.com/userdocs/qbt-workflow-files/releases/latest/download/zlib.tar.xz"
27 |
28 | openssl_version="$(git ls-remote -q -t --refs "https://github.com/openssl/openssl.git" | awk '/openssl-3\.1\./{sub("refs/tags/", "");sub("(.*)(v6|rc|alpha|beta)(.*)", ""); print $2 }' | awk '!/^$/' | sort -rV | head -n1)"
29 |
30 | printf '\n%b\n' " \e[94m\U25cf\e[0m Downloading openssl ${openssl_version}"
31 | curl -sLO "https://github.com/openssl/openssl/releases/download/${openssl_version}/${openssl_version}.tar.gz"
32 |
33 | printf '\n%b\n' " \e[94m\U25cf\e[0m Extracting zlib"
34 | rm -rf "zlib" && tar xf "zlib.tar.xz"
35 |
36 | printf '\n%b\n' " \e[94m\U25cf\e[0m Extracting openssl"
37 | rm -rf "openssl" && mkdir -p "openssl"
38 | tar xf "${openssl_version}.tar.gz" --strip-components=1 -C "openssl"
39 |
40 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Configuring zlib"
41 | pushd "zlib" || exit 1
42 | ./configure --prefix="${cygwin_path}" --static --zlib-compat
43 |
44 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Building with zlib"
45 | make -j"$(nproc)"
46 | make install
47 |
48 | popd || exit 1
49 |
50 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Configuring openssl"
51 | pushd "${HOME}/openssl" || exit 1
52 | ./config --prefix="${cygwin_path}" --libdir=lib threads no-shared no-dso no-comp
53 |
54 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Building openssl"
55 | make -j"$(nproc)"
56 | make install_sw
57 |
58 | popd || exit 1
59 | fi
60 |
61 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Cloning iperf3 git repo"
62 |
63 | [[ -d "$HOME/iperf3_build" ]] && rm -rf "$HOME/iperf3_build"
64 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m git clone --no-tags --single-branch --branch ${source_branch} --shallow-submodules --recurse-submodules -j$(nproc) --depth 1 ${source_repo} $HOME/iperf3_build"
65 | git clone --no-tags --single-branch --branch "${source_branch}" --shallow-submodules --recurse-submodules -j"$(nproc)" --depth 1 "${source_repo}" "$HOME/iperf3_build"
66 | cd "$HOME/iperf3_build" || exit 1
67 |
68 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Repo Info"
69 |
70 | git remote show origin
71 |
72 | printf '\n%b\n' " \e[92m\U25cf\e[0m Setting iperf3 version to file iperf3_version"
73 | sed -rn 's|(.*)\[(.*)],\[https://github.com/esnet/iperf],(.*)|\2|p' configure.ac > "$HOME/iperf3_version"
74 |
75 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Bootstrapping iperf3"
76 |
77 | ./bootstrap.sh
78 |
79 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m Configuring iperf3"
80 | ./configure --disable-shared --enable-static --enable-static-bin --prefix="$HOME/iperf3"
81 |
82 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m make"
83 | make -j"$(nproc)"
84 |
85 | printf '\n%b\n\n' " \e[94m\U25cf\e[0m make install"
86 | [[ -d "$HOME/iperf3" ]] && rm -rf "$HOME/iperf3"
87 | make install
88 |
89 | if [[ -d "$HOME/iperf3/bin" ]]; then
90 | printf '\n%b\n' " \e[94m\U25cf\e[0m Copy dll dependencies"
91 | [[ -f "${cygwin_path}/bin/cygwin1.dll" ]] && cp -f "${cygwin_path}/bin/cygwin1.dll" "$HOME/iperf3/bin"
92 | printf '\n%b\n' " \e[92m\U25cf\e[0m Copied the dll dependencies"
93 | fi
94 |
--------------------------------------------------------------------------------
/pwsh-here.cmd:
--------------------------------------------------------------------------------
1 | powershell.exe -noexit -command Set-Location -literalPath "%~dp0."
--------------------------------------------------------------------------------
/zizmor.yml:
--------------------------------------------------------------------------------
1 | rules:
2 | unpinned-uses: # https://woodruffw.github.io/zizmor/audits/#unpinned-uses
3 | config:
4 | policies:
5 | "*": ref-pin
6 |
--------------------------------------------------------------------------------