diff --git a/.ci/docker-compose-file/docker-compose-emqx-cluster.yaml b/.ci/docker-compose-file/docker-compose-emqx-cluster.yaml index 65bf4faf8..5745dcf5b 100644 --- a/.ci/docker-compose-file/docker-compose-emqx-cluster.yaml +++ b/.ci/docker-compose-file/docker-compose-emqx-cluster.yaml @@ -19,7 +19,9 @@ services: - emqx2 volumes: - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg - - ../../apps/emqx/etc/certs:/usr/local/etc/haproxy/certs + - ../../apps/emqx/etc/certs/cert.pem:/usr/local/etc/haproxy/certs/cert.pem + - ../../apps/emqx/etc/certs/key.pem:/usr/local/etc/haproxy/certs/key.pem + - ../../apps/emqx/etc/certs/cacert.pem:/usr/local/etc/haproxy/certs/cacert.pem ports: - "18083:18083" # - "1883:1883" @@ -34,7 +36,7 @@ services: - -c - | set -x - cat /usr/local/etc/haproxy/certs/cert.pem /usr/local/etc/haproxy/certs/key.pem > /tmp/emqx.pem + cat /usr/local/etc/haproxy/certs/cert.pem /usr/local/etc/haproxy/certs/key.pem > /var/lib/haproxy/emqx.pem haproxy -f /usr/local/etc/haproxy/haproxy.cfg emqx1: diff --git a/.ci/docker-compose-file/haproxy/haproxy.cfg b/.ci/docker-compose-file/haproxy/haproxy.cfg index 1f10c4f9e..8a863c2d3 100644 --- a/.ci/docker-compose-file/haproxy/haproxy.cfg +++ b/.ci/docker-compose-file/haproxy/haproxy.cfg @@ -83,13 +83,13 @@ backend emqx_ws_back frontend emqx_ssl mode tcp option tcplog - bind *:8883 ssl crt /tmp/emqx.pem ca-file /usr/local/etc/haproxy/certs/cacert.pem verify required no-sslv3 + bind *:8883 ssl crt /var/lib/haproxy/emqx.pem ca-file /usr/local/etc/haproxy/certs/cacert.pem verify required no-sslv3 default_backend emqx_ssl_back frontend emqx_wss mode tcp option tcplog - bind *:8084 ssl crt /tmp/emqx.pem ca-file /usr/local/etc/haproxy/certs/cacert.pem verify required no-sslv3 + bind *:8084 ssl crt /var/lib/haproxy/emqx.pem ca-file /usr/local/etc/haproxy/certs/cacert.pem verify required no-sslv3 default_backend emqx_wss_back backend emqx_ssl_back diff --git a/.github/actions/prepare-jmeter/action.yaml b/.github/actions/prepare-jmeter/action.yaml new file mode 100644 index 000000000..e3d30af1a --- /dev/null +++ b/.github/actions/prepare-jmeter/action.yaml @@ -0,0 +1,49 @@ +name: 'Prepare jmeter' + +inputs: + version-emqx: + required: true + type: string + +runs: + using: composite + steps: + - uses: actions/download-artifact@v3 + with: + name: emqx-docker + path: /tmp + - name: load docker image + shell: bash + env: + PKG_VSN: ${{ inputs.version-emqx }} + run: | + EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g') + echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV + - uses: actions/checkout@v3 + with: + repository: emqx/emqx-fvt + ref: broker-autotest-v5 + path: scripts + - uses: actions/setup-java@v3 + with: + java-version: '8.0.282' # The JDK version to make available on the path. + java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk + architecture: x64 # (x64 or x86) - defaults to x64 + # https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md + distribution: 'zulu' + - uses: actions/download-artifact@v3 + with: + name: apache-jmeter.tgz + - name: install jmeter + shell: bash + env: + JMETER_VERSION: 5.4.3 + run: | + tar -xf apache-jmeter.tgz + ln -s apache-jmeter-$JMETER_VERSION jmeter + echo "jmeter.save.saveservice.output_format=xml" >> jmeter/user.properties + echo "jmeter.save.saveservice.response_data.on_error=true" >> jmeter/user.properties + cd jmeter/lib/ext + wget --no-verbose https://raw.githubusercontent.com/xmeter-net/mqtt-jmeter/master/Download/v2.0.2/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar + wget --no-verbose https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar + wget --no-verbose https://repo1.maven.org/maven2/org/postgresql/postgresql/42.2.18/postgresql-42.2.18.jar diff --git a/.github/workflows/_pr_entrypoint.yaml b/.github/workflows/_pr_entrypoint.yaml new file mode 100644 index 000000000..ec2bbf2e1 --- /dev/null +++ b/.github/workflows/_pr_entrypoint.yaml @@ -0,0 +1,242 @@ +name: PR Entrypoint + +concurrency: + group: pr-entrypoint-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +on: + pull_request: + workflow_dispatch: + inputs: + ref: + required: false + +env: + IS_CI: "yes" + +jobs: + sanity-checks: + runs-on: ${{ github.repository_owner == 'emqx' && 'aws-amd64' || 'ubuntu-22.04' }} + container: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" + outputs: + ct-matrix: ${{ steps.matrix.outputs.ct-matrix }} + ct-host: ${{ steps.matrix.outputs.ct-host }} + ct-docker: ${{ steps.matrix.outputs.ct-docker }} + version-emqx: ${{ steps.matrix.outputs.version-emqx }} + version-emqx-enterprise: ${{ steps.matrix.outputs.version-emqx-enterprise }} + runner: ${{ github.repository_owner == 'emqx' && 'aws-amd64' || 'ubuntu-22.04' }} + builder: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" + builder_vsn: "5.1-3" + otp_vsn: "25.3.2-1" + elixir_vsn: "1.14.5" + + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.inputs.ref }} + fetch-depth: 0 + - name: Work around https://github.com/actions/checkout/issues/766 + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Run gitlint + env: + BEFORE_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }} + AFTER_REF: ${{ github.sha }} + run: | + pip install gitlint + gitlint --commits $BEFORE_REF..$AFTER_REF --config .github/workflows/.gitlint + - name: Run shellcheck + run: | + DEBIAN_FRONTEND=noninteractive apt-get update -qy && apt-get install -qy shellcheck + ./scripts/shellcheck.sh + - name: Run shell tests + run: | + DEBIAN_FRONTEND=noninteractive apt-get update -qy && apt-get install -qy shelltestrunner + scripts/shelltest/run_tests.sh + - name: Check workflow files + env: + ACTIONLINT_VSN: 1.6.25 + run: | + wget https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VSN}/actionlint_${ACTIONLINT_VSN}_linux_amd64.tar.gz + tar zxf actionlint_${ACTIONLINT_VSN}_linux_amd64.tar.gz actionlint + # TODO: enable shellcheck when all the current issues are fixed + ./actionlint -color \ + -shellcheck= \ + -ignore 'label ".+" is unknown' \ + -ignore 'value "emqx-enterprise" in "exclude"' + - name: Check line-break at EOF + run: | + ./scripts/check-nl-at-eof.sh + - name: Check apps version + run: | + ./scripts/apps-version-check.sh + - name: Setup mix + env: + MIX_ENV: emqx-enterprise + PROFILE: emqx-enterprise + run: | + mix local.hex --force --if-missing && mix local.rebar --force --if-missing + - name: Check formatting + env: + MIX_ENV: emqx-enterprise + PROFILE: emqx-enterprise + run: | + ./scripts/check-format.sh + - name: Run elvis check + run: | + ./scripts/elvis-check.sh $GITHUB_BASE_REF + - name: Generate CT Matrix + id: matrix + run: | + APPS="$(./scripts/find-apps.sh --ci)" + MATRIX="$(echo "${APPS}" | jq -c ' + [ + (.[] | select(.profile == "emqx") | . + { + builder: "5.1-3", + otp: "25.3.2-1", + elixir: "1.14.5" + }), + (.[] | select(.profile == "emqx-enterprise") | . + { + builder: "5.1-3", + otp: ["25.3.2-1"][], + elixir: "1.14.5" + }) + ] + ')" + echo "${MATRIX}" | jq + CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile, builder, otp, elixir}) | unique')" + CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')" + CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')" + echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT + echo "ct-host=${CT_HOST}" | tee -a $GITHUB_OUTPUT + echo "ct-docker=${CT_DOCKER}" | tee -a $GITHUB_OUTPUT + echo "version-emqx=$(./pkg-vsn.sh emqx)" | tee -a $GITHUB_OUTPUT + echo "version-emqx-enterprise=$(./pkg-vsn.sh emqx-enterprise)" | tee -a $GITHUB_OUTPUT + + compile: + runs-on: ${{ needs.sanity-checks.outputs.runner }} + container: ${{ needs.sanity-checks.outputs.builder }} + needs: + - sanity-checks + strategy: + matrix: + profile: + - emqx + - emqx-enterprise + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Work around https://github.com/actions/checkout/issues/766 + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + - id: compile + env: + PROFILE: ${{ matrix.profile }} + ENABLE_COVER_COMPILE: 1 + run: | + make ensure-rebar3 + make ${PROFILE} + make test-compile + zip -ryq $PROFILE.zip . + - uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.profile }} + path: ${{ matrix.profile }}.zip + retention-days: 1 + + run_test_cases: + needs: + - sanity-checks + - compile + uses: ./.github/workflows/run_test_cases.yaml + with: + runner: ${{ needs.sanity-checks.outputs.runner }} + builder: ${{ needs.sanity-checks.outputs.builder }} + ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }} + ct-host: ${{ needs.sanity-checks.outputs.ct-host }} + ct-docker: ${{ needs.sanity-checks.outputs.ct-docker }} + + static_checks: + needs: + - sanity-checks + - compile + uses: ./.github/workflows/static_checks.yaml + with: + runner: ${{ needs.sanity-checks.outputs.runner }} + builder: ${{ needs.sanity-checks.outputs.builder }} + ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }} + + build_slim_packages: + needs: + - sanity-checks + uses: ./.github/workflows/build_slim_packages.yaml + with: + runner: ${{ needs.sanity-checks.outputs.runner }} + builder: ${{ needs.sanity-checks.outputs.builder }} + builder_vsn: ${{ needs.sanity-checks.outputs.builder_vsn }} + otp_vsn: ${{ needs.sanity-checks.outputs.otp_vsn }} + elixir_vsn: ${{ needs.sanity-checks.outputs.elixir_vsn }} + + build_docker_for_test: + needs: + - sanity-checks + uses: ./.github/workflows/build_docker_for_test.yaml + with: + otp_vsn: ${{ needs.sanity-checks.outputs.otp_vsn }} + elixir_vsn: ${{ needs.sanity-checks.outputs.elixir_vsn }} + version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }} + version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }} + + spellcheck: + needs: + - sanity-checks + - build_slim_packages + uses: ./.github/workflows/spellcheck.yaml + with: + runner: ${{ needs.sanity-checks.outputs.runner }} + + run_conf_tests: + needs: + - sanity-checks + - compile + uses: ./.github/workflows/run_conf_tests.yaml + with: + runner: ${{ needs.sanity-checks.outputs.runner }} + builder: ${{ needs.sanity-checks.outputs.builder }} + + check_deps_integrity: + needs: + - sanity-checks + uses: ./.github/workflows/check_deps_integrity.yaml + with: + runner: ${{ needs.sanity-checks.outputs.runner }} + builder: ${{ needs.sanity-checks.outputs.builder }} + + run_jmeter_tests: + needs: + - sanity-checks + - build_docker_for_test + uses: ./.github/workflows/run_jmeter_tests.yaml + with: + version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }} + + run_docker_tests: + needs: + - sanity-checks + - build_docker_for_test + uses: ./.github/workflows/run_docker_tests.yaml + with: + runner: ${{ needs.sanity-checks.outputs.runner }} + version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }} + version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }} + + run_helm_tests: + needs: + - sanity-checks + - build_docker_for_test + uses: ./.github/workflows/run_helm_tests.yaml + with: + version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }} + version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }} diff --git a/.github/workflows/_push-entrypoint.yaml b/.github/workflows/_push-entrypoint.yaml new file mode 100644 index 000000000..9faceebbc --- /dev/null +++ b/.github/workflows/_push-entrypoint.yaml @@ -0,0 +1,191 @@ +name: Push Entrypoint + +concurrency: + group: push-entrypoint-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + tags: + - 'v*' + - 'e*' + branches: + - 'master' + - 'release-51' + - 'ci/**' + +env: + IS_CI: 'yes' + +jobs: + prepare: + runs-on: ${{ github.repository_owner == 'emqx' && 'aws-amd64' || 'ubuntu-22.04' }} + container: 'ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04' + outputs: + profile: ${{ steps.parse-git-ref.outputs.profile }} + edition: ${{ steps.parse-git-ref.outputs.edition }} + release: ${{ steps.parse-git-ref.outputs.release }} + latest: ${{ steps.parse-git-ref.outputs.latest }} + version: ${{ steps.parse-git-ref.outputs.version }} + ct-matrix: ${{ steps.matrix.outputs.ct-matrix }} + ct-host: ${{ steps.matrix.outputs.ct-host }} + ct-docker: ${{ steps.matrix.outputs.ct-docker }} + runner: ${{ github.repository_owner == 'emqx' && 'aws-amd64' || 'ubuntu-22.04' }} + builder: 'ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04' + builder_vsn: '5.1-3' + otp_vsn: '25.3.2-1' + elixir_vsn: '1.14.5' + + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.inputs.ref }} + fetch-depth: 0 + - name: Work around https://github.com/actions/checkout/issues/766 + shell: bash + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Detect emqx profile and version + id: parse-git-ref + run: | + JSON="$(./scripts/parse-git-ref.sh $GITHUB_REF)" + PROFILE=$(echo "$JSON" | jq -cr '.profile') + EDITION=$(echo "$JSON" | jq -cr '.edition') + RELEASE=$(echo "$JSON" | jq -cr '.release') + LATEST=$(echo "$JSON" | jq -cr '.latest') + VERSION="$(./pkg-vsn.sh "$PROFILE")" + echo "profile=$PROFILE" | tee -a $GITHUB_OUTPUT + echo "edition=$EDITION" | tee -a $GITHUB_OUTPUT + echo "release=$RELEASE" | tee -a $GITHUB_OUTPUT + echo "latest=$LATEST" | tee -a $GITHUB_OUTPUT + echo "version=$VERSION" | tee -a $GITHUB_OUTPUT + - name: Build matrix + id: matrix + run: | + APPS="$(./scripts/find-apps.sh --ci)" + MATRIX="$(echo "${APPS}" | jq -c ' + [ + (.[] | select(.profile == "emqx") | . + { + builder: "5.1-3", + otp: "25.3.2-1", + elixir: "1.14.5" + }), + (.[] | select(.profile == "emqx-enterprise") | . + { + builder: "5.1-3", + otp: ["25.3.2-1"][], + elixir: "1.14.5" + }) + ] + ')" + echo "${MATRIX}" | jq + CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile, builder, otp, elixir}) | unique')" + CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')" + CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')" + echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT + echo "ct-host=${CT_HOST}" | tee -a $GITHUB_OUTPUT + echo "ct-docker=${CT_DOCKER}" | tee -a $GITHUB_OUTPUT + + build_slim_packages: + if: ${{ needs.prepare.outputs.release != 'true' }} + needs: + - prepare + uses: ./.github/workflows/build_slim_packages.yaml + with: + runner: ${{ needs.prepare.outputs.runner }} + builder: ${{ needs.prepare.outputs.builder }} + builder_vsn: ${{ needs.prepare.outputs.builder_vsn }} + otp_vsn: ${{ needs.prepare.outputs.otp_vsn }} + elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }} + + build_packages: + if: ${{ needs.prepare.outputs.release == 'true' }} + needs: + - prepare + uses: ./.github/workflows/build_packages.yaml + with: + profile: ${{ needs.prepare.outputs.profile }} + publish: ${{ needs.prepare.outputs.release }} + otp_vsn: ${{ needs.prepare.outputs.otp_vsn }} + elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }} + runner: ${{ needs.prepare.outputs.runner }} + builder_vsn: ${{ needs.prepare.outputs.builder_vsn }} + + build_and_push_docker_images: + if: ${{ needs.prepare.outputs.release == 'true' }} + needs: + - prepare + uses: ./.github/workflows/build_and_push_docker_images.yaml + with: + profile: ${{ needs.prepare.outputs.profile }} + edition: ${{ needs.prepare.outputs.edition }} + version: ${{ needs.prepare.outputs.version }} + latest: ${{ needs.prepare.outputs.latest }} + publish: ${{ needs.prepare.outputs.release }} + otp_vsn: ${{ needs.prepare.outputs.otp_vsn }} + elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }} + runner: ${{ needs.prepare.outputs.runner }} + builder_vsn: ${{ needs.prepare.outputs.builder_vsn }} + + compile: + runs-on: ${{ needs.prepare.outputs.runner }} + container: ${{ needs.prepare.outputs.builder }} + needs: + - prepare + strategy: + matrix: + profile: + - emqx + - emqx-enterprise + + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.inputs.ref }} + fetch-depth: 0 + - name: Work around https://github.com/actions/checkout/issues/766 + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + - id: compile + env: + PROFILE: ${{ matrix.profile }} + ENABLE_COVER_COMPILE: 1 + run: | + make $PROFILE + zip -ryq $PROFILE.zip . + - uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.profile }} + path: ${{ matrix.profile }}.zip + retention-days: 1 + + run_test_cases: + needs: + - prepare + - compile + uses: ./.github/workflows/run_test_cases.yaml + with: + runner: ${{ needs.prepare.outputs.runner }} + builder: ${{ needs.prepare.outputs.builder }} + ct-matrix: ${{ needs.prepare.outputs.ct-matrix }} + ct-host: ${{ needs.prepare.outputs.ct-host }} + ct-docker: ${{ needs.prepare.outputs.ct-docker }} + + run_conf_tests: + needs: + - prepare + - compile + uses: ./.github/workflows/run_conf_tests.yaml + with: + runner: ${{ needs.prepare.outputs.runner }} + builder: ${{ needs.prepare.outputs.builder }} + + static_checks: + needs: + - prepare + - compile + uses: ./.github/workflows/static_checks.yaml + with: + runner: ${{ needs.prepare.outputs.runner }} + builder: ${{ needs.prepare.outputs.builder }} + ct-matrix: ${{ needs.prepare.outputs.ct-matrix }} + diff --git a/.github/workflows/apps_version_check.yaml b/.github/workflows/apps_version_check.yaml deleted file mode 100644 index 52c467786..000000000 --- a/.github/workflows/apps_version_check.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: Check Apps Version - -on: [pull_request] - -jobs: - check_apps_version: - runs-on: ubuntu-22.04 - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Check apps version - run: ./scripts/apps-version-check.sh diff --git a/.github/workflows/build_and_push_docker_images.yaml b/.github/workflows/build_and_push_docker_images.yaml index e8066b8bc..33128e40d 100644 --- a/.github/workflows/build_and_push_docker_images.yaml +++ b/.github/workflows/build_and_push_docker_images.yaml @@ -5,138 +5,102 @@ concurrency: cancel-in-progress: true on: - push: - tags: - - v* - - e* - - docker-latest-* + workflow_call: + inputs: + profile: + required: true + type: string + edition: + required: true + type: string + version: + required: true + type: string + latest: + required: true + type: string + publish: + required: true + type: string + otp_vsn: + required: true + type: string + elixir_vsn: + required: true + type: string + runner: + required: true + type: string + builder_vsn: + required: true + type: string workflow_dispatch: inputs: - branch_or_tag: + ref: required: false + version: + required: true + type: string profile: required: false + type: string default: 'emqx' - is_latest: + edition: required: false + type: string + default: 'Opensource' + latest: + required: false + type: boolean default: false + publish: + required: false + type: boolean + default: false + otp_vsn: + required: false + type: string + default: '25.3.2-1' + elixir_vsn: + required: false + type: string + default: '1.14.5' + runner: + required: false + type: string + default: 'ubuntu-22.04' + builder_vsn: + required: false + type: string + default: '5.1-3' jobs: - prepare: - runs-on: ubuntu-22.04 - # prepare source with any OTP version, no need for a matrix - container: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" - - outputs: - PROFILE: ${{ steps.get_profile.outputs.PROFILE }} - EDITION: ${{ steps.get_profile.outputs.EDITION }} - IS_LATEST: ${{ steps.get_profile.outputs.IS_LATEST }} - IS_EXACT_TAG: ${{ steps.get_profile.outputs.IS_EXACT_TAG }} - VERSION: ${{ steps.get_profile.outputs.VERSION }} - - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.inputs.branch_or_tag }} # when input is not given, the event tag is used - path: source - fetch-depth: 0 - - - name: Get profiles to build - id: get_profile - env: - INPUTS_PROFILE: ${{ github.event.inputs.profile }} - run: | - cd source - # tag docker-latest-ce or docker-latest-ee - if git describe --tags --exact --match 'docker-latest-*' 2>/dev/null; then - echo 'is_latest=true due to docker-latest-* tag' - is_latest=true - elif [ "${{ inputs.is_latest }}" = "true" ]; then - echo 'is_latest=true due to manual input from workflow_dispatch' - is_latest=true - else - echo 'is_latest=false' - is_latest=false - fi - # resolve profile - if git describe --tags --match "v*" --exact; then - echo "This is an exact git tag, will publish images" - is_exact='true' - PROFILE=emqx - elif git describe --tags --match "e*" --exact; then - echo "This is an exact git tag, will publish images" - is_exact='true' - PROFILE=emqx-enterprise - else - echo "This is NOT an exact git tag, will not publish images" - is_exact='false' - fi - - case "${PROFILE:-$INPUTS_PROFILE}" in - emqx) - EDITION='Opensource' - ;; - emqx-enterprise) - EDITION='Enterprise' - ;; - *) - echo "ERROR: Failed to resolve build profile" - exit 1 - ;; - esac - - VSN="$(./pkg-vsn.sh "$PROFILE")" - echo "Building emqx/$PROFILE:$VSN image (latest=$is_latest)" - echo "Push = $is_exact" - echo "IS_LATEST=$is_latest" >> $GITHUB_OUTPUT - echo "IS_EXACT_TAG=$is_exact" >> $GITHUB_OUTPUT - echo "PROFILE=$PROFILE" >> $GITHUB_OUTPUT - echo "EDITION=$EDITION" >> $GITHUB_OUTPUT - echo "VERSION=$VSN" >> $GITHUB_OUTPUT - - name: get_all_deps - env: - PROFILE: ${{ steps.get_profile.outputs.PROFILE }} - run: | - zip -ryq source.zip source/* source/.[^.]* - - uses: actions/upload-artifact@v3 - with: - name: source - path: source.zip - docker: - runs-on: ubuntu-22.04 - needs: prepare + runs-on: ${{ inputs.runner }} strategy: fail-fast: false matrix: profile: - - "${{ needs.prepare.outputs.PROFILE }}" + - ${{ inputs.profile }} registry: - 'docker.io' - 'public.ecr.aws' os: - [debian11, "debian:11-slim", "deploy/docker/Dockerfile"] - # NOTE: 'otp' and 'elixir' are to configure emqx-builder image - # only support latest otp and elixir, not a matrix builder: - - 5.1-3 # update to latest + - ${{ inputs.builder_vsn }} otp: - - 25.3.2-1 + - ${{ inputs.otp_vsn }} elixir: - 'no_elixir' - - '1.14.5' # update to latest - exclude: # TODO: publish enterprise to ecr too? - - registry: 'public.ecr.aws' - profile: emqx-enterprise + - ${{ inputs.elixir_vsn }} steps: - - uses: actions/download-artifact@v3 + - uses: actions/checkout@v3 with: - name: source - path: . - - name: unzip source code - run: unzip -q source.zip + ref: ${{ github.event.inputs.ref }} + fetch-depth: 0 - uses: docker/setup-qemu-action@v2 - uses: docker/setup-buildx-action@v2 @@ -185,18 +149,18 @@ jobs: latest=${{ matrix.elixir == 'no_elixir' }} suffix=${{ steps.pre-meta.outputs.img_suffix }} tags: | - type=semver,pattern={{major}}.{{minor}},value=${{ needs.prepare.outputs.VERSION }} - type=semver,pattern={{version}},value=${{ needs.prepare.outputs.VERSION }} - type=raw,value=${{ needs.prepare.outputs.VERSION }} - type=raw,value=latest,enable=${{ needs.prepare.outputs.IS_LATEST }} + type=semver,pattern={{major}}.{{minor}},value=${{ inputs.version }} + type=semver,pattern={{version}},value=${{ inputs.version }} + type=raw,value=${{ inputs.version }} + type=raw,value=latest,enable=${{ inputs.latest }} labels: | org.opencontainers.image.otp.version=${{ matrix.otp }} - org.opencontainers.image.edition=${{ needs.prepare.outputs.EDITION }} + org.opencontainers.image.edition=${{ inputs.edition }} ${{ steps.pre-meta.outputs.extra_labels }} - uses: docker/build-push-action@v3 with: - push: ${{ needs.prepare.outputs.IS_EXACT_TAG == 'true' || github.repository_owner != 'emqx' }} + push: ${{ inputs.publish == 'true' || github.repository_owner != 'emqx' }} pull: true no-cache: true platforms: linux/amd64,linux/arm64 @@ -206,4 +170,4 @@ jobs: EMQX_NAME=${{ matrix.profile }}${{ steps.pre-meta.outputs.img_suffix }} EXTRA_DEPS=${{ steps.pre-meta.outputs.extra_deps }} file: source/${{ matrix.os[2] }} - context: source + diff --git a/.github/workflows/build_docker_for_test.yaml b/.github/workflows/build_docker_for_test.yaml new file mode 100644 index 000000000..548d5e2cd --- /dev/null +++ b/.github/workflows/build_docker_for_test.yaml @@ -0,0 +1,61 @@ +name: Build docker image for test + +concurrency: + group: docker-test-build-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_call: + inputs: + otp_vsn: + required: true + type: string + elixir_vsn: + required: true + type: string + version-emqx: + required: true + type: string + version-emqx-enterprise: + required: true + type: string + +jobs: + docker: + runs-on: ubuntu-latest + env: + EMQX_NAME: ${{ matrix.profile }} + PKG_VSN: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }} + OTP_VSN: ${{ inputs.otp_vsn }} + ELIXIR_VSN: ${{ inputs.elixir_vsn }} + + strategy: + fail-fast: false + matrix: + profile: + - emqx + - emqx-enterprise + - emqx-elixir + + steps: + - uses: actions/checkout@v3 + - name: build and export to Docker + id: build + run: | + make ${EMQX_NAME}-docker + echo "EMQX_IMAGE_TAG=$(cat .docker_image_tag)" >> $GITHUB_ENV + - name: smoke test + run: | + CID=$(docker run -d --rm -P $EMQX_IMAGE_TAG) + HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID) + ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT + docker stop $CID + - name: export docker image + run: | + docker save $EMQX_IMAGE_TAG | gzip > $EMQX_NAME-docker-$PKG_VSN.tar.gz + - uses: actions/upload-artifact@v3 + with: + name: "${{ env.EMQX_NAME }}-docker" + path: "${{ env.EMQX_NAME }}-docker-${{ env.PKG_VSN }}.tar.gz" + retention-days: 3 + diff --git a/.github/workflows/build_packages.yaml b/.github/workflows/build_packages.yaml index bb6b46612..94841edc8 100644 --- a/.github/workflows/build_packages.yaml +++ b/.github/workflows/build_packages.yaml @@ -1,81 +1,61 @@ name: Cross build packages concurrency: - group: build-${{ github.event_name }}-${{ github.ref }} + group: build-packages-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true on: - push: - branches: - - 'ci/**' - tags: - - v* - - e* + workflow_call: + inputs: + profile: + required: true + type: string + publish: + required: true + type: string + otp_vsn: + required: true + type: string + elixir_vsn: + required: true + type: string + runner: + required: true + type: string + builder_vsn: + required: true + type: string workflow_dispatch: inputs: - branch_or_tag: + ref: required: false profile: required: false + publish: + required: false + type: boolean + default: false + otp_vsn: + required: false + type: string + default: '25.3.2-1' + elixir_vsn: + required: false + type: string + default: '1.14.5' + runner: + required: false + type: string + default: 'ubuntu-22.04' + builder_vsn: + required: false + type: string + default: '5.1-3' jobs: - prepare: - runs-on: ubuntu-22.04 - container: ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04 - outputs: - BUILD_PROFILE: ${{ steps.get_profile.outputs.BUILD_PROFILE }} - IS_EXACT_TAG: ${{ steps.get_profile.outputs.IS_EXACT_TAG }} - VERSION: ${{ steps.get_profile.outputs.VERSION }} - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.inputs.branch_or_tag }} # when input is not given, the event tag is used - fetch-depth: 0 - - - name: Get profile to build - id: get_profile - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - tag=${{ github.ref }} - if git describe --tags --match "[v|e]*" --exact; then - echo "WARN: This is an exact git tag, will publish release" - is_exact_tag='true' - else - echo "WARN: This is NOT an exact git tag, will not publish release" - is_exact_tag='false' - fi - echo "IS_EXACT_TAG=${is_exact_tag}" >> $GITHUB_OUTPUT - case $tag in - refs/tags/v*) - PROFILE='emqx' - ;; - refs/tags/e*) - PROFILE=emqx-enterprise - ;; - *) - PROFILE=${{ github.event.inputs.profile }} - case "$PROFILE" in - emqx) - true - ;; - emqx-enterprise) - true - ;; - *) - # maybe triggered from schedule - echo "WARN: \"$PROFILE\" is not a valid profile." - echo "building the default profile 'emqx' instead" - PROFILE='emqx' - ;; - esac - ;; - esac - echo "BUILD_PROFILE=$PROFILE" >> $GITHUB_OUTPUT - echo "VERSION=$(./pkg-vsn.sh $PROFILE)" >> $GITHUB_OUTPUT - windows: runs-on: windows-2019 - if: startsWith(github.ref_name, 'v') + if: inputs.profile == 'emqx' strategy: fail-fast: false matrix: @@ -84,11 +64,11 @@ jobs: steps: - uses: actions/checkout@v3 with: - ref: ${{ github.event.inputs.branch_or_tag }} + ref: ${{ github.event.inputs.ref }} fetch-depth: 0 - uses: ilammy/msvc-dev-cmd@v1.12.0 - - uses: erlef/setup-beam@v1.15.4 + - uses: erlef/setup-beam@v1.16.0 with: otp-version: 25.3.2 - name: build @@ -125,14 +105,13 @@ jobs: path: _packages/${{ matrix.profile }}/ mac: - needs: prepare strategy: fail-fast: false matrix: profile: - - ${{ needs.prepare.outputs.BUILD_PROFILE }} + - ${{ inputs.profile }} otp: - - 25.3.2-1 + - ${{ inputs.otp_vsn }} os: - macos-11 - macos-12 @@ -142,7 +121,7 @@ jobs: - uses: emqx/self-hosted-cleanup-action@v1.0.3 - uses: actions/checkout@v3 with: - ref: ${{ github.event.inputs.branch_or_tag }} + ref: ${{ github.event.inputs.ref }} fetch-depth: 0 - uses: ./.github/actions/package-macos with: @@ -160,7 +139,6 @@ jobs: path: _packages/${{ matrix.profile }}/ linux: - needs: prepare runs-on: ${{ matrix.build_machine }} # always run in builder container because the host might have the wrong OTP version etc. # otherwise buildx.sh does not run docker if arch and os matches the target arch and os. @@ -171,9 +149,9 @@ jobs: fail-fast: false matrix: profile: - - ${{ needs.prepare.outputs.BUILD_PROFILE }} + - ${{ inputs.profile }} otp: - - 25.3.2-1 + - ${{ inputs.otp_vsn }} arch: - amd64 - arm64 @@ -193,9 +171,9 @@ jobs: - aws-arm64 - aws-amd64 builder: - - 5.1-3 + - ${{ inputs.builder_vsn }} elixir: - - 1.14.5 + - ${{ inputs.elixir_vsn }} with_elixir: - 'no' exclude: @@ -205,12 +183,12 @@ jobs: build_machine: aws-arm64 include: - profile: emqx - otp: 25.3.2-1 + otp: ${{ inputs.otp_vsn }} arch: amd64 os: ubuntu22.04 build_machine: aws-amd64 - builder: 5.1-3 - elixir: 1.14.5 + builder: ${{ inputs.builder_vsn }} + elixir: ${{ inputs.elixir_vsn }} with_elixir: 'yes' defaults: @@ -222,7 +200,7 @@ jobs: - uses: actions/checkout@v3 with: - ref: ${{ github.event.inputs.branch_or_tag }} + ref: ${{ github.event.inputs.ref }} fetch-depth: 0 - name: fix workdir @@ -267,14 +245,16 @@ jobs: path: _packages/${{ matrix.profile }}/ publish_artifacts: - runs-on: ubuntu-22.04 - needs: [prepare, mac, linux] - if: needs.prepare.outputs.IS_EXACT_TAG == 'true' + runs-on: ${{ inputs.runner }} + needs: + - mac + - linux + if: ${{ inputs.publish == 'true' }} strategy: fail-fast: false matrix: profile: - - ${{ needs.prepare.outputs.BUILD_PROFILE }} + - ${{ inputs.profile }} steps: - uses: actions/download-artifact@v3 with: @@ -284,7 +264,7 @@ jobs: run: sudo apt-get update && sudo apt install -y dos2unix - name: get packages run: | - set -e -u + set -eu cd packages/${{ matrix.profile }} # fix the .sha256 file format for var in $(ls | grep emqx | grep -v sha256); do diff --git a/.github/workflows/build_packages_cron.yaml b/.github/workflows/build_packages_cron.yaml index 09f68c256..b245078da 100644 --- a/.github/workflows/build_packages_cron.yaml +++ b/.github/workflows/build_packages_cron.yaml @@ -29,7 +29,7 @@ jobs: arch: - amd64 os: - - debian10 + - ubuntu22.04 - amzn2023 builder: - 5.1-3 @@ -94,7 +94,7 @@ jobs: otp: - 25.3.2-1 os: - - macos-12 + - macos-13 - macos-12-arm64 steps: @@ -117,6 +117,7 @@ jobs: with: name: ${{ matrix.profile }} path: _packages/${{ matrix.profile }}/ + retention-days: 7 - name: Send notification to Slack uses: slackapi/slack-github-action@v1.23.0 if: failure() @@ -125,3 +126,59 @@ jobs: with: payload: | {"text": "Scheduled build of ${{ matrix.profile }} package for ${{ matrix.os }} failed: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"} + + windows: + if: github.repository_owner == 'emqx' + runs-on: windows-2019 + strategy: + fail-fast: false + matrix: + profile: + - emqx + otp: + - 25.3.2 + steps: + - uses: actions/checkout@v3 + - uses: ilammy/msvc-dev-cmd@v1.12.0 + - uses: erlef/setup-beam@v1.16.0 + with: + otp-version: ${{ matrix.otp }} + - name: build + env: + PYTHON: python + DIAGNOSTIC: 1 + run: | + # ensure crypto app (openssl) + erl -eval "erlang:display(crypto:info_lib())" -s init stop + make ${{ matrix.profile }}-tgz + - name: run emqx + timeout-minutes: 5 + run: | + ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx start + Start-Sleep -s 10 + $pingOutput = ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx ping + if ($pingOutput = 'pong') { + echo "EMQX started OK" + } else { + echo "Failed to ping EMQX $pingOutput" + Exit 1 + } + ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx stop + echo "EMQX stopped" + ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx install + echo "EMQX installed" + ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx uninstall + echo "EMQX uninstalled" + - uses: actions/upload-artifact@v3 + with: + name: windows + path: _packages/${{ matrix.profile }}/* + retention-days: 7 + - name: Send notification to Slack + uses: slackapi/slack-github-action@v1.23.0 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + with: + payload: | + {"text": "Scheduled build of ${{ matrix.profile }} package for Windows failed: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"} diff --git a/.github/workflows/build_slim_packages.yaml b/.github/workflows/build_slim_packages.yaml index a955b4a9b..b7ba78ef4 100644 --- a/.github/workflows/build_slim_packages.yaml +++ b/.github/workflows/build_slim_packages.yaml @@ -5,54 +5,73 @@ concurrency: cancel-in-progress: true on: - push: - branches: - - master - - release-51 - pull_request: - # GitHub pull_request action is by default triggered when - # opened reopened or synchronize, - # we add labeled and unlabeled to the list because - # the mac job dpends on the PR having a 'Mac' label - types: - - labeled - - unlabeled - - opened - - reopened - - synchronize + workflow_call: + inputs: + runner: + required: true + type: string + builder: + required: true + type: string + builder_vsn: + required: true + type: string + otp_vsn: + required: true + type: string + elixir_vsn: + required: true + type: string + workflow_dispatch: + inputs: + ref: + required: false + runner: + required: false + type: string + default: 'ubuntu-22.04' + builder: + required: false + type: string + default: 'ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04' + builder_vsn: + required: false + type: string + default: '5.1-3' + otp_vsn: + required: false + type: string + default: '25.3.2-1' + elixir_vsn: + required: false + type: string + default: '1.14.5' jobs: linux: - runs-on: aws-amd64 + runs-on: ${{ inputs.runner }} + env: + EMQX_NAME: ${{ matrix.profile[0] }} strategy: fail-fast: false matrix: profile: - - ["emqx", "25.3.2-1", "el7", "erlang"] - - ["emqx", "25.3.2-1", "ubuntu22.04", "elixir"] - - ["emqx-enterprise", "25.3.2-1", "amzn2023", "erlang"] + - ["emqx", "25.3.2-1", "ubuntu20.04", "elixir"] - ["emqx-enterprise", "25.3.2-1", "ubuntu20.04", "erlang"] - builder: - - 5.1-3 - elixir: - - '1.14.5' - container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}" + container: "ghcr.io/emqx/emqx-builder/${{ inputs.builder_vsn }}:${{ inputs.elixir_vsn }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}" steps: - uses: AutoModality/action-clean@v1 - uses: actions/checkout@v3 with: fetch-depth: 0 - - name: prepare - run: | - echo "EMQX_NAME=${{ matrix.profile[0] }}" >> $GITHUB_ENV - echo "CODE_PATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV - name: Work around https://github.com/actions/checkout/issues/766 run: | git config --global --add safe.directory "$GITHUB_WORKSPACE" + echo "CODE_PATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV - name: build and test tgz package if: matrix.profile[3] == 'erlang' run: | @@ -77,58 +96,14 @@ jobs: with: name: "${{ matrix.profile[0] }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}" path: _packages/${{ matrix.profile[0] }}/* + retention-days: 7 - uses: actions/upload-artifact@v3 with: name: "${{ matrix.profile[0] }}_schema_dump" path: | scripts/spellcheck _build/docgen/${{ matrix.profile[0] }}/schema-en.json - - windows: - runs-on: windows-2019 - strategy: - fail-fast: false - matrix: - profile: - - emqx - otp: - - 25.3.2 - steps: - - uses: actions/checkout@v3 - - uses: ilammy/msvc-dev-cmd@v1.12.0 - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: ${{ matrix.otp }} - - name: build - env: - PYTHON: python - DIAGNOSTIC: 1 - run: | - # ensure crypto app (openssl) - erl -eval "erlang:display(crypto:info_lib())" -s init stop - make ${{ matrix.profile }}-tgz - - name: run emqx - timeout-minutes: 5 - run: | - ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx start - Start-Sleep -s 10 - $pingOutput = ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx ping - if ($pingOutput = 'pong') { - echo "EMQX started OK" - } else { - echo "Failed to ping EMQX $pingOutput" - Exit 1 - } - ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx stop - echo "EMQX stopped" - ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx install - echo "EMQX installed" - ./_build/${{ matrix.profile }}/rel/emqx/bin/emqx uninstall - echo "EMQX uninstalled" - - uses: actions/upload-artifact@v3 - with: - name: windows - path: _packages/${{ matrix.profile }}/* + retention-days: 7 mac: strategy: @@ -136,20 +111,18 @@ jobs: matrix: profile: - emqx - - emqx-enterprise otp: - - 25.3.2-1 + - ${{ inputs.otp_vsn }} os: - macos-11 - macos-12-arm64 runs-on: ${{ matrix.os }} + env: + EMQX_NAME: ${{ matrix.profile }} steps: - uses: actions/checkout@v3 - - name: prepare - run: | - echo "EMQX_NAME=${{ matrix.profile }}" >> $GITHUB_ENV - uses: ./.github/actions/package-macos with: profile: ${{ matrix.profile }} @@ -163,84 +136,4 @@ jobs: with: name: ${{ matrix.os }} path: _packages/**/* - - docker: - runs-on: aws-amd64 - - strategy: - fail-fast: false - matrix: - profile: - - ["emqx", "5.0.16"] - - ["emqx-enterprise", "5.0.1"] - - steps: - - uses: actions/checkout@v3 - - name: prepare - run: | - EMQX_NAME=${{ matrix.profile[0] }} - PKG_VSN=${PKG_VSN:-$(./pkg-vsn.sh $EMQX_NAME)} - EMQX_IMAGE_TAG=emqx/$EMQX_NAME:test - EMQX_IMAGE_OLD_VERSION_TAG=emqx/$EMQX_NAME:${{ matrix.profile[1] }} - echo "EMQX_NAME=$EMQX_NAME" >> $GITHUB_ENV - echo "PKG_VSN=$PKG_VSN" >> $GITHUB_ENV - echo "EMQX_IMAGE_TAG=$EMQX_IMAGE_TAG" >> $GITHUB_ENV - echo "EMQX_IMAGE_OLD_VERSION_TAG=$EMQX_IMAGE_OLD_VERSION_TAG" >> $GITHUB_ENV - - uses: docker/setup-buildx-action@v2 - - name: build and export to Docker - uses: docker/build-push-action@v4 - with: - context: . - file: ./deploy/docker/Dockerfile - load: true - tags: ${{ env.EMQX_IMAGE_TAG }} - build-args: | - EMQX_NAME=${{ env.EMQX_NAME }} - - name: smoke test - run: | - CID=$(docker run -d --rm -P $EMQX_IMAGE_TAG) - HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID) - ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT - docker stop $CID - - name: dashboard tests - working-directory: ./scripts/ui-tests - run: | - set -eu - docker compose up --abort-on-container-exit --exit-code-from selenium - - name: test two nodes cluster with proto_dist=inet_tls in docker - run: | - ./scripts/test/start-two-nodes-in-docker.sh -P $EMQX_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG - HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' haproxy) - ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT - # cleanup - ./scripts/test/start-two-nodes-in-docker.sh -c - - name: export docker image - run: | - docker save $EMQX_IMAGE_TAG | gzip > $EMQX_NAME-$PKG_VSN.tar.gz - - uses: actions/upload-artifact@v3 - with: - name: "${{ matrix.profile[0] }}-docker" - path: "${{ env.EMQX_NAME }}-${{ env.PKG_VSN }}.tar.gz" - - name: cleanup - if: always() - working-directory: ./scripts/ui-tests - run: | - docker compose rm -fs - - spellcheck: - needs: linux - strategy: - matrix: - profile: - - emqx - - emqx-enterprise - runs-on: aws-amd64 - steps: - - uses: actions/download-artifact@v3 - name: Download schema dump - with: - name: "${{ matrix.profile }}_schema_dump" - path: /tmp/ - - name: Run spellcheck - run: | - bash /tmp/scripts/spellcheck/spellcheck.sh /tmp/_build/docgen/${{ matrix.profile }}/schema-en.json + retention-days: 7 diff --git a/.github/workflows/check_deps_integrity.yaml b/.github/workflows/check_deps_integrity.yaml index 4a079c570..8ece0746b 100644 --- a/.github/workflows/check_deps_integrity.yaml +++ b/.github/workflows/check_deps_integrity.yaml @@ -1,14 +1,46 @@ -name: Check Rebar Dependencies +name: Check integrity of rebar and mix dependencies on: - pull_request: + workflow_call: + inputs: + runner: + required: true + type: string + builder: + required: true + type: string jobs: check_deps_integrity: - runs-on: ubuntu-22.04 - container: ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04 - + runs-on: ${{ inputs.runner }} + container: ${{ inputs.builder }} steps: - uses: actions/checkout@v3 - - name: Run check-deps-integrity.escript - run: ./scripts/check-deps-integrity.escript + - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - run: make ensure-rebar3 + - run: ./scripts/check-deps-integrity.escript + - name: Setup mix + env: + MIX_ENV: emqx-enterprise + PROFILE: emqx-enterprise + run: | + mix local.hex --force + mix local.rebar --force + mix deps.get + - run: ./scripts/check-elixir-deps-discrepancies.exs + env: + MIX_ENV: emqx-enterprise + PROFILE: emqx-enterprise + - run: ./scripts/check-elixir-applications.exs + env: + MIX_ENV: emqx-enterprise + PROFILE: emqx-enterprise + - name: Upload produced lock files + uses: actions/upload-artifact@v3 + if: failure() + with: + name: produced_lock_files + path: | + mix.lock + rebar.lock + retention-days: 1 diff --git a/.github/workflows/code_style_check.yaml b/.github/workflows/code_style_check.yaml deleted file mode 100644 index ff1043b81..000000000 --- a/.github/workflows/code_style_check.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Code style check - -on: [pull_request] - -jobs: - code_style_check: - runs-on: ubuntu-22.04 - container: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 1000 - - name: Work around https://github.com/actions/checkout/issues/766 - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - - name: Check line-break at EOF - run: | - ./scripts/check-nl-at-eof.sh - - name: Check Elixir code formatting - run: | - mix format --check-formatted - - - name: Check Erlang code formatting - run: | - ./scripts/check-format.sh - - - name: Run elvis check - run: | - ./scripts/elvis-check.sh $GITHUB_BASE_REF diff --git a/.github/workflows/elixir_apps_check.yaml b/.github/workflows/elixir_apps_check.yaml deleted file mode 100644 index 31f70690e..000000000 --- a/.github/workflows/elixir_apps_check.yaml +++ /dev/null @@ -1,45 +0,0 @@ ---- - -name: Check Elixir Release Applications - -on: - pull_request: - -jobs: - elixir_apps_check: - runs-on: ubuntu-22.04 - # just use the latest builder - container: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" - - strategy: - fail-fast: false - matrix: - profile: - - emqx - - emqx-enterprise - - emqx-pkg - - emqx-enterprise-pkg - - steps: - - name: fix_git_permission - run: git config --global --add safe.directory '/__w/emqx/emqx' - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: ensure rebar - run: ./scripts/ensure-rebar3.sh - - name: Work around https://github.com/actions/checkout/issues/766 - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - - name: check applications - run: ./scripts/check-elixir-applications.exs - env: - MIX_ENV: ${{ matrix.profile }} - PROFILE: ${{ matrix.profile }} -# - name: check applications started with emqx_machine -# run: ./scripts/check-elixir-emqx-machine-boot-discrepancies.exs -# env: -# MIX_ENV: ${{ matrix.profile }} - -... diff --git a/.github/workflows/elixir_deps_check.yaml b/.github/workflows/elixir_deps_check.yaml deleted file mode 100644 index a7e086bb1..000000000 --- a/.github/workflows/elixir_deps_check.yaml +++ /dev/null @@ -1,49 +0,0 @@ ---- - -name: Elixir Dependency Version Check - -on: - pull_request: - -jobs: - elixir_deps_check: - runs-on: ubuntu-22.04 - container: ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04 - - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: ensure rebar - run: ./scripts/ensure-rebar3.sh - - name: Work around https://github.com/actions/checkout/issues/766 - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - - name: setup mix - run: | - mix local.hex --force - mix local.rebar --force - mix deps.get - # we check only enterprise because `rebar3 tree`, even if an - # enterprise app is excluded from `project_app_dirs` in - # `rebar.config.erl`, will still list dependencies from it. - # Since the enterprise profile is a superset of the - # community one and thus more complete, we use the former. - env: - MIX_ENV: emqx-enterprise - PROFILE: emqx-enterprise - - name: check elixir deps - run: ./scripts/check-elixir-deps-discrepancies.exs - env: - MIX_ENV: emqx-enterprise - PROFILE: emqx-enterprise - - name: produced lock files - uses: actions/upload-artifact@v3 - if: failure() - with: - name: produced_lock_files - path: | - mix.lock - rebar.lock - retention-days: 1 - -... diff --git a/.github/workflows/elixir_release.yml b/.github/workflows/elixir_release.yml deleted file mode 100644 index 73807bfa0..000000000 --- a/.github/workflows/elixir_release.yml +++ /dev/null @@ -1,41 +0,0 @@ -# FIXME: temporary workflow for testing; remove later -name: Elixir Build (temporary) - -concurrency: - group: mix-${{ github.event_name }}-${{ github.ref }} - cancel-in-progress: true - -on: - pull_request: - workflow_dispatch: - -jobs: - elixir_release_build: - runs-on: ubuntu-22.04 - strategy: - matrix: - profile: - - emqx - - emqx-enterprise - container: ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04 - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: install tools - run: apt update && apt install netcat-openbsd - - name: Work around https://github.com/actions/checkout/issues/766 - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - - name: elixir release - run: make ${{ matrix.profile }}-elixir - - name: start release - run: | - cd _build/${{ matrix.profile }}/rel/emqx - bin/emqx start - - name: check if started - run: | - sleep 10 - nc -zv localhost 1883 - cd _build/${{ matrix.profile }}/rel/emqx - bin/emqx ping - bin/emqx ctl status diff --git a/.github/workflows/run_conf_tests.yaml b/.github/workflows/run_conf_tests.yaml index 80fe53133..cf696e0c6 100644 --- a/.github/workflows/run_conf_tests.yaml +++ b/.github/workflows/run_conf_tests.yaml @@ -5,49 +5,45 @@ concurrency: cancel-in-progress: true on: - push: - branches: - - master - - 'ci/**' - tags: - - v* - - e* - pull_request: - -env: - IS_CI: "yes" + workflow_call: + inputs: + runner: + required: true + type: string + builder: + required: true + type: string jobs: run_conf_tests: - runs-on: ubuntu-22.04 + runs-on: ${{ inputs.runner }} + container: ${{ inputs.builder }} + env: + PROFILE: ${{ matrix.profile }} strategy: fail-fast: false matrix: profile: - emqx - emqx-enterprise - container: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" steps: - uses: AutoModality/action-clean@v1 - - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 with: - path: source - - name: build_package - working-directory: source + name: ${{ matrix.profile }} + - name: extract artifact run: | - make ${{ matrix.profile }} - - name: run_tests - working-directory: source - env: - PROFILE: ${{ matrix.profile }} - run: | - ./scripts/conf-test/run.sh - - name: print_erlang_log + unzip -o -q ${{ matrix.profile }}.zip + git config --global --add safe.directory "$GITHUB_WORKSPACE" + - run: ./scripts/test/check-example-configs.sh + - run: ./scripts/conf-test/run.sh + - name: print erlang log if: failure() run: | - cat source/_build/${{ matrix.profile }}/rel/emqx/logs/erlang.log.* + cat _build/${{ matrix.profile }}/rel/emqx/logs/erlang.log.* - uses: actions/upload-artifact@v3 if: failure() with: name: logs-${{ matrix.profile }} - path: source/_build/${{ matrix.profile }}/rel/emqx/logs + path: _build/${{ matrix.profile }}/rel/emqx/logs + diff --git a/.github/workflows/run_docker_tests.yaml b/.github/workflows/run_docker_tests.yaml new file mode 100644 index 000000000..4188378d0 --- /dev/null +++ b/.github/workflows/run_docker_tests.yaml @@ -0,0 +1,118 @@ +name: Docker image tests + +concurrency: + group: docker-tests-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_call: + inputs: + runner: + required: true + type: string + version-emqx: + required: true + type: string + version-emqx-enterprise: + required: true + type: string + +jobs: + basic-tests: + runs-on: ${{ inputs.runner }} + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + profile: + - ["emqx", "emqx/emqx:5.0.16"] + - ["emqx-enterprise", "emqx/emqx-enterprise:5.0.1"] + + env: + EMQX_NAME: ${{ matrix.profile[0] }} + PKG_VSN: ${{ matrix.profile[0] == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }} + EMQX_IMAGE_OLD_VERSION_TAG: ${{ matrix.profile[1] }} + + steps: + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 + with: + name: ${{ env.EMQX_NAME }}-docker + path: /tmp + - name: load docker image + run: | + EMQX_IMAGE_TAG=$(docker load < /tmp/${EMQX_NAME}-docker-${PKG_VSN}.tar.gz 2>/dev/null | sed 's/Loaded image: //g') + echo "EMQX_IMAGE_TAG=$EMQX_IMAGE_TAG" >> $GITHUB_ENV + - name: dashboard tests + working-directory: ./scripts/ui-tests + run: | + set -eu + docker compose up --abort-on-container-exit --exit-code-from selenium + - name: test two nodes cluster with proto_dist=inet_tls in docker + run: | + ./scripts/test/start-two-nodes-in-docker.sh -P $EMQX_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG + HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' haproxy) + ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT + ./scripts/test/start-two-nodes-in-docker.sh -c + - name: cleanup + if: always() + working-directory: ./scripts/ui-tests + run: | + docker compose rm -fs + + paho-mqtt-testing: + runs-on: ${{ inputs.runner }} + defaults: + run: + shell: bash + env: + EMQX_NAME: ${{ matrix.profile }} + PKG_VSN: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }} + _EMQX_TEST_DB_BACKEND: ${{ matrix.cluster_db_backend }} + + strategy: + fail-fast: false + matrix: + profile: + - emqx + - emqx-enterprise + - emqx-elixir + cluster_db_backend: + - mnesia + - rlog + steps: + - uses: AutoModality/action-clean@v1 + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 + with: + name: ${{ env.EMQX_NAME }}-docker + path: /tmp + - name: load docker image + run: | + EMQX_IMAGE_TAG=$(docker load < /tmp/${EMQX_NAME}-docker-${PKG_VSN}.tar.gz 2>/dev/null | sed 's/Loaded image: //g') + echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_IMAGE_TAG" >> $GITHUB_ENV + - name: run emqx + timeout-minutes: 5 + run: | + ./.ci/docker-compose-file/scripts/run-emqx.sh $_EMQX_DOCKER_IMAGE_TAG $_EMQX_TEST_DB_BACKEND + - name: make paho tests + run: | + if ! docker exec -i python /scripts/pytest.sh "$_EMQX_TEST_DB_BACKEND"; then + echo "DUMP_CONTAINER_LOGS_BGN" + echo "============== haproxy ==============" + docker logs haproxy + echo "============== node1 ==============" + docker logs node1.emqx.io + echo "============== node2 ==============" + docker logs node2.emqx.io + echo "DUMP_CONTAINER_LOGS_END" + exit 1 + fi + # node_dump requires netstat, which is not available in the container + # simple smoke test for node_dump + # - name: test node_dump + # run: | + # docker exec -u root node1.emqx.io apt update && apt install -y net-tools + # docker exec node1.emqx.io node_dump diff --git a/.github/workflows/run_emqx_app_tests.yaml b/.github/workflows/run_emqx_app_tests.yaml deleted file mode 100644 index 40a630e76..000000000 --- a/.github/workflows/run_emqx_app_tests.yaml +++ /dev/null @@ -1,80 +0,0 @@ -name: Check emqx app standalone - -## apps/emqx can be used as a rebar/mix dependency -## in other project, so we need to make sure apps/emqx -## as an Erlang/Elixir app works standalone - -on: - pull_request: - -jobs: - run_emqx_app_tests: - strategy: - matrix: - builder: - - 5.1-3 - otp: - - 25.3.2-1 - # no need to use more than 1 version of Elixir, since tests - # run using only Erlang code. This is needed just to specify - # the base image. - elixir: - - 1.14.5 - os: - - ubuntu22.04 - arch: - - amd64 - runs-on: - - aws-amd64 - - ubuntu-22.04 - use-self-hosted: - - ${{ github.repository_owner == 'emqx' }} - exclude: - - runs-on: ubuntu-22.04 - use-self-hosted: true - - runs-on: aws-amd64 - use-self-hosted: false - - runs-on: ${{ matrix.runs-on }} - container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir}}-${{ matrix.otp }}-${{ matrix.os }}" - - defaults: - run: - shell: bash - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: run - run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - echo "git diff base: $GITHUB_BASE_REF" - if [[ "$GITHUB_BASE_REF" =~ [0-9a-f]{8,40} ]]; then - # base is a commit sha1 - compare_base="$GITHUB_BASE_REF" - else - repo="${GITHUB_REPOSITORY}" - git remote -v - remote="$(git remote -v | grep -E "github\.com(:|/)$repo((\.git)|(\s))" | grep fetch | awk '{print $1}')" - git fetch "$remote" "$GITHUB_BASE_REF" - compare_base="$remote/$GITHUB_BASE_REF" - fi - changed_files="$(git diff --name-only ${compare_base} HEAD apps/emqx)" - if [ "$changed_files" = '' ]; then - echo "nothing changed in apps/emqx, ignored." - exit 0 - fi - make ensure-rebar3 - cp rebar3 apps/emqx/ - cd apps/emqx - ./rebar3 xref - ./rebar3 dialyzer - ./rebar3 eunit -v - ./rebar3 ct --name 'test@127.0.0.1' -v --readable=true - ./rebar3 proper -d test/props - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: logs-${{ matrix.runs-on }} - path: apps/emqx/_build/test/logs diff --git a/.github/workflows/run_fvt_tests.yaml b/.github/workflows/run_fvt_tests.yaml deleted file mode 100644 index 0bcdee93a..000000000 --- a/.github/workflows/run_fvt_tests.yaml +++ /dev/null @@ -1,255 +0,0 @@ -name: Functional Verification Tests - -concurrency: - group: fvt-${{ github.event_name }}-${{ github.ref }} - cancel-in-progress: true - -on: - push: - branches: - - master - - 'ci/**' - tags: - - v* - pull_request: - -jobs: - prepare: - runs-on: ubuntu-22.04 - # prepare source with any OTP version, no need for a matrix - container: ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-debian11 - - steps: - - uses: actions/checkout@v3 - with: - path: source - fetch-depth: 0 - - name: get deps - run: | - make -C source deps-all - zip -ryq source.zip source/* source/.[^.]* - - uses: actions/upload-artifact@v3 - with: - name: source - path: source.zip - - docker_test: - runs-on: ubuntu-22.04 - needs: prepare - - strategy: - fail-fast: false - matrix: - profile: - - emqx - - emqx-enterprise - - emqx-elixir - cluster_db_backend: - - mnesia - - rlog - os: - - ["debian11", "debian:11-slim"] - builder: - - 5.1-3 - otp: - - 25.3.2-1 - elixir: - - 1.14.5 - arch: - - amd64 - steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - - uses: actions/download-artifact@v3 - with: - name: source - path: . - - name: unzip source code - run: unzip -q source.zip - - - name: make docker image - working-directory: source - env: - EMQX_BUILDER: ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-${{ matrix.os[0] }} - EMQX_RUNNER: ${{ matrix.os[1] }} - run: | - make ${{ matrix.profile }}-docker - - name: run emqx - timeout-minutes: 5 - working-directory: source - run: | - set -x - if [[ "${{ matrix.profile }}" = *-elixir ]] - then - export IS_ELIXIR=yes - PROFILE=$(echo ${{ matrix.profile }} | sed -e "s/-elixir//g") - IMAGE=emqx/$PROFILE:$(./pkg-vsn.sh ${{ matrix.profile }})-elixir - else - IMAGE=emqx/${{ matrix.profile }}:$(./pkg-vsn.sh ${{ matrix.profile }}) - fi - ./.ci/docker-compose-file/scripts/run-emqx.sh $IMAGE ${{ matrix.cluster_db_backend }} - - name: make paho tests - run: | - if ! docker exec -i python /scripts/pytest.sh "${{ matrix.cluster_db_backend }}"; then - echo "DUMP_CONTAINER_LOGS_BGN" - echo "============== haproxy ==============" - docker logs haproxy - echo "============== node1 ==============" - docker logs node1.emqx.io - echo "============== node2 ==============" - docker logs node2.emqx.io - echo "DUMP_CONTAINER_LOGS_END" - exit 1 - fi - # simple smoke test for node_dump - - name: test node_dump - run: | - docker exec node1.emqx.io node_dump - - helm_test: - runs-on: ubuntu-22.04 - needs: prepare - - strategy: - fail-fast: false - matrix: - discovery: - - k8s - - dns - profile: - - emqx - - emqx-enterprise - os: - - ["debian11", "debian:11-slim"] - builder: - - 5.1-3 - otp: - - 25.3.2-1 - elixir: - - 1.14.5 - arch: - - amd64 - # - emqx-enterprise # TODO test enterprise - - steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - - uses: actions/download-artifact@v3 - with: - name: source - path: . - - name: unzip source code - run: unzip -q source.zip - - - name: make docker image - working-directory: source - env: - EMQX_BUILDER: ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-${{ matrix.os[0] }} - EMQX_RUNNER: ${{ matrix.os[1] }} - run: | - make ${{ matrix.profile }}-docker - echo "TARGET=emqx/${{ matrix.profile }}" >> $GITHUB_ENV - echo "EMQX_TAG=$(./pkg-vsn.sh ${{ matrix.profile }})" >> $GITHUB_ENV - - run: minikube start - - run: minikube image load $TARGET:$EMQX_TAG - - name: run emqx on chart - working-directory: source - if: matrix.discovery == 'k8s' - run: | - helm install ${{ matrix.profile }} \ - --set emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY="k8s" \ - --set emqxConfig.EMQX_CLUSTER__K8S__APISERVER="https://kubernetes.default.svc:443" \ - --set emqxConfig.EMQX_CLUSTER__K8S__SERVICE_NAME="${{ matrix.profile }}-headless" \ - --set emqxConfig.EMQX_CLUSTER__K8S__NAMESPACE="default" \ - --set image.repository=$TARGET \ - --set image.pullPolicy=Never \ - --set image.tag=$EMQX_TAG \ - --set emqxAclConfig="" \ - --set emqxConfig.EMQX_MQTT__RETRY_INTERVAL=2s \ - --set emqxConfig.EMQX_MQTT__MAX_TOPIC_ALIAS=10 \ - --set emqxConfig.EMQX_AUTHORIZATION__SOURCES=[] \ - --set emqxConfig.EMQX_AUTHORIZATION__NO_MATCH=allow \ - deploy/charts/${{ matrix.profile }} \ - --debug - - name: run emqx on chart - working-directory: source - if: matrix.discovery == 'dns' - run: | - helm install ${{ matrix.profile }} \ - --set emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY="dns" \ - --set emqxConfig.EMQX_CLUSTER__DNS__RECORD_TYPE="srv" \ - --set emqxConfig.EMQX_CLUSTER__DNS__NAME="${{ matrix.profile }}-headless.default.svc.cluster.local" \ - --set image.repository=$TARGET \ - --set image.pullPolicy=Never \ - --set image.tag=$EMQX_TAG \ - --set emqxAclConfig="" \ - --set emqxConfig.EMQX_MQTT__RETRY_INTERVAL=2s \ - --set emqxConfig.EMQX_MQTT__MAX_TOPIC_ALIAS=10 \ - --set emqxConfig.EMQX_AUTHORIZATION__SOURCES=[] \ - --set emqxConfig.EMQX_AUTHORIZATION__NO_MATCH=allow \ - deploy/charts/${{ matrix.profile }} \ - --debug - - name: waiting emqx started - timeout-minutes: 10 - run: | - while [ "$(kubectl get StatefulSet -l app.kubernetes.io/instance=${{ matrix.profile }} -o jsonpath='{.items[0].status.replicas}')" \ - != "$(kubectl get StatefulSet -l app.kubernetes.io/instance=${{ matrix.profile }} -o jsonpath='{.items[0].status.readyReplicas}')" ]; do - echo "=============================="; - kubectl get pods; - echo "=============================="; - echo "waiting emqx started"; - sleep 10; - done - - name: Get Token - timeout-minutes: 1 - run: | - kubectl port-forward service/${{ matrix.profile }} 18083:18083 > /dev/null & - - while - [ "$(curl --silent -X 'GET' 'http://127.0.0.1:18083/api/v5/status' | tail -n1)" != "emqx is running" ] - do - echo "waiting emqx" - sleep 1 - done - - echo "TOKEN=$(curl --silent -X 'POST' 'http://127.0.0.1:18083/api/v5/login' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"username": "admin","password": "public"}' | jq -r ".token")" >> $GITHUB_ENV - - - name: Check cluster - timeout-minutes: 10 - run: | - while - [ "$(curl --silent -H "Authorization: Bearer $TOKEN" -X GET http://127.0.0.1:18083/api/v5/cluster| jq '.nodes|length')" != "3" ]; - do - echo "waiting ${{ matrix.profile }} cluster scale" - sleep 1 - done - - uses: actions/checkout@v3 - with: - repository: emqx/paho.mqtt.testing - ref: develop-5.0 - path: paho.mqtt.testing - - name: install pytest - run: | - pip install pytest==7.1.2 pytest-retry - echo "$HOME/.local/bin" >> $GITHUB_PATH - - name: run paho test - timeout-minutes: 10 - run: | - port_connected () { - local server="$1" - local port="$2" - echo > /dev/tcp/${server}/${port} 2>/dev/null - } - - kubectl port-forward service/${{ matrix.profile }} 1883:1883 > /dev/null & - - while ! port_connected localhost 1883; do - echo server not listening yet... - sleep 10 - done - - pytest --retries 3 -v paho.mqtt.testing/interoperability/test_client/V5/test_connect.py -k test_basic --host "127.0.0.1" - - if: failure() - run: kubectl logs -l "app.kubernetes.io/instance=${{ matrix.profile }}" -c emqx --tail=1000 diff --git a/.github/workflows/run_gitlint.yaml b/.github/workflows/run_gitlint.yaml deleted file mode 100644 index 52082c56e..000000000 --- a/.github/workflows/run_gitlint.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Run gitlint - -on: [pull_request] - -jobs: - run_gitlint: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Run gitlint - shell: bash - run: | - set -ex - docker run --ulimit nofile=1024 -v $(pwd):/repo -w /repo ghcr.io/emqx/gitlint --commits ${{ github.event.pull_request.base.sha }}..$GITHUB_SHA --config .github/workflows/.gitlint diff --git a/.github/workflows/run_helm_tests.yaml b/.github/workflows/run_helm_tests.yaml new file mode 100644 index 000000000..1106b6057 --- /dev/null +++ b/.github/workflows/run_helm_tests.yaml @@ -0,0 +1,144 @@ +name: Helm tests + +concurrency: + group: helm-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_call: + inputs: + version-emqx: + required: true + type: string + version-emqx-enterprise: + required: true + type: string + +jobs: + helm_test: + runs-on: ubuntu-22.04 + defaults: + run: + shell: bash + env: + EMQX_NAME: ${{ matrix.profile }} + EMQX_TAG: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }} + REPOSITORY: "emqx/${{ matrix.profile }}" + + strategy: + fail-fast: false + matrix: + discovery: + - k8s + - dns + profile: + - emqx + - emqx-enterprise + + steps: + - uses: actions/checkout@v3 + with: + path: source + - uses: actions/download-artifact@v3 + with: + name: "${{ env.EMQX_NAME }}-docker" + path: /tmp + - run: minikube start + - run: | + img="/tmp/${EMQX_NAME}-docker-${EMQX_TAG}.tar.gz" + if stderr=$(minikube image load "${img}" 2>&1 >/dev/null) && test -n "$stderr"; then + echo "${stderr}"; + exit 1; + fi + - name: run emqx on chart (k8s) + if: matrix.discovery == 'k8s' + working-directory: source + run: | + helm install ${EMQX_NAME} \ + --set emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY="k8s" \ + --set emqxConfig.EMQX_CLUSTER__K8S__APISERVER="https://kubernetes.default.svc:443" \ + --set emqxConfig.EMQX_CLUSTER__K8S__SERVICE_NAME="${EMQX_NAME}-headless" \ + --set emqxConfig.EMQX_CLUSTER__K8S__NAMESPACE="default" \ + --set image.repository=$REPOSITORY \ + --set image.pullPolicy=Never \ + --set image.tag=$EMQX_TAG \ + --set emqxAclConfig="" \ + --set emqxConfig.EMQX_MQTT__RETRY_INTERVAL=2s \ + --set emqxConfig.EMQX_MQTT__MAX_TOPIC_ALIAS=10 \ + --set emqxConfig.EMQX_AUTHORIZATION__SOURCES=[] \ + --set emqxConfig.EMQX_AUTHORIZATION__NO_MATCH=allow \ + deploy/charts/${EMQX_NAME} \ + --debug + - name: run emqx on chart (dns) + if: matrix.discovery == 'dns' + working-directory: source + run: | + helm install ${EMQX_NAME} \ + --set emqxConfig.EMQX_CLUSTER__DISCOVERY_STRATEGY="dns" \ + --set emqxConfig.EMQX_CLUSTER__DNS__RECORD_TYPE="srv" \ + --set emqxConfig.EMQX_CLUSTER__DNS__NAME="${EMQX_NAME}-headless.default.svc.cluster.local" \ + --set image.repository=$REPOSITORY \ + --set image.pullPolicy=Never \ + --set image.tag=$EMQX_TAG \ + --set emqxAclConfig="" \ + --set emqxConfig.EMQX_MQTT__RETRY_INTERVAL=2s \ + --set emqxConfig.EMQX_MQTT__MAX_TOPIC_ALIAS=10 \ + --set emqxConfig.EMQX_AUTHORIZATION__SOURCES=[] \ + --set emqxConfig.EMQX_AUTHORIZATION__NO_MATCH=allow \ + deploy/charts/${EMQX_NAME} \ + --debug + - name: waiting emqx started + timeout-minutes: 5 + run: | + while [ "$(kubectl get StatefulSet -l app.kubernetes.io/instance=${EMQX_NAME} -o jsonpath='{.items[0].status.replicas}')" \ + != "$(kubectl get StatefulSet -l app.kubernetes.io/instance=${EMQX_NAME} -o jsonpath='{.items[0].status.readyReplicas}')" ]; do + echo "=============================="; + kubectl get pods; + echo "=============================="; + echo "waiting emqx started"; + sleep 10; + done + - name: Get Token + run: | + kubectl port-forward service/${EMQX_NAME} 18083:18083 > /dev/null & + curl --head -X GET --retry 10 --retry-connrefused --retry-delay 6 http://localhost:18083/status + echo "TOKEN=$(curl --silent -X 'POST' 'http://127.0.0.1:18083/api/v5/login' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"username": "admin","password": "public"}' | jq -r ".token")" >> $GITHUB_ENV + + - name: Check cluster + timeout-minutes: 1 + run: | + while + nodes_length="$(curl --silent -H "Authorization: Bearer $TOKEN" -X GET http://127.0.0.1:18083/api/v5/cluster| jq '.nodes|length')" + [ $nodes_length != "3" ] + do + echo "waiting ${EMQX_NAME} cluster scale. Current live nodes: $nodes_length." + sleep 1 + done + - uses: actions/checkout@v3 + with: + repository: emqx/paho.mqtt.testing + ref: develop-5.0 + path: paho.mqtt.testing + - name: install pytest + run: | + pip install pytest==7.1.2 pytest-retry + echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: run paho test + timeout-minutes: 10 + run: | + port_connected () { + local server="$1" + local port="$2" + echo > /dev/tcp/${server}/${port} 2>/dev/null + } + + kubectl port-forward service/${EMQX_NAME} 1883:1883 > /dev/null & + + while ! port_connected localhost 1883; do + echo server not listening yet... + sleep 10 + done + + pytest --retries 3 -v paho.mqtt.testing/interoperability/test_client/V5/test_connect.py -k test_basic --host "127.0.0.1" + - if: failure() + run: kubectl logs -l "app.kubernetes.io/instance=${EMQX_NAME}" -c emqx --tail=1000 diff --git a/.github/workflows/run_jmeter_tests.yaml b/.github/workflows/run_jmeter_tests.yaml index 04866c7a9..d45b66324 100644 --- a/.github/workflows/run_jmeter_tests.yaml +++ b/.github/workflows/run_jmeter_tests.yaml @@ -1,22 +1,16 @@ name: JMeter integration tests on: - push: - tags: - - "v5.*" - pull_request: - branches: - - "master" + workflow_call: + inputs: + version-emqx: + required: true + type: string jobs: - build_emqx_for_jmeter_tests: + jmeter_artifact: runs-on: ubuntu-22.04 - outputs: - version: ${{ steps.build_docker.outputs.version}} steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - name: Cache Jmeter id: cache-jmeter uses: actions/cache@v3 @@ -42,21 +36,6 @@ jobs: with: name: apache-jmeter.tgz path: /tmp/apache-jmeter.tgz - - uses: actions/checkout@v3 - - name: zip emqx docker image - id: build_docker - if: endsWith(github.repository, 'emqx') - run: | - ## TODO: make profile a matrix dimension - PROFILE='emqx' - make "${PROFILE}-docker" - VSN="$(./pkg-vsn.sh $PROFILE)" - echo "version=${VSN}" >> $GITHUB_OUTPUT - docker save -o emqx.tar emqx/emqx:${VSN} - - uses: actions/upload-artifact@v3 - with: - name: emqx.tar - path: ./emqx.tar advanced_feat: runs-on: ubuntu-22.04 @@ -70,69 +49,28 @@ jobs: - mqtt_topic_rewrite # - mqtt_retainer - needs: build_emqx_for_jmeter_tests + needs: jmeter_artifact steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + - uses: ./.github/actions/prepare-jmeter with: - name: emqx.tar - path: /tmp - - name: load docker image - run: | - docker load < /tmp/emqx.tar + version-emqx: ${{ inputs.version-emqx }} - name: docker compose up timeout-minutes: 5 - env: - _EMQX_DOCKER_IMAGE_TAG: emqx/emqx:${{ needs.build_emqx_for_jmeter_tests.outputs.version }} run: | - docker-compose \ + docker compose \ -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml \ - up -d --build - - name: wait docker compose up - timeout-minutes: 5 - run: | - while [ "$(docker inspect -f '{{ .State.Health.Status}}' node1.emqx.io)" != "healthy" ] || [ "$(docker inspect -f '{{ .State.Health.Status}}' node2.emqx.io)" != "healthy" ]; do - echo "['$(date -u +"%y-%m-%dt%h:%m:%sz")']:waiting emqx"; - sleep 5; - done - while [ $(docker ps -a --filter name=client --filter exited=0 | wc -l) \ - != $(docker ps -a --filter name=client | wc -l) ]; do - sleep 1 - done - docker ps -a + up --wait --build echo HAPROXY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' haproxy) >> $GITHUB_ENV - - uses: actions/checkout@v3 - with: - repository: emqx/emqx-fvt - ref: broker-autotest-v5 - path: scripts - - uses: actions/setup-java@v3 - with: - java-version: '8.0.282' # The JDK version to make available on the path. - java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk - architecture: x64 # (x64 or x86) - defaults to x64 - # https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md - distribution: 'zulu' - - uses: actions/download-artifact@v3 - with: - name: apache-jmeter.tgz - path: /tmp - - name: install jmeter - timeout-minutes: 10 - env: - JMETER_VERSION: 5.4.3 + - name: show logs + if: failure() run: | - cd /tmp && tar -xvf apache-jmeter.tgz - echo "jmeter.save.saveservice.output_format=xml" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - echo "jmeter.save.saveservice.response_data.on_error=true" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/ext/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar https://raw.githubusercontent.com/xmeter-net/mqtt-jmeter/master/Download/v2.0.2/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar - ln -s /tmp/apache-jmeter-$JMETER_VERSION /opt/jmeter + docker compose \ + -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml \ + logs - name: run jmeter run: | - /opt/jmeter/bin/jmeter.sh \ + jmeter/bin/jmeter.sh \ -Jjmeter.save.saveservice.output_format=xml -n \ -t scripts/broker-autotest-suite/${{ matrix.scripts_type }}.jmx \ -Demqx_ip=$HAPROXY_IP \ @@ -152,8 +90,6 @@ jobs: pgsql_authn_authz: runs-on: ubuntu-22.04 - env: - _EMQX_DOCKER_IMAGE_TAG: emqx/emqx:${{ needs.build_emqx_for_jmeter_tests.outputs.version }} strategy: fail-fast: false @@ -168,72 +104,26 @@ jobs: - pgsql_authn - pgsql_authz - needs: build_emqx_for_jmeter_tests + needs: jmeter_artifact steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + - uses: ./.github/actions/prepare-jmeter with: - name: emqx.tar - path: /tmp - - name: load docker image - run: | - docker load < /tmp/emqx.tar + version-emqx: ${{ inputs.version-emqx }} - name: docker compose up timeout-minutes: 5 env: PGSQL_TAG: ${{ matrix.pgsql_tag }} run: | - docker-compose \ + docker compose \ -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml \ -f .ci/docker-compose-file/docker-compose-pgsql-tls.yaml \ - up -d --build - - name: wait docker compose up - timeout-minutes: 5 - run: | - while [ "$(docker inspect -f '{{ .State.Health.Status}}' node1.emqx.io)" != "healthy" ] || [ "$(docker inspect -f '{{ .State.Health.Status}}' node2.emqx.io)" != "healthy" ]; do - echo "['$(date -u +"%y-%m-%dt%h:%m:%sz")']:waiting emqx"; - sleep 5; - done - while [ $(docker ps -a --filter name=client --filter exited=0 | wc -l) \ - != $(docker ps -a --filter name=client | wc -l) ]; do - sleep 1 - done - docker ps -a + up --wait --build echo HAPROXY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' haproxy) >> $GITHUB_ENV echo PGSQL_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' pgsql-tls) >> $GITHUB_ENV - - uses: actions/checkout@v3 - with: - repository: emqx/emqx-fvt - ref: broker-autotest-v5 - path: scripts - - uses: actions/setup-java@v3 - with: - java-version: '8.0.282' # The JDK version to make available on the path. - java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk - architecture: x64 # (x64 or x86) - defaults to x64 - # https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md - distribution: 'zulu' - - uses: actions/download-artifact@v3 - with: - name: apache-jmeter.tgz - path: /tmp - - name: install jmeter - timeout-minutes: 10 - env: - JMETER_VERSION: 5.4.3 - run: | - cd /tmp && tar -xvf apache-jmeter.tgz - echo "jmeter.save.saveservice.output_format=xml" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - echo "jmeter.save.saveservice.response_data.on_error=true" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/ext/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar https://raw.githubusercontent.com/xmeter-net/mqtt-jmeter/master/Download/v2.0.2/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/postgresql-42.2.18.jar https://repo1.maven.org/maven2/org/postgresql/postgresql/42.2.18/postgresql-42.2.18.jar - ln -s /tmp/apache-jmeter-$JMETER_VERSION /opt/jmeter - name: run jmeter run: | - /opt/jmeter/bin/jmeter.sh \ + jmeter/bin/jmeter.sh \ -Jjmeter.save.saveservice.output_format=xml -n \ -t scripts/broker-autotest-suite/${{ matrix.scripts_type }}.jmx \ -Demqx_ip=$HAPROXY_IP \ @@ -257,7 +147,7 @@ jobs: - name: dump docker compose logs if: failure() run: | - docker-compose -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml logs --no-color > ./jmeter_logs/emqx.log + docker compose -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml logs --no-color > ./jmeter_logs/emqx.log - uses: actions/upload-artifact@v3 if: always() with: @@ -277,73 +167,26 @@ jobs: - mysql_authn - mysql_authz - needs: build_emqx_for_jmeter_tests + needs: jmeter_artifact steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + - uses: ./.github/actions/prepare-jmeter with: - name: emqx.tar - path: /tmp - - name: load docker image - run: | - docker load < /tmp/emqx.tar + version-emqx: ${{ inputs.version-emqx }} - name: docker compose up timeout-minutes: 5 env: - _EMQX_DOCKER_IMAGE_TAG: emqx/emqx:${{ needs.build_emqx_for_jmeter_tests.outputs.version }} PGSQL_TAG: ${{ matrix.mysql_tag }} run: | - docker-compose \ + docker compose \ -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml \ -f .ci/docker-compose-file/docker-compose-mysql-tls.yaml \ - up -d --build - - name: wait docker compose up - timeout-minutes: 5 - run: | - while [ "$(docker inspect -f '{{ .State.Health.Status}}' node1.emqx.io)" != "healthy" ] || [ "$(docker inspect -f '{{ .State.Health.Status}}' node2.emqx.io)" != "healthy" ]; do - echo "['$(date -u +"%y-%m-%dt%h:%m:%sz")']:waiting emqx"; - sleep 5; - done - while [ $(docker ps -a --filter name=client --filter exited=0 | wc -l) \ - != $(docker ps -a --filter name=client | wc -l) ]; do - sleep 1 - done - docker ps -a + up --wait --build echo HAPROXY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' haproxy) >> $GITHUB_ENV echo MYSQL_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mysql-tls) >> $GITHUB_ENV - - uses: actions/checkout@v3 - with: - repository: emqx/emqx-fvt - ref: broker-autotest-v5 - path: scripts - - uses: actions/setup-java@v3 - with: - java-version: '8.0.282' # The JDK version to make available on the path. - java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk - architecture: x64 # (x64 or x86) - defaults to x64 - # https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md - distribution: 'zulu' - - uses: actions/download-artifact@v3 - with: - name: apache-jmeter.tgz - path: /tmp - - name: install jmeter - timeout-minutes: 10 - env: - JMETER_VERSION: 5.4.3 - run: | - cd /tmp && tar -xvf apache-jmeter.tgz - echo "jmeter.save.saveservice.output_format=xml" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - echo "jmeter.save.saveservice.response_data.on_error=true" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/ext/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar https://raw.githubusercontent.com/xmeter-net/mqtt-jmeter/master/Download/v2.0.2/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/mysql-connector-java-8.0.16.jar https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar - ln -s /tmp/apache-jmeter-$JMETER_VERSION /opt/jmeter - name: run jmeter run: | - /opt/jmeter/bin/jmeter.sh \ + jmeter/bin/jmeter.sh \ -Jjmeter.save.saveservice.output_format=xml -n \ -t scripts/broker-autotest-suite/${{ matrix.scripts_type }}.jmx \ -Demqx_ip=$HAPROXY_IP \ @@ -379,45 +222,19 @@ jobs: scripts_type: - jwt_authn - needs: build_emqx_for_jmeter_tests + needs: jmeter_artifact steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + - uses: ./.github/actions/prepare-jmeter with: - name: emqx.tar - path: /tmp - - name: load docker image - run: | - docker load < /tmp/emqx.tar + version-emqx: ${{ inputs.version-emqx }} - name: docker compose up timeout-minutes: 5 - env: - _EMQX_DOCKER_IMAGE_TAG: emqx/emqx:${{ needs.build_emqx_for_jmeter_tests.outputs.version }} run: | - docker-compose \ + docker compose \ -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml \ - up -d --build - - name: wait docker compose up - timeout-minutes: 5 - run: | - while [ "$(docker inspect -f '{{ .State.Health.Status}}' node1.emqx.io)" != "healthy" ] || [ "$(docker inspect -f '{{ .State.Health.Status}}' node2.emqx.io)" != "healthy" ]; do - echo "['$(date -u +"%y-%m-%dt%h:%m:%sz")']:waiting emqx"; - sleep 5; - done - while [ $(docker ps -a --filter name=client --filter exited=0 | wc -l) \ - != $(docker ps -a --filter name=client | wc -l) ]; do - sleep 1 - done - docker ps -a + up --wait --build echo HAPROXY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' haproxy) >> $GITHUB_ENV - - uses: actions/checkout@v3 - with: - repository: emqx/emqx-fvt - ref: broker-autotest-v5 - path: scripts - name: run jwks_server timeout-minutes: 10 run: | @@ -426,30 +243,9 @@ jobs: cd target docker run --name jwks_server --network emqx_bridge --ip 172.100.239.88 -d -v $(pwd)/jwkserver-0.0.1.jar:/jwks_server/jwkserver-0.0.1.jar --workdir /jwks_server openjdk:8-jdk bash \ -c "java -jar jwkserver-0.0.1.jar" - - uses: actions/setup-java@v3 - with: - java-version: '8.0.282' # The JDK version to make available on the path. - java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk - architecture: x64 # (x64 or x86) - defaults to x64 - # https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md - distribution: 'zulu' - - uses: actions/download-artifact@v3 - with: - name: apache-jmeter.tgz - path: /tmp - - name: install jmeter - timeout-minutes: 10 - env: - JMETER_VERSION: 5.4.3 - run: | - cd /tmp && tar -xvf apache-jmeter.tgz - echo "jmeter.save.saveservice.output_format=xml" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - echo "jmeter.save.saveservice.response_data.on_error=true" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/ext/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar https://raw.githubusercontent.com/xmeter-net/mqtt-jmeter/master/Download/v2.0.2/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar - ln -s /tmp/apache-jmeter-$JMETER_VERSION /opt/jmeter - name: run jmeter run: | - /opt/jmeter/bin/jmeter.sh \ + jmeter/bin/jmeter.sh \ -Jjmeter.save.saveservice.output_format=xml -n \ -t scripts/broker-autotest-suite/${{ matrix.scripts_type }}.jmx \ -Demqx_ip=$HAPROXY_IP \ @@ -478,79 +274,30 @@ jobs: - built_in_database_authn - built_in_database_authz - needs: build_emqx_for_jmeter_tests + needs: jmeter_artifact steps: - - uses: erlef/setup-beam@v1.15.4 - with: - otp-version: 25.3.2 - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + - uses: ./.github/actions/prepare-jmeter with: - name: emqx.tar - path: /tmp - - name: load docker image - run: | - docker load < /tmp/emqx.tar + version-emqx: ${{ inputs.version-emqx }} - name: docker compose up timeout-minutes: 5 - env: - _EMQX_DOCKER_IMAGE_TAG: emqx/emqx:${{ needs.build_emqx_for_jmeter_tests.outputs.version }} - PGSQL_TAG: ${{ matrix.mysql_tag }} run: | - docker-compose \ + docker compose \ -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml \ - up -d --build - - name: wait docker compose up - timeout-minutes: 5 - run: | - while [ "$(docker inspect -f '{{ .State.Health.Status}}' node1.emqx.io)" != "healthy" ] || [ "$(docker inspect -f '{{ .State.Health.Status}}' node2.emqx.io)" != "healthy" ]; do - echo "['$(date -u +"%y-%m-%dt%h:%m:%sz")']:waiting emqx"; - sleep 5; - done - while [ $(docker ps -a --filter name=client --filter exited=0 | wc -l) \ - != $(docker ps -a --filter name=client | wc -l) ]; do - sleep 1 - done - docker ps -a + up --wait --build echo HAPROXY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' haproxy) >> $GITHUB_ENV - - uses: actions/checkout@v3 - with: - repository: emqx/emqx-fvt - ref: broker-autotest-v5 - path: scripts - - uses: actions/setup-java@v3 - with: - java-version: '8.0.282' # The JDK version to make available on the path. - java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk - architecture: x64 # (x64 or x86) - defaults to x64 - # https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md - distribution: 'zulu' - - uses: actions/download-artifact@v3 - with: - name: apache-jmeter.tgz - path: /tmp - - name: install jmeter - timeout-minutes: 10 - env: - JMETER_VERSION: 5.4.3 - run: | - cd /tmp && tar -xvf apache-jmeter.tgz - echo "jmeter.save.saveservice.output_format=xml" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - echo "jmeter.save.saveservice.response_data.on_error=true" >> /tmp/apache-jmeter-$JMETER_VERSION/user.properties - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/ext/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar https://raw.githubusercontent.com/xmeter-net/mqtt-jmeter/master/Download/v2.0.2/mqtt-xmeter-fuse-2.0.2-jar-with-dependencies.jar - wget --no-verbose -O /tmp/apache-jmeter-$JMETER_VERSION/lib/mysql-connector-java-8.0.16.jar https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar - ln -s /tmp/apache-jmeter-$JMETER_VERSION /opt/jmeter - name: run jmeter run: | - /opt/jmeter/bin/jmeter.sh \ + jmeter/bin/jmeter.sh \ -Jjmeter.save.saveservice.output_format=xml -n \ -t scripts/broker-autotest-suite/${{ matrix.scripts_type }}.jmx \ -Demqx_ip=$HAPROXY_IP \ - -l jmeter_logs/${{ matrix.scripts_type }}_${{ matrix.mysql_tag }}.jtl \ - -j jmeter_logs/logs/${{ matrix.scripts_type }}_${{ matrix.mysql_tag }}.log + -l jmeter_logs/${{ matrix.scripts_type }}.jtl \ + -j jmeter_logs/logs/${{ matrix.scripts_type }}.log - name: check logs run: | - if cat jmeter_logs/${{ matrix.scripts_type }}_${{ matrix.mysql_tag }}.jtl | grep -e 'true' > /dev/null 2>&1; then + if cat jmeter_logs/${{ matrix.scripts_type }}.jtl | grep -e 'true' > /dev/null 2>&1; then echo "check logs failed" exit 1 fi @@ -559,11 +306,3 @@ jobs: with: name: jmeter_logs path: ./jmeter_logs - - delete-artifact: - runs-on: ubuntu-22.04 - needs: [advanced_feat,pgsql_authn_authz,JWT_authn,mysql_authn_authz,built_in_database_authn_authz] - steps: - - uses: geekyeggo/delete-artifact@v2 - with: - name: emqx.tar diff --git a/.github/workflows/run_relup_tests.yaml b/.github/workflows/run_relup_tests.yaml index 0400d0502..3958d5b00 100644 --- a/.github/workflows/run_relup_tests.yaml +++ b/.github/workflows/run_relup_tests.yaml @@ -4,18 +4,20 @@ concurrency: group: relup-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true -# on: -# push: -# branches: -# - '**' -# tags: -# - e* -# pull_request: +on: + workflow_call: + inputs: + runner: + required: true + type: string + builder: + required: true + type: string jobs: relup_test_plan: - runs-on: ubuntu-22.04 - container: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" + runs-on: ${{ inputs.runner }} + container: ${{ inputs.builder }} outputs: CUR_EE_VSN: ${{ steps.find-versions.outputs.CUR_EE_VSN }} OLD_VERSIONS: ${{ steps.find-versions.outputs.OLD_VERSIONS }} @@ -23,16 +25,18 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v3 - name: Checkout + - uses: AutoModality/action-clean@v1 + - uses: actions/download-artifact@v3 with: - path: emqx - fetch-depth: 0 + name: emqx-enterprise + - name: extract artifact + run: | + unzip -o -q emqx-enterprise.zip + git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Find versions id: find-versions run: | set -x - cd emqx ee_vsn="$(./pkg-vsn.sh enterprise)" old_ee_vsns="$(./scripts/relup-build/base-vsns.sh enterprise | xargs)" old_vsns=$(echo -n "${old_ee_vsns}" | sed 's/ $//g' | jq -R -s -c 'split(" ")') @@ -40,8 +44,6 @@ jobs: echo "OLD_VERSIONS=$old_vsns" >> $GITHUB_OUTPUT - name: build emqx run: | - set -x - cd emqx export PROFILE='emqx-enterprise' make emqx-enterprise-tgz - uses: actions/upload-artifact@v3 @@ -49,10 +51,10 @@ jobs: with: name: emqx_built path: | - emqx/_upgrade_base - emqx/_packages - emqx/scripts - emqx/.ci + _upgrade_base + _packages + scripts + .ci relup_test_run: needs: @@ -70,8 +72,7 @@ jobs: run: shell: bash steps: - # setup Erlang to run lux - - uses: erlef/setup-beam@v1.15.4 + - uses: erlef/setup-beam@v1.16.0 with: otp-version: 25.3.2 - uses: actions/checkout@v3 @@ -81,7 +82,7 @@ jobs: path: lux - name: Install lux run: | - set -e -u -x + set -eu cd lux autoconf ./configure @@ -94,10 +95,7 @@ jobs: path: . - name: run relup test run: | - set -e -x -u - chmod a+x scripts/**/*.sh - ls -l scripts - ls -l scripts/relup-test + set -eux case "$OLD_VSN" in e*) export CUR_VSN="$CUR_EE_VSN" diff --git a/.github/workflows/run_test_cases.yaml b/.github/workflows/run_test_cases.yaml index d43079d61..48e551612 100644 --- a/.github/workflows/run_test_cases.yaml +++ b/.github/workflows/run_test_cases.yaml @@ -5,152 +5,34 @@ concurrency: cancel-in-progress: true on: - push: - branches: - - master - - 'ci/**' - tags: - - v* - - e* - pull_request: + workflow_call: + inputs: + runner: + required: true + type: string + builder: + required: true + type: string + ct-matrix: + required: true + type: string + ct-host: + required: true + type: string + ct-docker: + required: true + type: string env: IS_CI: "yes" jobs: - build-matrix: - runs-on: ubuntu-22.04 - outputs: - prepare: ${{ steps.matrix.outputs.prepare }} - host: ${{ steps.matrix.outputs.host }} - docker: ${{ steps.matrix.outputs.docker }} - runs-on: ${{ steps.runner.outputs.runs-on }} - steps: - - uses: actions/checkout@v3 - - name: Build matrix - id: matrix - run: | - APPS="$(./scripts/find-apps.sh --ci)" - MATRIX="$(echo "${APPS}" | jq -c ' - [ - (.[] | select(.profile == "emqx") | . + { - builder: "5.1-3", - otp: "25.3.2-1", - elixir: "1.14.5" - }), - (.[] | select(.profile == "emqx-enterprise") | . + { - builder: "5.1-3", - otp: ["25.3.2-1"][], - elixir: "1.14.5" - }) - ] - ')" - echo "${MATRIX}" | jq - MATRIX_PREPARE="$(echo "${MATRIX}" | jq -c 'map({profile, builder, otp, elixir}) | unique')" - MATRIX_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')" - MATRIX_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')" - echo "prepare=${MATRIX_PREPARE}" | tee -a $GITHUB_OUTPUT - echo "host=${MATRIX_HOST}" | tee -a $GITHUB_OUTPUT - echo "docker=${MATRIX_DOCKER}" | tee -a $GITHUB_OUTPUT - - name: Choose runner host - id: runner - run: | - RUNS_ON="ubuntu-22.04" - ${{ github.repository_owner == 'emqx' }} && RUNS_ON="aws-amd64" - echo "runs-on=${RUNS_ON}" | tee -a $GITHUB_OUTPUT - - prepare: - runs-on: ${{ needs.build-matrix.outputs.runs-on }} - needs: [build-matrix] - strategy: - fail-fast: false - matrix: - include: ${{ fromJson(needs.build-matrix.outputs.prepare) }} - container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/checkout@v3 - with: - path: source - - name: get_all_deps - working-directory: source - env: - PROFILE: ${{ matrix.profile }} - run: | - make ensure-rebar3 - # fetch all deps and compile - make ${{ matrix.profile }}-compile - make test-compile - cd .. - zip -ryq source.zip source/* source/.[^.]* - - uses: actions/upload-artifact@v3 - with: - name: source-${{ matrix.profile }}-${{ matrix.otp }} - path: source.zip - - check_examples: - needs: - - build-matrix - - prepare - runs-on: ${{ needs.build-matrix.outputs.runs-on }} - strategy: - fail-fast: false - matrix: - include: ${{ fromJson(needs.build-matrix.outputs.prepare) }} - container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/download-artifact@v3 - with: - name: source-${{ matrix.profile }}-${{ matrix.otp }} - path: . - - name: unzip source code - run: unzip -o -q source.zip - - name: check example config files - env: - PROFILE: ${{ matrix.profile }} - working-directory: source - run: ./scripts/test/check-example-configs.sh - - static_checks: - needs: - - build-matrix - - prepare - runs-on: ${{ needs.build-matrix.outputs.runs-on }} - strategy: - fail-fast: false - matrix: - include: ${{ fromJson(needs.build-matrix.outputs.prepare) }} - container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" - steps: - - uses: AutoModality/action-clean@v1 - - uses: actions/download-artifact@v3 - with: - name: source-${{ matrix.profile }}-${{ matrix.otp }} - path: . - - name: unzip source code - run: unzip -o -q source.zip - - uses: actions/cache@v3 - with: - path: "source/emqx_dialyzer_${{ matrix.otp }}_plt" - key: rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}-${{ hashFiles('source/rebar.*', 'source/apps/*/rebar.*', 'source/lib-ee/*/rebar.*') }} - restore-keys: | - rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}- - - name: run static checks - env: - PROFILE: ${{ matrix.profile }} - working-directory: source - run: make static_checks - eunit_and_proper: - needs: - - build-matrix - - prepare - runs-on: ${{ needs.build-matrix.outputs.runs-on }} + runs-on: ${{ inputs.runner }} strategy: fail-fast: false matrix: - include: ${{ fromJson(needs.build-matrix.outputs.prepare) }} + include: ${{ fromJson(inputs.ct-matrix) }} defaults: run: @@ -161,16 +43,16 @@ jobs: - uses: AutoModality/action-clean@v1 - uses: actions/download-artifact@v3 with: - name: source-${{ matrix.profile }}-${{ matrix.otp }} - path: . - - name: unzip source code - run: unzip -o -q source.zip + name: ${{ matrix.profile }} + - name: extract artifact + run: | + unzip -o -q ${{ matrix.profile }}.zip + git config --global --add safe.directory "$GITHUB_WORKSPACE" # produces eunit.coverdata - name: eunit env: PROFILE: ${{ matrix.profile }} CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }} - working-directory: source run: make eunit # produces proper.coverdata @@ -178,23 +60,19 @@ jobs: env: PROFILE: ${{ matrix.profile }} CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }} - working-directory: source run: make proper - uses: actions/upload-artifact@v3 with: name: coverdata - path: source/_build/test/cover + path: _build/test/cover ct_docker: - needs: - - build-matrix - - prepare - runs-on: ${{ needs.build-matrix.outputs.runs-on }} + runs-on: ${{ inputs.runner }} strategy: fail-fast: false matrix: - include: ${{ fromJson(needs.build-matrix.outputs.docker) }} + include: ${{ fromJson(inputs.ct-docker) }} defaults: run: @@ -204,14 +82,14 @@ jobs: - uses: AutoModality/action-clean@v1 - uses: actions/download-artifact@v3 with: - name: source-${{ matrix.profile }}-${{ matrix.otp }} - path: . - - name: unzip source code - run: unzip -q source.zip + name: ${{ matrix.profile }} + - name: extract artifact + run: | + unzip -o -q ${{ matrix.profile }}.zip + git config --global --add safe.directory "$GITHUB_WORKSPACE" # produces $PROFILE---sg.coverdata - name: run common tests - working-directory: source env: DOCKER_CT_RUNNER_IMAGE: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" MONGO_TAG: "5" @@ -229,22 +107,19 @@ jobs: - uses: actions/upload-artifact@v3 with: name: coverdata - path: source/_build/test/cover + path: _build/test/cover - uses: actions/upload-artifact@v3 if: failure() with: name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }} - path: source/_build/test/logs + path: _build/test/logs ct: - needs: - - build-matrix - - prepare - runs-on: ${{ needs.build-matrix.outputs.runs-on }} + runs-on: ${{ inputs.runner }} strategy: fail-fast: false matrix: - include: ${{ fromJson(needs.build-matrix.outputs.host) }} + include: ${{ fromJson(inputs.ct-host) }} container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" defaults: @@ -255,14 +130,14 @@ jobs: - uses: AutoModality/action-clean@v1 - uses: actions/download-artifact@v3 with: - name: source-${{ matrix.profile }}-${{ matrix.otp }} - path: . - - name: unzip source code - run: unzip -q source.zip + name: ${{ matrix.profile }} + - name: extract artifact + run: | + unzip -o -q ${{ matrix.profile }}.zip + git config --global --add safe.directory "$GITHUB_WORKSPACE" # produces $PROFILE---sg.coverdata - name: run common tests - working-directory: source env: PROFILE: ${{ matrix.profile }} SUITEGROUP: ${{ matrix.suitegroup }} @@ -272,58 +147,61 @@ jobs: - uses: actions/upload-artifact@v3 with: name: coverdata - path: source/_build/test/cover + path: _build/test/cover if-no-files-found: warn # do not fail if no coverdata found - uses: actions/upload-artifact@v3 if: failure() with: name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }} - path: source/_build/test/logs + path: _build/test/logs make_cover: needs: - eunit_and_proper - ct - ct_docker - runs-on: ubuntu-22.04 - container: "ghcr.io/emqx/emqx-builder/5.1-3:1.14.5-25.3.2-1-ubuntu22.04" + runs-on: ${{ inputs.runner }} + container: ${{ inputs.builder }} + strategy: + fail-fast: false + matrix: + profile: + - emqx-enterprise steps: - uses: AutoModality/action-clean@v1 - uses: actions/download-artifact@v3 with: - name: source-emqx-enterprise-25.3.2-1 - path: . - - name: unzip source code - run: unzip -q source.zip + name: ${{ matrix.profile }} + - name: extract artifact + run: | + unzip -o -q ${{ matrix.profile }}.zip + git config --global --add safe.directory "$GITHUB_WORKSPACE" - uses: actions/download-artifact@v3 name: download coverdata with: name: coverdata - path: source/_build/test/cover + path: _build/test/cover - name: make cover - working-directory: source env: PROFILE: emqx-enterprise run: make cover - name: send to coveralls - working-directory: source env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PROFILE: emqx-enterprise run: make coveralls - name: get coveralls logs - working-directory: source if: failure() run: cat rebar3.crashdump # do this in a separate job upload_coverdata: needs: make_cover - runs-on: ubuntu-22.04 + runs-on: ${{ inputs.runner }} steps: - name: Coveralls Finished env: diff --git a/.github/workflows/shellcheck.yaml b/.github/workflows/shellcheck.yaml deleted file mode 100644 index 7f29572b9..000000000 --- a/.github/workflows/shellcheck.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Shellcheck - -on: - pull_request: - -jobs: - shellcheck: - runs-on: ubuntu-22.04 - steps: - - name: Checkout source code - uses: actions/checkout@v3 - - name: Install shellcheck - run: | - sudo apt-get update - sudo apt install shellcheck - - name: Run shellcheck - run: | - ./scripts/shellcheck.sh - echo "success" diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml new file mode 100644 index 000000000..42a464ee8 --- /dev/null +++ b/.github/workflows/spellcheck.yaml @@ -0,0 +1,29 @@ +name: Spellcheck + +concurrency: + group: spellcheck-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_call: + inputs: + runner: + required: true + type: string + +jobs: + spellcheck: + strategy: + matrix: + profile: + - emqx + - emqx-enterprise + runs-on: ${{ inputs.runner }} + steps: + - uses: actions/download-artifact@v3 + with: + name: "${{ matrix.profile }}_schema_dump" + path: /tmp/ + - name: Run spellcheck + run: | + bash /tmp/scripts/spellcheck/spellcheck.sh /tmp/_build/docgen/${{ matrix.profile }}/schema-en.json diff --git a/.github/workflows/static_checks.yaml b/.github/workflows/static_checks.yaml new file mode 100644 index 000000000..3b32a36b4 --- /dev/null +++ b/.github/workflows/static_checks.yaml @@ -0,0 +1,49 @@ +name: Static checks + +concurrency: + group: static-checks-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_call: + inputs: + runner: + required: true + type: string + builder: + required: true + type: string + ct-matrix: + required: true + type: string + +env: + IS_CI: "yes" + +jobs: + static_checks: + runs-on: ${{ inputs.runner }} + strategy: + fail-fast: false + matrix: + include: ${{ fromJson(inputs.ct-matrix) }} + container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" + steps: + - uses: AutoModality/action-clean@v1 + - uses: actions/download-artifact@v3 + with: + name: ${{ matrix.profile }} + - name: extract artifact + run: | + unzip -o -q ${{ matrix.profile }}.zip + git config --global --add safe.directory "$GITHUB_WORKSPACE" + - uses: actions/cache@v3 + with: + path: "emqx_dialyzer_${{ matrix.otp }}_plt" + key: rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}-${{ hashFiles('rebar.*', 'apps/*/rebar.*', 'lib-ee/*/rebar.*') }} + restore-keys: | + rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}- + - name: run static checks + env: + PROFILE: ${{ matrix.profile }} + run: make static_checks diff --git a/Makefile b/Makefile index db00303d6..037d33cea 100644 --- a/Makefile +++ b/Makefile @@ -143,7 +143,7 @@ endif .PHONY: cover cover: $(REBAR) - @ENABLE_COVER_COMPILE=1 $(REBAR) cover + @ENABLE_COVER_COMPILE=1 $(REBAR) as test cover .PHONY: coveralls coveralls: $(REBAR) diff --git a/build b/build index 1ca324120..fb0d213f2 100755 --- a/build +++ b/build @@ -361,10 +361,10 @@ make_tgz() { log "Archive sha256sum: $(cat "${target}.sha256")" } -trap docker_cleanup EXIT - docker_cleanup() { rm -f ./.dockerignore >/dev/null + # shellcheck disable=SC2015 + [ -f ./.dockerignore.bak ] && mv ./.dockerignore.bak ./.dockerignore >/dev/null || true } ## Build the default docker image based on debian 11. @@ -384,7 +384,14 @@ make_docker() { if [[ "$PROFILE" = *enterprise* ]]; then extra_deps='libsasl2-2,libsasl2-modules-gssapi-mit' fi - echo '_build' >> ./.dockerignore + # shellcheck disable=SC2015 + [ -f ./.dockerignore ] && mv ./.dockerignore ./.dockerignore.bak || true + trap docker_cleanup EXIT + { + echo '/_build' + echo '/deps' + echo '/*.lock' + } >> ./.dockerignore set -x docker build --no-cache --pull \ --build-arg BUILD_FROM="${EMQX_BUILDER}" \ @@ -394,6 +401,7 @@ make_docker() { --tag "${EMQX_IMAGE_TAG}" \ -f "${EMQX_DOCKERFILE}" . [[ "${DEBUG:-}" -eq 1 ]] || set +x + echo "${EMQX_IMAGE_TAG}" > ./.docker_image_tag } function join { diff --git a/rel/i18n/emqx_bridge_dynamo.hocon b/rel/i18n/emqx_bridge_dynamo.hocon index 0b49c6e2f..417b43c0c 100644 --- a/rel/i18n/emqx_bridge_dynamo.hocon +++ b/rel/i18n/emqx_bridge_dynamo.hocon @@ -37,8 +37,7 @@ local_topic.label: template.desc: """Template, the default value is empty. When this value is empty the whole message will be stored in the database.
The template can be any valid JSON with placeholders and make sure all keys for table are here, example:
- {"id" : "${id}", "clientid" : "${clientid}", "data" : "${payload.data}"} -""" + {"id" : "${id}", "clientid" : "${clientid}", "data" : "${payload.data}"}""" template.label: """Template""" diff --git a/rel/i18n/emqx_conf_schema.hocon b/rel/i18n/emqx_conf_schema.hocon index 46d2817ca..442df1fa8 100644 --- a/rel/i18n/emqx_conf_schema.hocon +++ b/rel/i18n/emqx_conf_schema.hocon @@ -779,8 +779,7 @@ db_shard_transports.label: node_broker_pool_size.desc: """The number of workers in emqx_broker pool. Increasing this value may improve performance by enhancing parallelism, especially when EMQX cluster interconnect network latency is high. -Defaults to the number of Erlang schedulers (CPU cores) * 2. -""" +Defaults to the number of Erlang schedulers (CPU cores) * 2.""" node_broker_pool_size.label: """Node Broker Pool Size""" @@ -788,8 +787,7 @@ node_broker_pool_size.label: node_generic_pool_size.desc: """The number of workers in emqx_pool. Increasing this value may improve performance by enhancing parallelism, especially when EMQX cluster interconnect network latency is high. -Defaults to the number of Erlang schedulers (CPU cores). -""" +Defaults to the number of Erlang schedulers (CPU cores).""" node_generic_pool_size.label: """Node Generic Pool Size""" @@ -798,8 +796,7 @@ node_channel_cleanup_batch_size.desc: """The size of the channel cleanup batch. if EMQX cluster interconnect network latency is high, reducing this value together with increasing node.generic_pool_size may improve performance during an abrupt disconnect of a large numbers of clients. -Defaults to 100000. -""" +Defaults to 100000.""" node_channel_cleanup_batch_size.label: """Node Channel Cleanup Batch Size""" diff --git a/rel/i18n/emqx_dashboard_schema.hocon b/rel/i18n/emqx_dashboard_schema.hocon index 0559af2c5..524e633aa 100644 --- a/rel/i18n/emqx_dashboard_schema.hocon +++ b/rel/i18n/emqx_dashboard_schema.hocon @@ -8,8 +8,7 @@ backlog.label: bind.desc: """Port without IP(18083) or port with specified IP(127.0.0.1:18083). -Disabled when setting bind to `0`. -""" +Disabled when setting bind to `0`.""" bind.label: """Bind""" diff --git a/rel/i18n/emqx_mgmt_api_key_schema.hocon b/rel/i18n/emqx_mgmt_api_key_schema.hocon index c217dc2db..811ab8a98 100644 --- a/rel/i18n/emqx_mgmt_api_key_schema.hocon +++ b/rel/i18n/emqx_mgmt_api_key_schema.hocon @@ -10,8 +10,7 @@ bootstrap_file.desc: """The bootstrap file provides API keys for EMQX. EMQX will load these keys on startup to authorize API requests. It contains key-value pairs in the format:`api_key:api_secret`. -Each line specifies an API key and its associated secret. -""" +Each line specifies an API key and its associated secret.""" bootstrap_file.label: """Initialize api_key file.""" diff --git a/scripts/check-i18n-style.escript b/scripts/check-i18n-style.escript index b8b6bdac7..f48e5a513 100755 --- a/scripts/check-i18n-style.escript +++ b/scripts/check-i18n-style.escript @@ -16,9 +16,9 @@ main([Files0]) -> ok = lists:foreach(fun check/1, Files), case get(errors) of 1 -> - logerr("1 error found~n", []); + die("1 error found~n", []); N when is_integer(N) andalso N > 1 -> - logerr("~p errors found~n", [N]); + die("~p errors found~n", [N]); _ -> io:format(user, "~nOK~n", []) end. diff --git a/scripts/parse-git-ref.sh b/scripts/parse-git-ref.sh new file mode 100755 index 000000000..a486f2589 --- /dev/null +++ b/scripts/parse-git-ref.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# $1 is fully qualified git ref name, e.g. refs/tags/v5.1.0 or refs/heads/master + +is_latest() { + ref_name=$(basename "$1") + # shellcheck disable=SC2046 + for t in $(git tag --points-at $(git rev-list --tags --max-count=1)); do + if [[ "$t" == "$ref_name" ]]; then + echo true; + return; + fi + done + echo false +} + +if [[ $1 =~ ^refs/tags/v[5-9]+\.[0-9]+\.[0-9]+$ ]]; then + PROFILE=emqx + EDITION=Opensource + RELEASE=true + LATEST=$(is_latest "$1") +elif [[ $1 =~ ^refs/tags/v[5-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + PROFILE=emqx + EDITION=Opensource + RELEASE=true + LATEST=$(is_latest "$1") +elif [[ $1 =~ ^refs/tags/e[5-9]+\.[0-9]+\.[0-9]+$ ]]; then + PROFILE=emqx-enterprise + EDITION=Enterprise + RELEASE=true + LATEST=$(is_latest "$1") +elif [[ $1 =~ ^refs/tags/e[5-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + PROFILE=emqx-enterprise + EDITION=Enterprise + RELEASE=true + LATEST=$(is_latest "$1") +elif [[ $1 =~ ^refs/tags/v[5-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc)\.[0-9]+$ ]]; then + PROFILE=emqx + EDITION=Opensource + RELEASE=true + LATEST=false +elif [[ $1 =~ ^refs/tags/e[5-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc)\.[0-9]+$ ]]; then + PROFILE=emqx-enterprise + EDITION=Enterprise + RELEASE=true + LATEST=false +elif [[ $1 =~ ^refs/tags/.+ ]]; then + echo "Unrecognized tag: $1" 1>&2 + exit 1 +elif [[ $1 =~ ^refs/heads/master$ ]]; then + PROFILE=emqx + EDITION=Opensource + RELEASE=false + LATEST=false +elif [[ $1 =~ ^refs/heads/release-[5-9][0-9]+$ ]]; then + PROFILE=emqx-enterprise + EDITION=Enterprise + RELEASE=false + LATEST=false +elif [[ $1 =~ ^refs/heads/ci/.* ]]; then + PROFILE=emqx + EDITION=Opensource + RELEASE=false + LATEST=false +else + echo "Unrecognized git ref: $1" 1>&2 + exit 1 +fi + +cat < /dev/null; then + echo "docker is not installed" + exit 1 +fi + +if ! type "yq" > /dev/null; then + echo "yq is not installed" + exit 1 +fi + +EMQX_BUILDER_VERSION=${EMQX_BUILDER_VERSION:-5.1-3} +EMQX_BUILDER_OTP=${EMQX_BUILDER_OTP:-25.3.2-1} +EMQX_BUILDER_ELIXIR=${EMQX_BUILDER_ELIXIR:-1.14.5} +EMQX_BUILDER_PLATFORM=${EMQX_BUILDER_PLATFORM:-ubuntu22.04} +EMQX_BUILDER=${EMQX_BUILDER:-ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VERSION}:${EMQX_BUILDER_ELIXIR}-${EMQX_BUILDER_OTP}-${EMQX_BUILDER_PLATFORM}} + +commands=$(yq ".jobs.sanity-checks.steps[].run" .github/workflows/_pr_entrypoint.yaml | grep -v null) + +BEFORE_REF=${BEFORE_REF:-$(git rev-parse master)} +AFTER_REF=${AFTER_REF:-$(git rev-parse HEAD)} +docker run --rm -it -v "$(pwd):/emqx" -w /emqx \ + -e GITHUB_WORKSPACE=/emqx \ + -e BEFORE_REF="$BEFORE_REF" \ + -e AFTER_REF="$AFTER_REF" \ + -e GITHUB_BASE_REF="$BEFORE_REF" \ + -e MIX_ENV=emqx-enterprise \ + -e PROFILE=emqx-enterprise \ + -e ACTIONLINT_VSN=1.6.25 \ + "${EMQX_BUILDER}" /bin/bash -c "git config --global --add safe.directory /emqx; ${commands}" diff --git a/scripts/shelltest/parse-git-ref.cleanup b/scripts/shelltest/parse-git-ref.cleanup new file mode 100644 index 000000000..8c6dcc027 --- /dev/null +++ b/scripts/shelltest/parse-git-ref.cleanup @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +git tag -d v5.1.99 >/dev/null +git tag -d e5.1.99 >/dev/null diff --git a/scripts/shelltest/parse-git-ref.setup b/scripts/shelltest/parse-git-ref.setup new file mode 100644 index 000000000..f8938787f --- /dev/null +++ b/scripts/shelltest/parse-git-ref.setup @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +git tag v5.1.99 +git tag e5.1.99 diff --git a/scripts/shelltest/parse-git-ref.test b/scripts/shelltest/parse-git-ref.test new file mode 100644 index 000000000..3f2ede0d1 --- /dev/null +++ b/scripts/shelltest/parse-git-ref.test @@ -0,0 +1,94 @@ +./parse-git-ref.sh refs/tags/v5.2.0-foobar.1 +>>>2 +Unrecognized tag: refs/tags/v5.2.0-foobar.1 +>>>= 1 + +./parse-git-ref.sh v5.2.0 +>>>2 +Unrecognized git ref: v5.2.0 +>>>= 1 + +./parse-git-ref.sh refs/tags/v5.1.0 +>>> +{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/v5.1.5.1 +>>> +{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/v5.2.0-alpha.1 +>>> +{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/v5.2.0-alpha-1 +>>>2 +Unrecognized tag: refs/tags/v5.2.0-alpha-1 +>>>= 1 + +./parse-git-ref.sh refs/tags/v5.2.0-beta.1 +>>> +{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/v5.2.0-rc.1 +>>> +{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/e5.1.0 +>>> +{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/e5.1.5.1 +>>> +{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/e5.2.0-alpha.1 +>>> +{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/e5.2.0-beta.1 +>>> +{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/e5.2.0-rc.1 +>>> +{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/tags/e5.1.99 +>>> +{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": true} +>>>= 0 + +./parse-git-ref.sh refs/tags/v5.1.99 +>>> +{"profile": "emqx", "edition": "Opensource", "release": true, "latest": true} +>>>= 0 + +./parse-git-ref.sh refs/heads/master +>>> +{"profile": "emqx", "edition": "Opensource", "release": false, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/heads/release-51 +>>> +{"profile": "emqx-enterprise", "edition": "Enterprise", "release": false, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/heads/ci/foobar +>>> +{"profile": "emqx", "edition": "Opensource", "release": false, "latest": false} +>>>= 0 + +./parse-git-ref.sh refs/heads/release-44 +>>>2 +Unrecognized git ref: refs/heads/release-44 +>>>= 1 diff --git a/scripts/shelltest/run_tests.sh b/scripts/shelltest/run_tests.sh new file mode 100755 index 000000000..11caa6cac --- /dev/null +++ b/scripts/shelltest/run_tests.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC2164 +cd -P -- "$(dirname -- "$0")/.." + +exit_code=0 + +for test in shelltest/*.test; do + echo "Running $test" + /bin/sh "${test%.test}.setup" + shelltest -c --diff --all --precise -- "$test" + # shellcheck disable=SC2181 + if [ $? -ne 0 ]; then + exit_code=1 + fi + /bin/sh "${test%.test}.cleanup" +done + +exit $exit_code