1+ # Copyright 2026 The casbin Authors. All Rights Reserved.
2+
3+ # Licensed under the Apache License, Version 2.0 (the "License");
4+ # you may not use this file except in compliance with the License.
5+ # You may obtain a copy of the License at
6+
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+
9+ # Unless required by applicable law or agreed to in writing, software
10+ # distributed under the License is distributed on an "AS IS" BASIS,
11+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ # See the License for the specific language governing permissions and
13+ # limitations under the License.
14+
15+ # Releases are cut by hand: the release manager pushes a tag, and this workflow
16+ # turns that tag into a GitHub release. Nothing is published on a plain merge to
17+ # master, because an Apache release has to be voted on before it exists.
18+ #
19+ # v1.4.0-rc1 -> GitHub *pre-release*, for the release manager to sign and
20+ # put up for a vote.
21+ # v1.4.0 -> GitHub release plus a pull request against the vcpkg
22+ # registry, once that vote has passed.
23+ #
24+ # Both cases attach the same source package, named and laid out the way an
25+ # Apache release vote expects. The release manager downloads it, signs it
26+ # locally, and votes with it; the signature never comes back through here.
27+
128name : Release
229
330on :
431 push :
5- branches :
6- - master
7- pull_request :
8- branches :
9- - master
32+ tags :
33+ - ' v* '
34+
35+ permissions :
36+ contents : write
1037
1138jobs :
12- semantic-release :
39+ github-release :
40+ name : GitHub release
41+ if : github.repository == 'casbin/casbin-cpp'
42+ runs-on : ubuntu-latest
43+ outputs :
44+ version : ${{ steps.meta.outputs.version }}
45+ prerelease : ${{ steps.meta.outputs.prerelease }}
46+ steps :
47+ - name : Checkout
48+ uses : actions/checkout@v4
49+ with :
50+ fetch-depth : 0
51+
52+ - name : Read the version out of the tag
53+ id : meta
54+ run : |
55+ set -euo pipefail
56+ tag="${GITHUB_REF_NAME}"
57+ full="${tag#v}"
58+ # The package always carries the final version, even for a release
59+ # candidate, so the exact bits that were voted on can be promoted
60+ # without being repackaged: v1.4.0-rc1 also packages as 1.4.0.
61+ version="${full%%-rc*}"
62+ if [ "$full" = "$version" ]; then
63+ prerelease=false
64+ else
65+ prerelease=true
66+ fi
67+ {
68+ echo "version=${version}"
69+ echo "prerelease=${prerelease}"
70+ } >> "$GITHUB_OUTPUT"
71+ echo "::notice::${tag} -> version ${version}, prerelease=${prerelease}"
72+
73+ - name : Build the source release package
74+ id : package
75+ env :
76+ VERSION : ${{ steps.meta.outputs.version }}
77+ run : |
78+ set -euo pipefail
79+ name="apache-casbin-cpp-${VERSION}-src"
80+ # git archive ships exactly what is tracked at the tag: no .git, no
81+ # build output, no bundled binaries, everything under a single
82+ # versioned top-level directory.
83+ git archive --format=tar.gz --prefix="${name}/" -o "${name}.tar.gz" "${GITHUB_REF_NAME}"
84+ sha512sum "${name}.tar.gz" > "${name}.tar.gz.sha512"
85+ echo "tarball=${name}.tar.gz" >> "$GITHUB_OUTPUT"
86+
87+ - name : Check the package carries the required legal files
88+ env :
89+ TARBALL : ${{ steps.package.outputs.tarball }}
90+ run : |
91+ set -euo pipefail
92+ prefix="${TARBALL%.tar.gz}"
93+ # Listed once into a variable: piping tar into `grep -q` would leave
94+ # tar killed by SIGPIPE, which pipefail reports as a failed check.
95+ listing="$(tar -tzf "${TARBALL}")"
96+ for legal in LICENSE NOTICE; do
97+ if ! grep -qx "${prefix}/${legal}" <<< "${listing}"; then
98+ echo "::error::${legal} is missing from ${TARBALL}; the release vote would fail on it"
99+ exit 1
100+ fi
101+ done
102+
103+ - name : Publish the release
104+ env :
105+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
106+ TARBALL : ${{ steps.package.outputs.tarball }}
107+ PRERELEASE : ${{ steps.meta.outputs.prerelease }}
108+ run : |
109+ set -euo pipefail
110+ args=(--title "${GITHUB_REF_NAME}" --generate-notes)
111+ if [ "${PRERELEASE}" = "true" ]; then
112+ args+=(--prerelease)
113+ fi
114+ gh release create "${GITHUB_REF_NAME}" "${args[@]}" "${TARBALL}" "${TARBALL}.sha512"
115+
116+ vcpkg :
117+ name : Submit to vcpkg
118+ needs : github-release
119+ # Release candidates exist only for the vote; they never reach a registry.
120+ if : needs.github-release.outputs.prerelease == 'false'
13121 runs-on : ubuntu-latest
122+ env :
123+ VERSION : ${{ needs.github-release.outputs.version }}
124+ # A fork of microsoft/vcpkg that the token below can push to.
125+ FORK : ${{ vars.VCPKG_FORK || 'casbin/vcpkg' }}
14126 steps :
15- - uses : actions/checkout@v3
127+ - name : Check the vcpkg fork token is configured
128+ id : gate
129+ env :
130+ VCPKG_PR_TOKEN : ${{ secrets.VCPKG_PR_TOKEN }}
131+ run : |
132+ if [ -n "${VCPKG_PR_TOKEN}" ]; then
133+ echo "enabled=true" >> "$GITHUB_OUTPUT"
134+ else
135+ echo "enabled=false" >> "$GITHUB_OUTPUT"
136+ echo "::warning::VCPKG_PR_TOKEN is not set, so no vcpkg pull request was opened for ${VERSION}."
137+ fi
138+
139+ - name : Checkout casbin-cpp
140+ if : steps.gate.outputs.enabled == 'true'
141+ uses : actions/checkout@v4
142+ with :
143+ path : casbin-cpp
16144
17- - name : Run semantic-release
18- if : github.repository == 'casbin/casbin-cpp' && github.event_name == 'push'
145+ - name : Checkout vcpkg
146+ if : steps.gate.outputs.enabled == 'true'
147+ uses : actions/checkout@v4
148+ with :
149+ repository : microsoft/vcpkg
150+ path : vcpkg
151+ fetch-depth : 0
152+
153+ - name : Render the casbin port
154+ if : steps.gate.outputs.enabled == 'true'
19155 run : |
20- export PATH="$(yarn global bin):$PATH"
21- yarn global add semantic-release@19.0.5
22- semantic-release
23- sleep 10
156+ set -euo pipefail
157+ # vcpkg_from_github pins the tarball GitHub generates for the tag, so
158+ # that is the file whose checksum goes into the port.
159+ curl -fsSL -o source.tar.gz \
160+ "https://github.com/${GITHUB_REPOSITORY}/archive/refs/tags/v${VERSION}.tar.gz"
161+ sha512="$(sha512sum source.tar.gz | cut -d' ' -f1)"
162+ mkdir -p vcpkg/ports/casbin
163+ for file in portfile.cmake vcpkg.json; do
164+ sed -e "s|@VERSION@|${VERSION}|g" -e "s|@SHA512@|${sha512}|g" \
165+ "casbin-cpp/.github/vcpkg/casbin/${file}" > "vcpkg/ports/casbin/${file}"
166+ done
167+
168+ - name : Update the vcpkg version database
169+ if : steps.gate.outputs.enabled == 'true'
170+ working-directory : vcpkg
171+ run : |
172+ set -euo pipefail
173+ git config user.name "casbin-bot"
174+ git config user.email "casbin-bot@users.noreply.github.com"
175+ git add ports/casbin
176+ git commit -m "[casbin] Update to ${VERSION}"
177+ ./bootstrap-vcpkg.sh -disableMetrics
178+ # x-add-version reads the port out of the commit above, so it has to
179+ # run after it; the result is folded back into the same commit.
180+ ./vcpkg x-add-version casbin --overwrite-version
181+ git add versions
182+ git commit --amend --no-edit
183+
184+ - name : Open the pull request against microsoft/vcpkg
185+ if : steps.gate.outputs.enabled == 'true'
186+ working-directory : vcpkg
24187 env :
25- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
188+ GH_TOKEN : ${{ secrets.VCPKG_PR_TOKEN }}
189+ run : |
190+ set -euo pipefail
191+ branch="casbin-${VERSION}"
192+ git remote add fork "https://x-access-token:${GH_TOKEN}@github.com/${FORK}.git"
193+ git push --force fork "HEAD:${branch}"
194+ gh pr create \
195+ --repo microsoft/vcpkg \
196+ --base master \
197+ --head "${FORK%%/*}:${branch}" \
198+ --title "[casbin] Update to ${VERSION}" \
199+ --body "Updates the \`casbin\` port to ${VERSION}, released at https://github.com/${GITHUB_REPOSITORY}/releases/tag/v${VERSION}."
0 commit comments