Skip to content

Commit c8a0458

Browse files
committed
ci: replace semantic-release with manual tag-based release
1 parent 2d90c7d commit c8a0458

6 files changed

Lines changed: 522 additions & 2745 deletions

File tree

.github/workflows/main.yml

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,3 @@ jobs:
2727
token: ${{ secrets.CODECOV_TOKEN }}
2828
flags: node-${{ matrix.node-version }}
2929
fail_ci_if_error: false
30-
31-
semantic-release:
32-
needs: [test]
33-
runs-on: ubuntu-latest
34-
steps:
35-
- uses: actions/checkout@v4
36-
37-
- name: Run semantic-release
38-
if: github.repository == 'apache/casbin-node-casbin' && github.event_name == 'push'
39-
run: yarn install && yarn semantic-release
40-
env:
41-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/release.yml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: release
2+
3+
# Releases are cut manually by pushing a git tag (Apache requires a release vote,
4+
# so nothing is ever published automatically from a commit or a merged PR).
5+
#
6+
# v5.44.0-rc1 -> GitHub *pre-release* (the candidate the release manager votes on)
7+
# v5.44.0 -> GitHub release + publish to npm
8+
#
9+
# Both cases attach an Apache-style source release tarball plus its SHA-512
10+
# checksum. The release manager downloads the tarball, signs it locally with
11+
# their own GPG key, and uses that for the vote.
12+
on:
13+
push:
14+
tags:
15+
- 'v*'
16+
17+
permissions:
18+
contents: write
19+
20+
env:
21+
# Base name of the Apache source release artifact.
22+
ARTIFACT_PREFIX: apache-casbin-node-casbin
23+
24+
jobs:
25+
release:
26+
runs-on: ubuntu-latest
27+
outputs:
28+
prerelease: ${{ steps.meta.outputs.prerelease }}
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Resolve release metadata
35+
id: meta
36+
run: |
37+
set -euo pipefail
38+
TAG="${GITHUB_REF_NAME}"
39+
VERSION="${TAG#v}"
40+
41+
# A candidate tag (v5.44.0-rc1) is a pre-release; the artifact inside it is
42+
# still named after the final version so it can be promoted unchanged.
43+
if [[ "$VERSION" == *-rc* ]]; then
44+
PRERELEASE=true
45+
else
46+
PRERELEASE=false
47+
fi
48+
BASE_VERSION="${VERSION%%-rc*}"
49+
50+
PKG_VERSION="$(node -p "require('./package.json').version")"
51+
if [[ "$BASE_VERSION" != "$PKG_VERSION" ]]; then
52+
echo "::error::Tag $TAG implies version $BASE_VERSION but package.json says $PKG_VERSION"
53+
exit 1
54+
fi
55+
56+
{
57+
echo "tag=$TAG"
58+
echo "version=$VERSION"
59+
echo "base_version=$BASE_VERSION"
60+
echo "prerelease=$PRERELEASE"
61+
} >> "$GITHUB_OUTPUT"
62+
63+
- name: Build source release tarball
64+
id: src
65+
run: |
66+
set -euo pipefail
67+
BASE_VERSION="${{ steps.meta.outputs.base_version }}"
68+
NAME="${ARTIFACT_PREFIX}-${BASE_VERSION}-incubating-src"
69+
70+
git archive --format=tar.gz --prefix="${NAME}/" -o "${NAME}.tar.gz" "${{ steps.meta.outputs.tag }}"
71+
sha512sum "${NAME}.tar.gz" > "${NAME}.tar.gz.sha512"
72+
73+
echo "name=$NAME" >> "$GITHUB_OUTPUT"
74+
75+
- name: Create GitHub release
76+
env:
77+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
78+
run: |
79+
set -euo pipefail
80+
NAME="${{ steps.src.outputs.name }}"
81+
ARGS=(--title "${{ steps.meta.outputs.tag }}" --generate-notes)
82+
if [[ "${{ steps.meta.outputs.prerelease }}" == "true" ]]; then
83+
ARGS+=(--prerelease)
84+
fi
85+
gh release create "${{ steps.meta.outputs.tag }}" "${ARGS[@]}" \
86+
"${NAME}.tar.gz" "${NAME}.tar.gz.sha512"
87+
88+
publish:
89+
# Only a final tag (no -rc) goes to the package registry.
90+
needs: [release]
91+
if: needs.release.outputs.prerelease == 'false'
92+
runs-on: ubuntu-latest
93+
steps:
94+
- uses: actions/checkout@v4
95+
96+
- uses: actions/setup-node@v4
97+
with:
98+
node-version: '22'
99+
registry-url: 'https://registry.npmjs.org'
100+
101+
- run: yarn install
102+
103+
# `prepack` runs lint + test + build, so the published tarball is built here.
104+
- run: npm publish --access public
105+
env:
106+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.releaserc.json

Lines changed: 0 additions & 9 deletions
This file was deleted.

package.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,11 @@
2222
"test": "jest",
2323
"lint": "eslint . --ext .js,.ts",
2424
"fmt": "eslint . --ext .js,.ts --fix",
25-
"semantic-release": "semantic-release",
2625
"commit": "git-cz",
2726
"clean": "rimraf lib",
2827
"coverage": "jest --coverage"
2928
},
3029
"devDependencies": {
31-
"@semantic-release/commit-analyzer": "^8.0.1",
32-
"@semantic-release/github": "^7.2.3",
33-
"@semantic-release/npm": "^7.1.3",
34-
"@semantic-release/release-notes-generator": "^9.0.3",
3530
"@types/jest": "^26.0.20",
3631
"@types/node": "^10.5.3",
3732
"@types/picomatch": "^2.2.2",
@@ -48,7 +43,6 @@
4843
"prettier": "^2.2.1",
4944
"pretty-quick": "^3.1.0",
5045
"rimraf": "^3.0.2",
51-
"semantic-release": "^17.4.4",
5246
"ts-jest": "^26.5.3",
5347
"tslint": "^5.11.0",
5448
"tsup": "^8.5.1",

src/enforcer.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -294,11 +294,43 @@ export class Enforcer extends ManagementEnforcer {
294294
* getPermissionsForUser gets permissions for a user or role.
295295
*
296296
* @param user the user.
297+
* @param domain the domain, optional. When given, only the permissions of that domain are returned.
297298
* @return the permissions, a permission is usually like (obj, act). It is actually the rule without the subject.
298299
*/
299-
public async getPermissionsForUser(user: string): Promise<string[][]> {
300-
const subIndex = this.getFieldIndex('p', FieldIndex.Subject);
301-
return this.getFilteredPolicy(subIndex, user);
300+
public async getPermissionsForUser(user: string, ...domain: string[]): Promise<string[][]> {
301+
return this.getNamedPermissionsForUser('p', user, ...domain);
302+
}
303+
304+
/**
305+
* getNamedPermissionsForUser gets permissions for a user or role by the named policy.
306+
*
307+
* @param ptype the policy type, can be "p", "p2", "p3", ..
308+
* @param user the user.
309+
* @param domain the domain, optional. When given, only the permissions of that domain are returned.
310+
* @return the permissions, a permission is usually like (obj, act). It is actually the rule without the subject.
311+
*/
312+
public async getNamedPermissionsForUser(ptype: string, user: string, ...domain: string[]): Promise<string[][]> {
313+
const subIndex = this.getFieldIndex(ptype, FieldIndex.Subject);
314+
if (subIndex === -1) {
315+
return [];
316+
}
317+
if (domain.length === 0) {
318+
return this.getFilteredNamedPolicy(ptype, subIndex, user);
319+
}
320+
321+
// The domain is not necessarily the token right after the subject, so it has to be
322+
// looked up in the model instead of being assumed to sit at a fixed index.
323+
const domIndex = this.getFieldIndex(ptype, FieldIndex.Domain);
324+
if (domIndex === -1) {
325+
return this.getFilteredNamedPolicy(ptype, subIndex, user);
326+
}
327+
328+
const start = Math.min(subIndex, domIndex);
329+
// "" means not to match that field.
330+
const fieldValues = new Array<string>(Math.abs(subIndex - domIndex) + 1).fill('');
331+
fieldValues[subIndex - start] = user;
332+
fieldValues[domIndex - start] = domain[0];
333+
return this.getFilteredNamedPolicy(ptype, start, ...fieldValues);
302334
}
303335

304336
/**
@@ -357,16 +389,10 @@ export class Enforcer extends ManagementEnforcer {
357389
const roles = await this.getImplicitRolesForUser(user, ...domain);
358390
roles.unshift(user);
359391
const res: string[][] = [];
360-
const withDomain = domain && domain.length !== 0;
361392

362393
for (const n of roles) {
363-
if (withDomain) {
364-
const p = await this.getFilteredPolicy(0, n, ...domain);
365-
res.push(...p);
366-
} else {
367-
const p = await this.getPermissionsForUser(n);
368-
res.push(...p);
369-
}
394+
const p = await this.getPermissionsForUser(n, ...domain);
395+
res.push(...p);
370396
}
371397

372398
return res;

0 commit comments

Comments
 (0)