Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Auto Release

on:
workflow_dispatch:
push:
branches:
- main
paths:
- '.openapi-generator/**'
- 'docs/**'
- 'src/**'
- 'test/**'
- 'package.json'
- 'README.md'

permissions:
contents: write

jobs:
release:
name: Create SDK Release
timeout-minutes: 10
runs-on: ubuntu-latest

steps:
- name: Harden Runner
uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
with:
egress-policy: audit

- name: Checkout repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0

- name: Create tag and release
env:
GH_TOKEN: ${{ secrets.PAT_TOKEN }}
run: |
PACKAGE_VERSION="$(sed -n 's/^[[:space:]]*"version":[[:space:]]*"\([^"]*\)".*/\1/p' package.json | head -n 1)"
OPENAPI_VERSION="$(sed -n 's/.*"version":[[:space:]]*"\([^"]*\)".*/\1/p' generator/openapi.json | head -n 1)"
OPENAPI_PACKAGE_VERSION="${OPENAPI_VERSION#v}"

if [ -z "${PACKAGE_VERSION}" ]; then
echo "Package version is empty. Skipping release creation."
exit 0
fi

if [ -n "${OPENAPI_PACKAGE_VERSION}" ] && [ "${PACKAGE_VERSION}" != "${OPENAPI_PACKAGE_VERSION}" ]; then
echo "Package version (${PACKAGE_VERSION}) does not match OpenAPI version (${OPENAPI_PACKAGE_VERSION}). Skipping release creation."
exit 0
fi

TAG_NAME="v${PACKAGE_VERSION}"

if git rev-parse -q --verify "refs/tags/${TAG_NAME}" >/dev/null; then
echo "Tag ${TAG_NAME} already exists. Skipping release creation."
exit 0
fi

echo "Creating release ${TAG_NAME}"
git config --global user.name "GitHub Actions Bot"
git config --global user.email "<>"
git tag -a "${TAG_NAME}" -m "Release ${TAG_NAME}"
git push origin "${TAG_NAME}"

gh release create "${TAG_NAME}" \
--repo "${GITHUB_REPOSITORY}" \
--title "${TAG_NAME}" \
--generate-notes
24 changes: 23 additions & 1 deletion .github/workflows/generator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,23 @@ jobs:
distribution: temurin
java-version: 17

- name: Setup Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 20

# Generate the SDK
- name: Generate JavaScript SDK
run: |
chmod +x generator/generate-sdk.sh
generator/generate-sdk.sh

- name: Install dependencies
run: npm install --no-package-lock

- name: Run smoke tests
run: npm test

# Commit changes and open PR if there are changes
- name: Commit changes
id: commitchanges
Expand All @@ -68,6 +79,17 @@ jobs:
if [ -n "${PR_NUMBER}" ]; then
gh pr edit "${PR_NUMBER}" --title "${PR_TITLE}" --body "${PR_BODY}"
else
gh pr create --base main --head "${BRANCH_NAME}" --title "${PR_TITLE}" --body "${PR_BODY}" --label dependencies --label automated
CREATE_ARGS=(--base main --head "${BRANCH_NAME}" --title "${PR_TITLE}" --body "${PR_BODY}")
LABELS="$(gh label list --json name --jq '.[].name' || true)"

if printf '%s\n' "${LABELS}" | grep -qx 'dependencies'; then
CREATE_ARGS+=(--label dependencies)
fi

if printf '%s\n' "${LABELS}" | grep -qx 'automated'; then
CREATE_ARGS+=(--label automated)
fi

gh pr create "${CREATE_ARGS[@]}"
fi
shell: bash
5 changes: 4 additions & 1 deletion .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ jobs:
registry-url: "https://registry.npmjs.org"

- name: Install dependencies
run: npm install
run: npm install --no-package-lock

- name: Build
run: npm run build

- name: Run smoke tests
run: npm test

- name: Write release version
run: |
VERSION=${GITHUB_REF_NAME#v}
Expand Down
7 changes: 7 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
permify:
image: "ghcr.io/permify/permify:v1.6.9"
ports:
- "3476:3476"
- "3478:3478"
command: "serve"
7 changes: 4 additions & 3 deletions generator/generate-sdk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${SCRIPT_DIR}/.."
OPENAPI_FILE="${SCRIPT_DIR}/openapi.json"
GENERATOR_VERSION="7.13.0"
PACKAGE_VERSION="$(sed -n 's/^[[:space:]]*"version":[[:space:]]*"\([^"]*\)".*/\1/p' "${PROJECT_ROOT}/package.json" | head -n 1)"
OPENAPI_VERSION="$(sed -n 's/.*"version":[[:space:]]*"\([^"]*\)".*/\1/p' "${OPENAPI_FILE}" | head -n 1)"
PACKAGE_VERSION="${OPENAPI_VERSION#v}"

if [[ -z "${PACKAGE_VERSION}" ]]; then
echo "Could not determine package version from ${PROJECT_ROOT}/package.json" >&2
if [[ -z "${OPENAPI_VERSION}" || -z "${PACKAGE_VERSION}" ]]; then
echo "Could not determine package version from ${OPENAPI_FILE}" >&2
exit 1
fi

Expand Down
139 changes: 139 additions & 0 deletions integration/live.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import assert from 'assert';
import * as PermifyApi from '../src/index';

const PERMIFY_BASE_URL = process.env.PERMIFY_BASE_URL || 'http://127.0.0.1:3476';
const TENANT_ID = 't1';
const RUN_ID = Date.now().toString(36);

function createApis() {
const apiClient = new PermifyApi.ApiClient(PERMIFY_BASE_URL);
apiClient.timeout = 10000;

return {
schema: new PermifyApi.SchemaApi(apiClient),
data: new PermifyApi.DataApi(apiClient),
permission: new PermifyApi.PermissionApi(apiClient),
};
}

describe('Permify live REST tests', function() {
this.timeout(20000);

it('denies a permission check when no relationship exists', async function() {
const apis = createApis();
const documentId = `denieddoc${RUN_ID}`;
const subjectId = `denieduser${RUN_ID}`;
const schema = `
entity user {}

entity document {
relation viewer @user

action view = viewer
}
`;

const schemaWrite = await apis.schema.schemasWrite(TENANT_ID, {
schema,
});

const check = await apis.permission.permissionsCheck(TENANT_ID, {
metadata: {
snap_token: '',
schema_version: schemaWrite.schema_version,
depth: 20,
},
entity: {
type: 'document',
id: documentId,
},
permission: 'view',
subject: {
type: 'user',
id: subjectId,
},
});

assert.strictEqual(check.can, 'CHECK_RESULT_DENIED');
});

it('looks up entities a subject can view', async function() {
const apis = createApis();
const subjectId = `lookupuser${RUN_ID}`;
const expectedEntityIds = [
`lookupdoca${RUN_ID}`,
`lookupdocb${RUN_ID}`,
`lookupdocc${RUN_ID}`,
];
const schema = `
entity user {}

entity document {
relation viewer @user

action view = viewer
}
`;

const schemaWrite = await apis.schema.schemasWrite(TENANT_ID, {
schema,
});

const dataWrite = await apis.data.dataWrite(TENANT_ID, {
metadata: {
schema_version: schemaWrite.schema_version,
},
tuples: [
{
entity: {
type: 'document',
id: expectedEntityIds[0],
},
relation: 'viewer',
subject: {
type: 'user',
id: subjectId,
},
},
{
entity: {
type: 'document',
id: expectedEntityIds[1],
},
relation: 'viewer',
subject: {
type: 'user',
id: subjectId,
},
},
{
entity: {
type: 'document',
id: expectedEntityIds[2],
},
relation: 'viewer',
subject: {
type: 'user',
id: subjectId,
},
},
],
});

const lookup = await apis.permission.permissionsLookupEntity(TENANT_ID, {
metadata: {
snap_token: dataWrite.snap_token,
schema_version: schemaWrite.schema_version,
depth: 20,
},
entity_type: 'document',
permission: 'view',
subject: {
type: 'user',
id: subjectId,
},
});

assert.deepStrictEqual(lookup.entity_ids.sort(), expectedEntityIds.sort());
});
});
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"scripts": {
"build": "babel src -d dist",
"prepare": "npm run build",
"test": "mocha --require @babel/register --recursive"
"test": "mocha --require @babel/register --recursive",
"test:live": "mocha --require @babel/register integration/**/*.spec.js",
"run-live-tests": "./scripts/run-live-tests.sh",
"run-instance": "./scripts/run-live-tests.sh"
},
"browser": {
"fs": false
Expand Down
2 changes: 1 addition & 1 deletion scripts/commit-changes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -euo pipefail

branch_name="${1:?branch name is required}"

if git diff --quiet; then
if [[ -z "$(git status --porcelain)" ]]; then
echo "changes_made=0" >> "${GITHUB_OUTPUT}"
echo "No changes detected"
exit 0
Expand Down
29 changes: 29 additions & 0 deletions scripts/run-live-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
COMPOSE_FILE="${ROOT_DIR}/docker-compose.yaml"
PERMIFY_BASE_URL="${PERMIFY_BASE_URL:-http://127.0.0.1:3476}"

cleanup() {
docker compose -f "${COMPOSE_FILE}" down -v >/dev/null 2>&1 || true
}

trap cleanup EXIT

cd "${ROOT_DIR}"

docker compose -f "${COMPOSE_FILE}" up -d

for attempt in {1..60}; do
if curl -s -o /dev/null "${PERMIFY_BASE_URL}/healthz"; then
npm run test:live
exit 0
fi

sleep 1
done

echo "Permify did not become reachable at ${PERMIFY_BASE_URL} within 60 seconds." >&2
exit 1