diff --git a/.github/workflows/tree.yml b/.github/workflows/tree.yml new file mode 100644 index 000000000000..a415aa07d9d8 --- /dev/null +++ b/.github/workflows/tree.yml @@ -0,0 +1,53 @@ +name: tree + +on: + push: + branches: + - 'master' + - 'release/**' + +concurrency: + # Update of a developer branch cancels the previously scheduled workflow + # run for this branch. However, the 'master' branch, release branch, and + # tag workflow runs are never canceled. + # + # We use a trick here: define the concurrency group as 'workflow run ID' + + # 'workflow run attempt' because it is a unique combination for any run. + # So it effectively discards grouping. + # + # Important: we cannot use `github.sha` as a unique identifier because + # pushing a tag may cancel a run that works on a branch push event. + group: ${{ ( + github.ref == 'refs/heads/master' || + startsWith(github.ref, 'refs/heads/release/') || + startsWith(github.ref, 'refs/tags/')) && + format('{0}-{1}', github.run_id, github.run_attempt) || + format('{0}-{1}', github.workflow, github.ref) }} + cancel-in-progress: true + +jobs: + entrypoint-tag: + if: github.repository == 'tarantool/tarantool' + + runs-on: ubuntu-20.04-self-hosted + + container: + image: docker.io/tarantool/testing:ubuntu-jammy + + steps: + - name: Prepare checkout + uses: tarantool/actions/prepare-checkout@master + + - name: Sources checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check entrypoint tag + run: ./tools/check-entrypoint-tag.sh + + - name: Send VK Teams message on failure + if: failure() + uses: ./.github/actions/report-job-status + with: + bot-token: ${{ secrets.VKTEAMS_BOT_TOKEN }} diff --git a/tools/check-entrypoint-tag.sh b/tools/check-entrypoint-tag.sh new file mode 100755 index 000000000000..66e0658a4249 --- /dev/null +++ b/tools/check-entrypoint-tag.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# +# This script checks that current branch has most recent entrypoint tag. +# Entrypoint tag is annotated tag. Release tags are also expected to +# be annotated tags. +# +# There are 2 cases when we require entrypoint tag. +# +# 1. We require that after release tag (like 2.11.3) the next commit +# has entrypoint tag (2.11.4-entrypoint). +# +# 2. After branching. For example we develop 3.0.0 in master. And decide +# to create 3.0 branch. The first commint in 3.0 branch is required +# to have some tag (like 3.0.0-rc1, 3.0.0 or whatever). The first commit after +# fork in master branch is required to have entrypoint tag (3.1.0-entrypoint). +# +# Note that in both cases we do not check that entrypoint tag has proper +# suffix or numbers. +# +# We check for most recent entrypoint tag only. For example if there +# are tags 2.10.0 and 2.10.1 we only check for 2.10.2-entrypoint. +# +# Expected branches names: +# +# - master +# - release/* + +set -eo pipefail + +error() { + echo "$@" 1>&2 + exit 1 +} + +######### +# Case 1. +######### + +# Match digit only release tags like 2.10.0. +pattern='^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+$' +# Get most recent tag in the HEAD ancestry. +tag=`git describe --abbrev=0` +# If it is a release tag. +if [[ "$tag" =~ $pattern ]]; then + # Find the commit just after the release tag in the HEAD ancestry. + # It is not tagged as entrypoint because it was not seen by the + # describe command above. + entrypoint=`git rev-list HEAD ^$tag | tail -n1` + if [[ $entrypoint ]]; then + error "Missing entrypoint tag for commit $entrypoint after release"\ + "tag $tag." + fi +fi + +######### +# Case 2. +######### + +# Find current branch (report HEAD for 'detached HEAD' state). +branch=`git rev-parse --abbrev-ref HEAD` +if [[ "$branch" =~ ^(master|release/.*)$ ]]; then + # We need to find the commit that starts this branch (i.e. that the first + # commit on this branch after the commit that is common for two branches.) + # + # In order to achieve this we find all the commits of this branch that + # are not on other branches from release/* && master set. + # + # Unfortunately I did not find a way to set arguments for git rev-list + # without this branch. + if [[ "$branch" = master ]]; then + not_remotes="--remotes=origin/release/*" + else + not_remotes="--exclude origin/$branch --remotes=origin/release/* origin/master" + fi + entrypoint=`git rev-list HEAD --not $not_remotes | tail -n1` + if [[ $entrypoint ]]; then + # Check if entrypoint has annotated tag. + git describe --exact-match $entrypoint &>/dev/null || \ + error "Missing tag for commit $entrypoint after branching in"\ + "branch $branch." + fi +fi + +echo OK