Просмотр исходного кода

Merge branch 'master' into release-v515-patch1-20230809

Thales Macedo Garitezi 2 лет назад
Родитель
Сommit
cce0d144f9

+ 5 - 8
.github/workflows/_push-entrypoint.yaml

@@ -23,7 +23,6 @@ jobs:
     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 }}
@@ -50,12 +49,10 @@ jobs:
         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
@@ -107,8 +104,9 @@ jobs:
       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 }}
+      runner: ${{ needs.prepare.outputs.runner }}
+    secrets: inherit
 
   build_and_push_docker_images:
     if: ${{ needs.prepare.outputs.release == 'true' }}
@@ -117,14 +115,14 @@ jobs:
     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 }}
+      latest: ${{ needs.prepare.outputs.latest }}
       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 }}
+      runner: ${{ needs.prepare.outputs.runner }}
+    secrets: inherit
 
   compile:
     runs-on: ${{ needs.prepare.outputs.runner }}
@@ -188,4 +186,3 @@ jobs:
       runner: ${{ needs.prepare.outputs.runner }}
       builder: ${{ needs.prepare.outputs.builder }}
       ct-matrix: ${{ needs.prepare.outputs.ct-matrix }}
-

+ 34 - 74
.github/workflows/build_and_push_docker_images.yaml

@@ -10,9 +10,6 @@ on:
       profile:
         required: true
         type: string
-      edition:
-        required: true
-        type: string
       version:
         required: true
         type: string
@@ -28,27 +25,31 @@ on:
       elixir_vsn:
         required: true
         type: string
-      runner:
+      builder_vsn:
         required: true
         type: string
-      builder_vsn:
+      runner:
         required: true
         type: string
+    secrets:
+      DOCKER_HUB_USER:
+        required: true
+      DOCKER_HUB_TOKEN:
+        required: true
+      AWS_ACCESS_KEY_ID:
+        required: true
+      AWS_SECRET_ACCESS_KEY:
+        required: true
   workflow_dispatch:
     inputs:
       ref:
         required: false
-      version:
-        required: true
-        type: string
       profile:
         required: false
         type: string
         default: 'emqx'
-      edition:
-        required: false
-        type: string
-        default: 'Opensource'
+      version:
+        required: true
       latest:
         required: false
         type: boolean
@@ -65,14 +66,14 @@ on:
         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'
+      runner:
+        required: false
+        type: string
+        default: 'ubuntu-22.04'
 
 jobs:
   docker:
@@ -83,18 +84,10 @@ jobs:
       matrix:
         profile:
           - ${{ inputs.profile }}
+          - ${{ inputs.profile }}-elixir
         registry:
           - 'docker.io'
           - 'public.ecr.aws'
-        os:
-          - [debian11, "debian:11-slim", "deploy/docker/Dockerfile"]
-        builder:
-          - ${{ inputs.builder_vsn }}
-        otp:
-          - ${{ inputs.otp_vsn }}
-        elixir:
-          - 'no_elixir'
-          - ${{ inputs.elixir_vsn }}
 
     steps:
     - uses: actions/checkout@v3
@@ -121,53 +114,20 @@ jobs:
         password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
         ecr: true
 
-    - name: prepare for docker/metadata-action
-      id: pre-meta
-      shell: bash
+    - name: Build docker image
+      env:
+        PROFILE: ${{ matrix.profile }}
+        DOCKER_REGISTRY: ${{ matrix.registry }}
+        DOCKER_ORG: ${{ github.repository_owner }}
+        DOCKER_LATEST: ${{ inputs.latest }}
+        DOCKER_PUSH: ${{ inputs.publish == 'true' || inputs.publish || github.repository_owner != 'emqx' }}
+        DOCKER_BUILD_NOCACHE: true
+        DOCKER_PLATFORMS: linux/amd64,linux/arm64
+        EMQX_RUNNER: 'debian:11-slim'
+        EMQX_DOCKERFILE: 'deploy/docker/Dockerfile'
+        PKG_VSN: ${{ inputs.version }}
+        EMQX_BUILDER_VSN: ${{ inputs.builder_vsn }}
+        EMQX_OTP_VSN: ${{ inputs.otp_vsn }}
+        EMQX_ELIXIR_VSN: ${{ inputs.elixir_vsn }}
       run: |
-        extra_labels=
-        img_suffix=
-        if [ "${{ matrix.elixir }}" != 'no_elixir' ]; then
-          img_suffix="-elixir"
-          extra_labels="org.opencontainers.image.elixir.version=${{ matrix.elixir }}"
-        fi
-        extra_deps=
-        if [[ "${{ matrix.profile }}" = *enterprise* ]]; then
-          extra_deps='libsasl2-2,libsasl2-modules-gssapi-mit'
-        fi
-
-        echo "img_suffix=$img_suffix" >> $GITHUB_OUTPUT
-        echo "extra_labels=$extra_labels" >> $GITHUB_OUTPUT
-        echo "extra_deps=$extra_deps" >> $GITHUB_OUTPUT
-
-    - uses: docker/metadata-action@v4
-      id: meta
-      with:
-        images: |
-          ${{ matrix.registry }}/${{ github.repository_owner }}/${{ matrix.profile }}
-        flavor: |
-          latest=${{ matrix.elixir == 'no_elixir'  }}
-          suffix=${{ steps.pre-meta.outputs.img_suffix }}
-        tags: |
-          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=${{ inputs.edition }}
-          ${{ steps.pre-meta.outputs.extra_labels }}
-
-    - uses: docker/build-push-action@v3
-      with:
-        push: ${{ inputs.publish == 'true' || github.repository_owner != 'emqx' }}
-        pull: true
-        no-cache: true
-        platforms: linux/amd64,linux/arm64
-        tags: ${{ steps.meta.outputs.tags }}
-        labels: ${{ steps.meta.outputs.labels }}
-        build-args: |
-          EMQX_NAME=${{ matrix.profile }}${{ steps.pre-meta.outputs.img_suffix }}
-          EXTRA_DEPS=${{ steps.pre-meta.outputs.extra_deps }}
-        file: source/${{ matrix.os[2] }}
-
+        ./build ${PROFILE} docker

+ 21 - 2
.github/workflows/build_packages.yaml

@@ -25,6 +25,25 @@ on:
       builder_vsn:
         required: true
         type: string
+    secrets:
+      AWS_ACCESS_KEY_ID:
+        required: true
+      AWS_SECRET_ACCESS_KEY:
+        required: true
+      AWS_DEFAULT_REGION:
+        required: true
+      AWS_S3_BUCKET:
+        required: true
+      AWS_CLOUDFRONT_ID:
+        required: true
+      APPLE_ID_PASSWORD:
+        required: true
+      APPLE_DEVELOPER_IDENTITY:
+        required: true
+      APPLE_DEVELOPER_ID_BUNDLE:
+        required: true
+      APPLE_DEVELOPER_ID_BUNDLE_PASSWORD:
+        required: true
   workflow_dispatch:
     inputs:
       ref:
@@ -249,7 +268,7 @@ jobs:
     needs:
       - mac
       - linux
-    if: ${{ inputs.publish == 'true' }}
+    if: inputs.publish == 'true' || inputs.publish
     strategy:
       fail-fast: false
       matrix:
@@ -261,7 +280,7 @@ jobs:
         name: ${{ matrix.profile }}
         path: packages/${{ matrix.profile }}
     - name: install dos2unix
-      run: sudo apt-get update && sudo apt install -y dos2unix
+      run: apt-get update && apt install -y dos2unix
     - name: get packages
       run: |
         set -eu

+ 18 - 5
apps/emqx/src/emqx_calendar.erl

@@ -158,9 +158,9 @@ offset_second_(Offset) when is_list(Offset) ->
             _ ->
                 error({bad_time_offset, Offset})
         end,
-    Hour = list_to_int_or_error(HourStr, {bad_time_offset_hour, HourStr}),
-    Minute = list_to_int_or_error(MinuteStr, {bad_time_offset_minute, MinuteStr}),
-    Second = list_to_int_or_error(SecondStr, {bad_time_offset_second, SecondStr}),
+    Hour = str_to_int_or_error(HourStr, {bad_time_offset_hour, HourStr}),
+    Minute = str_to_int_or_error(MinuteStr, {bad_time_offset_minute, MinuteStr}),
+    Second = str_to_int_or_error(SecondStr, {bad_time_offset_second, SecondStr}),
     (Hour =< 23) orelse error({bad_time_offset_hour, Hour}),
     (Minute =< 59) orelse error({bad_time_offset_minute, Minute}),
     (Second =< 59) orelse error({bad_time_offset_second, Second}),
@@ -417,7 +417,11 @@ do_parse_date_str(Date, [Key | Formatter], Result) ->
     <<DatePart:Size/binary-unit:8, Tail/binary>> = Date,
     case lists:member(Key, ?DATE_PART) of
         true ->
-            do_parse_date_str(Tail, Formatter, Result#{Key => erlang:binary_to_integer(DatePart)});
+            %% Note: Here is a fix to make the error reason more sense
+            %% when the format or date can't be matched,
+            %% but the root reason comment underneath at <ROOT>
+            PartValue = str_to_int_or_error(DatePart, bad_formatter_or_date),
+            do_parse_date_str(Tail, Formatter, Result#{Key => PartValue});
         false ->
             case lists:member(Key, ?DATE_ZONE_NAME) of
                 true ->
@@ -425,6 +429,13 @@ do_parse_date_str(Date, [Key | Formatter], Result) ->
                         parsed_offset => offset_second(DatePart)
                     });
                 false ->
+                    %% <ROOT>
+                    %% Here should have compared the date part with the key,
+                    %% but for compatibility, we can't fix it here
+                    %% e.g.
+                    %% date_to_unix_ts('second','%Y-%m-%d %H-%M-%S', '2022-05-26 10:40:12')
+                    %% this is valid in 4.x, but actually '%H-%M-%S' can't match with '10:40:12'
+                    %% We cannot ensure whether there are more exceptions in the user's rule
                     do_parse_date_str(Tail, Formatter, Result)
             end
     end.
@@ -456,10 +467,12 @@ dm(10) -> 273;
 dm(11) -> 304;
 dm(12) -> 334.
 
-list_to_int_or_error(Str, Error) ->
+str_to_int_or_error(Str, Error) ->
     case string:to_integer(Str) of
         {Int, []} ->
             Int;
+        {Int, <<>>} ->
+            Int;
         _ ->
             error(Error)
     end.

+ 6 - 4
apps/emqx_ldap/src/emqx_ldap.erl

@@ -54,10 +54,11 @@ fields(config) ->
         {pool_size, fun ?ECS:pool_size/1},
         {username, fun ensure_username/1},
         {password, fun ?ECS:password/1},
-        {base_object,
+        {base_dn,
             ?HOCON(binary(), #{
-                desc => ?DESC(base_object),
+                desc => ?DESC(base_dn),
                 required => true,
+                example => <<"uid=${username},ou=testdevice,dc=emqx,dc=io">>,
                 validator => fun emqx_schema:non_empty_string/1
             })},
         {filter,
@@ -66,6 +67,7 @@ fields(config) ->
                 #{
                     desc => ?DESC(filter),
                     default => <<"(objectClass=mqttUser)">>,
+                    example => <<"(& (objectClass=mqttUser) (uid=${username}))">>,
                     validator => fun emqx_schema:non_empty_string/1
                 }
             )}
@@ -229,9 +231,9 @@ log(Level, Format, Args) ->
     ).
 
 prepare_template(Config, State) ->
-    do_prepare_template(maps:to_list(maps:with([base_object, filter], Config)), State).
+    do_prepare_template(maps:to_list(maps:with([base_dn, filter], Config)), State).
 
-do_prepare_template([{base_object, V} | T], State) ->
+do_prepare_template([{base_dn, V} | T], State) ->
     do_prepare_template(T, State#{base_tokens => emqx_placeholder:preproc_tmpl(V)});
 do_prepare_template([{filter, V} | T], State) ->
     do_prepare_template(T, State#{filter_tokens => emqx_placeholder:preproc_tmpl(V)});

+ 1 - 1
apps/emqx_ldap/test/emqx_ldap_SUITE.erl

@@ -154,7 +154,7 @@ ldap_config(Config) ->
             "    password = public\n"
             "    pool_size = 8\n"
             "    server = \"~s:~b\"\n"
-            "    base_object=\"uid=${username},ou=testdevice,dc=emqx,dc=io\"\n"
+            "    base_dn=\"uid=${username},ou=testdevice,dc=emqx,dc=io\"\n"
             "    filter =\"(objectClass=mqttUser)\"\n"
             "    ~ts\n"
             "",

+ 2 - 2
apps/emqx_ldap/test/emqx_ldap_authn_SUITE.erl

@@ -167,7 +167,7 @@ t_update(_Config) ->
     CorrectConfig = raw_ldap_auth_config(),
     IncorrectConfig =
         CorrectConfig#{
-            <<"base_object">> => <<"ou=testdevice,dc=emqx,dc=io">>
+            <<"base_dn">> => <<"ou=testdevice,dc=emqx,dc=io">>
         },
 
     {ok, _} = emqx:update_config(
@@ -208,7 +208,7 @@ raw_ldap_auth_config() ->
         <<"mechanism">> => <<"password_based">>,
         <<"backend">> => <<"ldap">>,
         <<"server">> => ldap_server(),
-        <<"base_object">> => <<"uid=${username},ou=testdevice,dc=emqx,dc=io">>,
+        <<"base_dn">> => <<"uid=${username},ou=testdevice,dc=emqx,dc=io">>,
         <<"username">> => <<"cn=root,dc=emqx,dc=io">>,
         <<"password">> => <<"public">>,
         <<"pool_size">> => 8

+ 1 - 1
apps/emqx_ldap/test/emqx_ldap_authz_SUITE.erl

@@ -138,7 +138,7 @@ raw_ldap_authz_config() ->
         <<"enable">> => <<"true">>,
         <<"type">> => <<"ldap">>,
         <<"server">> => ldap_server(),
-        <<"base_object">> => <<"uid=${username},ou=testdevice,dc=emqx,dc=io">>,
+        <<"base_dn">> => <<"uid=${username},ou=testdevice,dc=emqx,dc=io">>,
         <<"username">> => <<"cn=root,dc=emqx,dc=io">>,
         <<"password">> => <<"public">>,
         <<"pool_size">> => 8

+ 29 - 0
apps/emqx_rule_engine/test/emqx_rule_funcs_SUITE.erl

@@ -1031,6 +1031,35 @@ timezone_to_offset_seconds_helper(FunctionName) ->
     apply_func(FunctionName, [local]),
     ok.
 
+t_parse_date_errors(_) ->
+    ?assertError(
+        bad_formatter_or_date,
+        emqx_rule_funcs:date_to_unix_ts(
+            second, <<"%Y-%m-%d %H:%M:%S">>, <<"2022-059999-26 10:40:12">>
+        )
+    ),
+    ?assertError(
+        bad_formatter_or_date,
+        emqx_rule_funcs:date_to_unix_ts(second, <<"%y-%m-%d %H:%M:%S">>, <<"2022-05-26 10:40:12">>)
+    ),
+
+    %% Compatibility test
+    UnixTs = 1653561612,
+    ?assertEqual(
+        UnixTs,
+        emqx_rule_funcs:date_to_unix_ts(second, <<"%Y-%m-%d %H:%M:%S">>, <<"2022-05-26 10:40:12">>)
+    ),
+
+    ?assertEqual(
+        UnixTs,
+        emqx_rule_funcs:date_to_unix_ts(second, <<"%Y-%m-%d %H-%M-%S">>, <<"2022-05-26 10:40:12">>)
+    ),
+
+    ?assertEqual(
+        UnixTs,
+        emqx_rule_funcs:date_to_unix_ts(second, <<"%Y-%m-%d %H:%M:%S">>, <<"2022-05-26 10-40-12">>)
+    ).
+
 %%------------------------------------------------------------------------------
 %% Utility functions
 %%------------------------------------------------------------------------------

+ 77 - 17
build

@@ -368,21 +368,87 @@ docker_cleanup() {
 }
 
 ## Build the default docker image based on debian 11.
-## NOTE: docker image build in github action does not call this
-##       function, see build_and_push_docker_images.yaml
 make_docker() {
-    EMQX_BUILDER="${EMQX_BUILDER:-${EMQX_DEFAULT_BUILDER}}"
-    EMQX_RUNNER="${EMQX_RUNNER:-${EMQX_DEFAULT_RUNNER}}"
-    EMQX_DOCKERFILE="${EMQX_DOCKERFILE:-deploy/docker/Dockerfile}"
+    local EMQX_BUILDER_VERSION="${EMQX_BUILDER_VERSION:-5.1-3}"
+    local EMQX_BUILDER_PLATFORM="${EMQX_BUILDER_PLATFORM:-debian11}"
+    local EMQX_BUILDER_OTP="${EMQX_BUILDER_OTP:-25.3.2-1}"
+    local EMQX_BUILDER_ELIXIR="${EMQX_BUILDER_ELIXIR:-1.14.5}"
+    local EMQX_BUILDER=${EMQX_BUILDER:-ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VERSION}:${EMQX_BUILDER_ELIXIR}-${EMQX_BUILDER_OTP}-${EMQX_BUILDER_PLATFORM}}
+    local EMQX_RUNNER="${EMQX_RUNNER:-${EMQX_DEFAULT_RUNNER}}"
+    local EMQX_DOCKERFILE="${EMQX_DOCKERFILE:-deploy/docker/Dockerfile}"
+    local PKG_VSN="${PKG_VSN:-$(./pkg-vsn.sh)}"
+    # shellcheck disable=SC2155
+    local VSN_MAJOR="$(echo "$PKG_VSN" | cut -d . -f 1)"
+    # shellcheck disable=SC2155
+    local VSN_MINOR="$(echo "$PKG_VSN" | cut -d . -f 2)"
+    # shellcheck disable=SC2155
+    local VSN_PATCH="$(echo "$PKG_VSN" | cut -d . -f 3)"
+    local SUFFIX=''
     if [[ "$PROFILE" = *-elixir ]]; then
-        PKG_VSN="$PKG_VSN-elixir"
+        SUFFIX="-elixir"
     fi
-    local default_tag="emqx/${PROFILE%%-elixir}:${PKG_VSN}"
-    EMQX_IMAGE_TAG="${EMQX_IMAGE_TAG:-$default_tag}"
+    local DOCKER_REGISTRY="${REGISTRY:-docker.io}"
+    local DOCKER_ORG="${DOCKER_ORG:-emqx}"
+    local EMQX_BASE_DOCKER_TAG="${DOCKER_REGISTRY}/${DOCKER_ORG}/${PROFILE%%-elixir}"
+    local default_tag="${EMQX_BASE_DOCKER_TAG}:${PKG_VSN}${SUFFIX}"
+    local EMQX_IMAGE_TAG="${EMQX_IMAGE_TAG:-$default_tag}"
+    local EDITION=Opensource
+    local LICENSE='Apache-2.0'
+    local PRODUCT_URL='https://www.emqx.io'
+    local PRODUCT_DESCRIPTION='Official docker image for EMQX, the most scalable open-source MQTT broker for IoT, IIoT, and connected vehicles.'
+    local DOCUMENTATION_URL='https://www.emqx.io/docs/en/latest/'
     ## extra_deps is a comma separated list of debian 11 package names
-    local extra_deps=''
+    local EXTRA_DEPS=''
     if [[ "$PROFILE" = *enterprise* ]]; then
-        extra_deps='libsasl2-2,libsasl2-modules-gssapi-mit'
+        EXTRA_DEPS='libsasl2-2,libsasl2-modules-gssapi-mit'
+        EDITION=Enterprise
+        LICENSE='(Apache-2.0 AND BSL-1.1)'
+        PRODUCT_URL='https://www.emqx.com/en/products/emqx'
+        PRODUCT_DESCRIPTION='Official docker image for EMQX Enterprise, an enterprise MQTT platform at scale. '
+        DOCUMENTATION_URL='https://docs.emqx.com/en/enterprise/latest/'
+    fi
+    # shellcheck disable=SC2155
+    local ISO_8601_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
+    # shellcheck disable=SC2155
+    local GIT_REVISION="$(git rev-parse HEAD)"
+    local DOCKER_BUILDX_ARGS=(
+       --build-arg BUILD_FROM="${EMQX_BUILDER}" \
+       --build-arg RUN_FROM="${EMQX_RUNNER}" \
+       --build-arg EMQX_NAME="${PROFILE}" \
+       --build-arg EXTRA_DEPS="${EXTRA_DEPS}" \
+       --build-arg PKG_VSN="${PKG_VSN}" \
+       --file "${EMQX_DOCKERFILE}" \
+       --label org.opencontainers.image.title="${PROFILE}" \
+       --label org.opencontainers.image.edition="${EDITION}" \
+       --label org.opencontainers.image.version="${PKG_VSN}" \
+       --label org.opencontainers.image.revision="${GIT_REVISION}" \
+       --label org.opencontainers.image.created="${ISO_8601_DATE}" \
+       --label org.opencontainers.image.source='https://github.com/emqx/emqx' \
+       --label org.opencontainers.image.url="${PRODUCT_URL}" \
+       --label org.opencontainers.image.description="${PRODUCT_DESCRIPTION}" \
+       --label org.opencontainers.image.documentation="${DOCUMENTATION_URL}" \
+       --label org.opencontainers.image.licenses="${LICENSE}" \
+       --label org.opencontainers.image.otp.version="${EMQX_BUILDER_OTP}" \
+       --tag "${EMQX_IMAGE_TAG}" \
+       --tag "${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}${SUFFIX}" \
+       --tag "${EMQX_BASE_DOCKER_TAG}:${VSN_MAJOR}.${VSN_MINOR}.${VSN_PATCH}${SUFFIX}" \
+       --provenance false \
+       --pull
+    )
+    if [ "${DOCKER_BUILD_NOCACHE:-false}" = true ]; then
+        DOCKER_BUILDX_ARGS+=(--no-cache)
+    fi
+    if [ "${SUFFIX}" = '-elixir' ]; then
+        DOCKER_BUILDX_ARGS+=(--label org.opencontainers.image.elixir.version="${EMQX_BUILDER_ELIXIR}")
+    fi
+    if [ "${DOCKER_LATEST:-false}" = true ]; then
+        DOCKER_BUILDX_ARGS+=(--tag "${DOCKER_REGISTRY}/${DOCKER_ORG}/${PROFILE}:latest${SUFFIX}")
+    fi
+    if [ "${DOCKER_PLATFORMS:-default}" != 'default' ]; then
+        DOCKER_BUILDX_ARGS+=(--platform "${DOCKER_PLATFORMS}")
+    fi
+    if [ "${DOCKER_PUSH:-false}" = true ]; then
+        DOCKER_BUILDX_ARGS+=(--push)
     fi
     # shellcheck disable=SC2015
     [ -f ./.dockerignore ] && mv ./.dockerignore ./.dockerignore.bak || true
@@ -393,13 +459,7 @@ make_docker() {
         echo '/*.lock'
     } >> ./.dockerignore
     set -x
-    docker build --no-cache --pull \
-       --build-arg BUILD_FROM="${EMQX_BUILDER}" \
-       --build-arg RUN_FROM="${EMQX_RUNNER}" \
-       --build-arg EMQX_NAME="${PROFILE}" \
-       --build-arg EXTRA_DEPS="${extra_deps}" \
-       --tag "${EMQX_IMAGE_TAG}" \
-       -f "${EMQX_DOCKERFILE}" .
+    docker buildx build "${DOCKER_BUILDX_ARGS[@]}" .
     [[ "${DEBUG:-}" -eq 1 ]] || set +x
     echo "${EMQX_IMAGE_TAG}" > ./.docker_image_tag
 }

+ 1 - 0
changes/ce/perf-11405.en.md

@@ -0,0 +1 @@
+Improve the error reason of the `date_to_unix_ts` to make more sense.

+ 1 - 0
deploy/docker/Dockerfile

@@ -5,6 +5,7 @@ FROM ${BUILD_FROM} AS builder
 COPY . /emqx
 
 ARG EMQX_NAME=emqx
+ARG PKG_VSN
 ENV EMQX_RELUP=false
 
 RUN export PROFILE=${EMQX_NAME%%-elixir} \

+ 5 - 4
rel/i18n/emqx_ldap.hocon

@@ -8,16 +8,17 @@ The LDAP default port 389 is used if `[:Port]` is not specified."""
 server.label:
 """Server Host"""
 
-base_object.desc:
+base_dn.desc:
 """The name of the base object entry (or possibly the root) relative to
 which the Search is to be performed."""
 
-base_object.label:
-"""Base Object"""
+base_dn.label:
+"""Base DN"""
 
 filter.desc:
 """The filter that defines the conditions that must be fulfilled in order
-for the Search to match a given entry."""
+for the Search to match a given entry.<br>
+The syntax of the filter follows RFC 4515 and also supports placeholders."""
 
 filter.label:
 """Filter"""

+ 3 - 12
scripts/parse-git-ref.sh

@@ -18,32 +18,26 @@ is_latest() {
 
 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
+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
+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
@@ -51,17 +45,14 @@ elif [[ $1 =~ ^refs/tags/.+ ]]; then
     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
@@ -70,5 +61,5 @@ else
 fi
 
 cat <<EOF
-{"profile": "$PROFILE", "edition": "$EDITION", "release": $RELEASE, "latest": $LATEST}
+{"profile": "$PROFILE", "release": $RELEASE, "latest": $LATEST}
 EOF

+ 17 - 17
scripts/shelltest/parse-git-ref.test

@@ -10,17 +10,17 @@ Unrecognized git ref: v5.2.0
 
 ./parse-git-ref.sh refs/tags/v5.1.0
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false}
+{"profile": "emqx", "release": true, "latest": false}
 >>>= 0
 
-./parse-git-ref.sh refs/tags/v5.1.5.1
+./parse-git-ref.sh refs/tags/v5.1.5-1
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false}
+{"profile": "emqx", "release": true, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/tags/v5.2.0-alpha.1
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false}
+{"profile": "emqx", "release": true, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/tags/v5.2.0-alpha-1
@@ -30,62 +30,62 @@ Unrecognized tag: refs/tags/v5.2.0-alpha-1
 
 ./parse-git-ref.sh refs/tags/v5.2.0-beta.1
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false}
+{"profile": "emqx", "release": true, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/tags/v5.2.0-rc.1
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": true, "latest": false}
+{"profile": "emqx", "release": true, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/tags/e5.1.0
 >>>
-{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": false}
+{"profile": "emqx-enterprise", "release": true, "latest": false}
 >>>= 0
 
-./parse-git-ref.sh refs/tags/e5.1.5.1
+./parse-git-ref.sh refs/tags/e5.1.5-1
 >>>
-{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": false}
+{"profile": "emqx-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}
+{"profile": "emqx-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}
+{"profile": "emqx-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}
+{"profile": "emqx-enterprise", "release": true, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/tags/e5.1.99
 >>>
-{"profile": "emqx-enterprise", "edition": "Enterprise", "release": true, "latest": true}
+{"profile": "emqx-enterprise", "release": true, "latest": true}
 >>>= 0
 
 ./parse-git-ref.sh refs/tags/v5.1.99
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": true, "latest": true}
+{"profile": "emqx", "release": true, "latest": true}
 >>>= 0
 
 ./parse-git-ref.sh refs/heads/master
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": false, "latest": false}
+{"profile": "emqx", "release": false, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/heads/release-51
 >>>
-{"profile": "emqx-enterprise", "edition": "Enterprise", "release": false, "latest": false}
+{"profile": "emqx-enterprise", "release": false, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/heads/ci/foobar
 >>>
-{"profile": "emqx", "edition": "Opensource", "release": false, "latest": false}
+{"profile": "emqx", "release": false, "latest": false}
 >>>= 0
 
 ./parse-git-ref.sh refs/heads/release-44