Skip to content

Commit

Permalink
[3.4] Backport cherry-pick of etcd-io#14860: Trigger release in curre…
Browse files Browse the repository at this point in the history
…nt branch for github workflow case

Signed-off-by: ArkaSaha30 <[email protected]>
  • Loading branch information
serathius authored and ArkaSaha30 committed Mar 30, 2023
2 parents bf22b35 + 7d62b4d commit 3b86bb3
Show file tree
Hide file tree
Showing 12 changed files with 550 additions and 125 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ jobs:
Name-Email: [email protected]
Expire-Date: 0
EOF
DRY_RUN=true ./scripts/release.sh --no-upload --no-docker-push 3.4.99
DRY_RUN=true ./scripts/release.sh --no-upload --no-docker-push --in-place 3.4.99
21 changes: 10 additions & 11 deletions scripts/build-binary.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ source ./scripts/test_lib.sh

VER=$1
PROJ="etcd"
REPOSITORY="${REPOSITORY:-https://github.com/etcd-io/etcd.git}"
REPOSITORY="${REPOSITORY:-git@github.com:etcd-io/etcd.git}"

if [ -z "$1" ]; then
echo "Usage: ${0} VERSION" >> /dev/stderr
Expand All @@ -16,18 +16,17 @@ fi
set -u

function setup_env {
local proj=${1}
local ver=${2}
local ver=${1}
local proj=${2}

if [ ! -d "${proj}" ]; then
log_callout "Cloning ${REPOSITORY}..."
git clone "${REPOSITORY}"
fi
if [ ! -d "${proj}" ]; then
run git clone "${REPOSITORY}"
fi

pushd "${proj}" >/dev/null
git fetch --all
git checkout "${ver}"
popd >/dev/null
pushd "${proj}" >/dev/null
run git fetch --all
run git checkout "${ver}"
popd >/dev/null
}


Expand Down
72 changes: 61 additions & 11 deletions scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ help() {
echo " flags:"
echo " --no-upload: skip gs://etcd binary artifact uploads."
echo " --no-docker-push: skip docker image pushes."
echo " --in-place: build binaries using current branch."
echo ""
}

Expand All @@ -34,7 +35,15 @@ main() {
fi
RELEASE_VERSION="v${VERSION}"
MINOR_VERSION=$(echo "${VERSION}" | cut -d. -f 1-2)
BRANCH="release-${MINOR_VERSION}"

if [ "${IN_PLACE}" == 1 ]; then
# Trigger release in current branch
REPOSITORY=$(pwd)
BRANCH=$(git rev-parse --abbrev-ref HEAD)
else
REPOSITORY=${REPOSITORY:-"https://github.com/etcd-io/etcd.git"}
BRANCH=${BRANCH:-"release-${MINOR_VERSION}"}
fi

log_warning "DRY_RUN=${DRY_RUN}"
log_callout "RELEASE_VERSION=${RELEASE_VERSION}"
Expand All @@ -53,12 +62,16 @@ main() {
# Set up release directory.
local reldir="/tmp/etcd-release-${VERSION}"
log_callout "Preparing temporary directory: ${reldir}"
if [ ! -d "${reldir}/etcd" ]; then
if [ ! -d "${reldir}/etcd" ] && [ "${IN_PLACE}" == 0 ]; then
mkdir -p "${reldir}"
cd "${reldir}"
git clone https://github.com/etcd-io/etcd.git --branch "${BRANCH}"
run git clone "${REPOSITORY}" --branch "${BRANCH}"
run cd "${reldir}/etcd" || exit 2
run git checkout "${BRANCH}" || exit 2
run git pull origin

git_assert_branch_in_sync || exit 2
fi
cd "${reldir}/etcd"

# If a release version tag already exists, use it.
log_callout "Checking tag: ${RELEASE_VERSION}"
Expand All @@ -70,7 +83,7 @@ main() {
fi

# Check go version.
log_callout "Checking go version"
log_callout "Check go version"
local go_version current_go_version
go_version="go$(grep go-version .github/workflows/tests.yaml | awk '{print $2}' | tr -d '"')"
current_go_version=$(go version | awk '{ print $3 }')
Expand All @@ -80,6 +93,7 @@ main() {
fi

# If the release tag does not already exist remotely, create it.
log_callout "Create tag if not present"
if [ "${remote_tag_exists}" -eq 0 ]; then
# Bump version/version.go to release version.
local source_version
Expand Down Expand Up @@ -140,12 +154,19 @@ main() {
exit 1
fi

# Verify the version tag is on the right branch
# shellcheck disable=SC2155
local branch=$(git for-each-ref --contains "${RELEASE_VERSION}" --format="%(refname)" 'refs/heads' | cut -d '/' -f 3)
if [ "${branch}" != "release-${MINOR_VERSION}" ]; then
log_error "Error: Git tag ${RELEASE_VERSION} should be on branch release-${MINOR_VERSION} but is on ${branch}"
exit 1
if [ "${IN_PLACE}" == 0 ]; then
# Tried with `local branch=$(git branch -a --contains tags/"${RELEASE_VERSION}")`
# so as to work with both current branch and main/release-3.X.
# But got error below on current branch mode,
# Error: Git tag v3.6.99 should be on branch '* (HEAD detached at pull/14860/merge)' but is on '* (HEAD detached from pull/14860/merge)'
#
# Verify the version tag is on the right branch
# shellcheck disable=SC2155
local branch=$(git for-each-ref --contains "${RELEASE_VERSION}" --format="%(refname)" 'refs/heads' | cut -d '/' -f 3)
if [ "${branch}" != "${BRANCH}" ]; then
log_error "Error: Git tag ${RELEASE_VERSION} should be on branch '${BRANCH}' but is on '${branch}'"
exit 1
fi
fi

# Push the tag change if it's not already been pushed.
Expand All @@ -154,6 +175,23 @@ main() {
[[ "${confirm,,}" == "y" ]] || exit 1
git push origin "tags/${RELEASE_VERSION}"
fi
log_callout "Verify the latest commit has the version tag"
# Verify the latest commit has the version tag
# shellcheck disable=SC2155
local tag="$(git describe --exact-match HEAD)"
if [ "${tag}" != "${RELEASE_VERSION}" ]; then
log_error "Error: Expected HEAD to be tagged with ${RELEASE_VERSION}, but 'git describe --exact-match HEAD' reported: ${tag}"
exit 1
fi

log_callout "Verify the work space is clean"
# Verify the clean working tree
# shellcheck disable=SC2155
local diff="$(git diff HEAD --stat)"
if [[ "${diff}" != '' ]]; then
log_error "Error: Expected clean working tree, but 'git diff --stat' reported: ${diff}"
exit 1
fi
fi

# Build release.
Expand Down Expand Up @@ -261,6 +299,7 @@ main() {
POSITIONAL=()
NO_UPLOAD=0
NO_DOCKER_PUSH=0
IN_PLACE=0

while test $# -gt 0; do
case "$1" in
Expand All @@ -269,6 +308,10 @@ while test $# -gt 0; do
help
exit 0
;;
--in-place)
IN_PLACE=1
shift
;;
--no-upload)
NO_UPLOAD=1
shift
Expand All @@ -290,4 +333,11 @@ if [[ ! $# -eq 1 ]]; then
exit 1
fi

# Note that we shouldn't upload artifacts in --in-place mode, so it
# must be called with DRY_RUN=true
if [ "${DRY_RUN}" != "true" ] && [ "${IN_PLACE}" == 1 ]; then
log_error "--in-place should only be called with DRY_RUN=true"
exit 1
fi

main "$1"
2 changes: 1 addition & 1 deletion scripts/test_lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ function log_info {
>&2 echo -n -e "${COLOR_NONE}"
>&2 echo "$@"
>&2 echo -n -e "${COLOR_NONE}"
}
}
8 changes: 0 additions & 8 deletions tests/e2e/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ import (

const etcdProcessBasePort = 20000

type clientConnType int

const (
clientNonTLS clientConnType = iota
clientTLS
clientTLSAndNonTLS
)

var (
configNoTLS = etcdProcessClusterConfig{
clusterSize: 3,
Expand Down
167 changes: 167 additions & 0 deletions tests/e2e/cmux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2023 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// These tests are directly validating etcd connection multiplexing.
//go:build !cluster_proxy

package e2e

import (
"context"
"encoding/json"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

clientv2 "go.etcd.io/etcd/client"
pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
"go.etcd.io/etcd/pkg/testutil"
)

func TestConnectionMultiplexing(t *testing.T) {
defer testutil.AfterTest(t)
for _, tc := range []struct {
name string
serverTLS clientConnType
}{
{
name: "ServerTLS",
serverTLS: clientTLS,
},
{
name: "ServerNonTLS",
serverTLS: clientNonTLS,
},
{
name: "ServerTLSAndNonTLS",
serverTLS: clientTLSAndNonTLS,
},
} {
t.Run(tc.name, func(t *testing.T) {
ctx := context.Background()
cfg := etcdProcessClusterConfig{clusterSize: 1, clientTLS: tc.serverTLS, enableV2: true}
clus, err := newEtcdProcessCluster(&cfg)
require.NoError(t, err)
defer clus.Close()

var clientScenarios []clientConnType
switch tc.serverTLS {
case clientTLS:
clientScenarios = []clientConnType{clientTLS}
case clientNonTLS:
clientScenarios = []clientConnType{clientNonTLS}
case clientTLSAndNonTLS:
clientScenarios = []clientConnType{clientTLS, clientNonTLS}
}

for _, connType := range clientScenarios {
name := "ClientNonTLS"
if connType == clientTLS {
name = "ClientTLS"
}
t.Run(name, func(t *testing.T) {
testConnectionMultiplexing(ctx, t, clus.EndpointsV3()[0], connType)
})
}
})
}

}

func testConnectionMultiplexing(ctx context.Context, t *testing.T, endpoint string, connType clientConnType) {
switch connType {
case clientTLS:
endpoint = toTLS(endpoint)
case clientNonTLS:
default:
panic(fmt.Sprintf("Unsupported conn type %v", connType))
}
t.Run("etcdctl", func(t *testing.T) {
t.Run("v2", func(t *testing.T) {
etcdctl := NewEtcdctl([]string{endpoint}, connType, false, true)
err := etcdctl.Set("a", "1")
assert.NoError(t, err)
})
t.Run("v3", func(t *testing.T) {
etcdctl := NewEtcdctl([]string{endpoint}, connType, false, false)
err := etcdctl.Put("a", "1")
assert.NoError(t, err)
})
})
t.Run("clientv2", func(t *testing.T) {
c, err := newClientV2(t, []string{endpoint}, connType, false)
require.NoError(t, err)
kv := clientv2.NewKeysAPI(c)
_, err = kv.Set(ctx, "a", "1", nil)
assert.NoError(t, err)
})
t.Run("clientv3", func(t *testing.T) {
c := newClient(t, []string{endpoint}, connType, false)
_, err := c.Get(ctx, "a")
assert.NoError(t, err)
})
t.Run("curl", func(t *testing.T) {
for _, httpVersion := range []string{"2", "1.1", "1.0", ""} {
tname := "http" + httpVersion
if httpVersion == "" {
tname = "default"
}
t.Run(tname, func(t *testing.T) {
assert.NoError(t, fetchGrpcGateway(endpoint, httpVersion, connType))
assert.NoError(t, fetchMetrics(endpoint, httpVersion, connType))
assert.NoError(t, fetchVersion(endpoint, httpVersion, connType))
assert.NoError(t, fetchHealth(endpoint, httpVersion, connType))
assert.NoError(t, fetchDebugVars(endpoint, httpVersion, connType))
})
}
})
}

func fetchGrpcGateway(endpoint string, httpVersion string, connType clientConnType) error {
rangeData, err := json.Marshal(&pb.RangeRequest{
Key: []byte("a"),
})
if err != nil {
return err
}
req := cURLReq{endpoint: "/v3/kv/range", value: string(rangeData), timeout: 5, httpVersion: httpVersion}
return curl(endpoint, "POST", req, connType, "header")
}

func fetchMetrics(endpoint string, httpVersion string, connType clientConnType) error {
req := cURLReq{endpoint: "/metrics", timeout: 5, httpVersion: httpVersion}
return curl(endpoint, "GET", req, connType, "etcd_cluster_version")
}

func fetchVersion(endpoint string, httpVersion string, connType clientConnType) error {
req := cURLReq{endpoint: "/version", timeout: 5, httpVersion: httpVersion}
return curl(endpoint, "GET", req, connType, "etcdserver")
}

func fetchHealth(endpoint string, httpVersion string, connType clientConnType) error {
req := cURLReq{endpoint: "/health", timeout: 5, httpVersion: httpVersion}
return curl(endpoint, "GET", req, connType, "health")
}

func fetchDebugVars(endpoint string, httpVersion string, connType clientConnType) error {
req := cURLReq{endpoint: "/debug/vars", timeout: 5, httpVersion: httpVersion}
return curl(endpoint, "GET", req, connType, "file_descriptor_limit")
}

func curl(endpoint string, method string, curlReq cURLReq, connType clientConnType, expect string) error {
args := cURLPrefixArgs(endpoint, connType, false, method, curlReq)
return spawnWithExpect(args, expect)
}
Loading

0 comments on commit 3b86bb3

Please sign in to comment.