Skip to content

Commit 0fc39ef

Browse files
committed
feat: generator
1 parent 1da57e5 commit 0fc39ef

File tree

6 files changed

+3865
-1
lines changed

6 files changed

+3865
-1
lines changed

.github/workflows/auto-release.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ on:
44
push:
55
branches:
66
- main
7+
paths:
8+
- 'permify/**'
9+
- 'test/**'
10+
- 'docs/**'
11+
- 'requirements.txt'
12+
- 'setup.py'
13+
- 'pyproject.toml'
714

815
permissions:
916
contents: write

.github/workflows/generator.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# This workflow generates the Python SDK from the Permify OpenAPI specification
2+
# It fetches the latest openapi.json from the Permify repository and runs the SDK generation script
3+
4+
name: Generate Python SDK
5+
6+
on:
7+
workflow_dispatch:
8+
push:
9+
paths:
10+
- 'generator/**'
11+
- '.github/workflows/generator.yml'
12+
13+
jobs:
14+
generate:
15+
name: Generate SDK from OpenAPI
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
token: ${{ secrets.GITHUB_TOKEN }}
21+
22+
- name: Download OpenAPI spec from Permify repository
23+
run: |
24+
echo "Downloading latest OpenAPI specification from Permify repository..."
25+
curl -L -o generator/openapi.json https://raw.githubusercontent.com/Permify/permify/master/docs/api-reference/openapiv2/apidocs.swagger.json
26+
27+
- name: Check if OpenAPI spec has changed
28+
id: check_changes
29+
run: |
30+
if git diff --quiet generator/openapi.json; then
31+
echo "No changes in OpenAPI specification"
32+
echo "changed=false" >> $GITHUB_OUTPUT
33+
else
34+
echo "OpenAPI specification has changed"
35+
echo "changed=true" >> $GITHUB_OUTPUT
36+
fi
37+
38+
- name: Make generate script executable
39+
if: steps.check_changes.outputs.changed == 'true'
40+
run: chmod +x generator/generate-sdk.sh
41+
42+
- name: Setup Java
43+
if: steps.check_changes.outputs.changed == 'true'
44+
uses: actions/setup-java@v4
45+
with:
46+
distribution: 'temurin'
47+
java-version: '11'
48+
49+
- name: Generate Python SDK
50+
if: steps.check_changes.outputs.changed == 'true'
51+
run: |
52+
cd generator
53+
./generate-sdk.sh
54+
55+
- name: Configure Git
56+
if: steps.check_changes.outputs.changed == 'true'
57+
run: |
58+
git config --global user.name "Permify GitHub Actions"
59+
git config --global user.email "<>"
60+
61+
- name: Create Pull Request
62+
if: steps.check_changes.outputs.changed == 'true'
63+
uses: peter-evans/create-pull-request@v5
64+
with:
65+
token: ${{ secrets.PAT_TOKEN }}
66+
commit-message: "chore: update Python SDK from latest OpenAPI specification"
67+
title: "chore: update Python SDK from latest OpenAPI specification"
68+
body: |
69+
This PR updates the Python SDK based on the latest OpenAPI specification from the Permify repository.
70+
71+
## Changes
72+
- Updated OpenAPI specification
73+
- Regenerated Python SDK code
74+
- Updated documentation
75+
- Updated package configuration (setup.py, pyproject.toml)
76+
77+
This is an automated update generated by the SDK generator workflow.
78+
branch: update-sdk-from-openapi
79+
delete-branch: true
80+

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,5 @@ cython_debug/
157157
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158158
# and can be added to the global gitignore or merged into this file. For a more nuclear
159159
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
160-
.idea/
160+
.idea/
161+
*.bak

generator/generate-sdk.sh

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6+
PROJECT_ROOT="${SCRIPT_DIR}/.."
7+
DEFAULT_OPENAPI_FILE="${SCRIPT_DIR}/openapi.json"
8+
DEFAULT_PACKAGE_NAME="permify"
9+
DEFAULT_CLIENT_NAME="PermifyClient"
10+
11+
usage() {
12+
echo "Usage: $0 [OPTIONS]"
13+
echo ""
14+
echo "Generate Python SDK from OpenAPI specification and update project directories"
15+
echo ""
16+
echo "Options:"
17+
echo " -i, --input FILE OpenAPI JSON file (default: ${DEFAULT_OPENAPI_FILE})"
18+
echo " -p, --package NAME Python package name (default: ${DEFAULT_PACKAGE_NAME})"
19+
echo " -c, --client NAME Client class name (default: ${DEFAULT_CLIENT_NAME})"
20+
echo " -h, --help Show this help message"
21+
echo ""
22+
echo "This script will update the following:"
23+
echo " - ../permify (generated Python package)"
24+
echo " - ../docs (API documentation)"
25+
echo " - ../test (generated tests)"
26+
echo " - ../setup.py (package metadata and dependencies)"
27+
echo " - ../pyproject.toml (package metadata and dependencies)"
28+
echo ""
29+
echo "Examples:"
30+
echo " $0 # Use defaults"
31+
echo " $0 -i swagger.json # Custom input file"
32+
echo " $0 -p custom_package # Custom package name"
33+
}
34+
35+
OPENAPI_FILE="${DEFAULT_OPENAPI_FILE}"
36+
PACKAGE_NAME="${DEFAULT_PACKAGE_NAME}"
37+
CLIENT_NAME="${DEFAULT_CLIENT_NAME}"
38+
39+
while [[ $# -gt 0 ]]; do
40+
case $1 in
41+
-i|--input)
42+
OPENAPI_FILE="$2"
43+
shift 2
44+
;;
45+
-p|--package)
46+
PACKAGE_NAME="$2"
47+
shift 2
48+
;;
49+
-c|--client)
50+
CLIENT_NAME="$2"
51+
shift 2
52+
;;
53+
-h|--help)
54+
usage
55+
exit 0
56+
;;
57+
*)
58+
echo "Unknown option: $1"
59+
usage
60+
exit 1
61+
;;
62+
esac
63+
done
64+
65+
if [[ ! -f "${OPENAPI_FILE}" ]]; then
66+
echo "Error: OpenAPI file '${OPENAPI_FILE}' not found"
67+
exit 1
68+
fi
69+
70+
# Check if Java is available
71+
if ! command -v java &> /dev/null; then
72+
echo "Error: Java is required but not installed"
73+
exit 1
74+
fi
75+
76+
TEMP_OUTPUT_DIR=$(mktemp -d)
77+
trap 'rm -rf "${TEMP_OUTPUT_DIR}"' EXIT
78+
79+
OPENAPI_ABSOLUTE_PATH=$(realpath "${OPENAPI_FILE}")
80+
81+
OPENAPI_VERSION=$(grep -o '"version": *"[^"]*"' "${OPENAPI_FILE}" | cut -d '"' -f 4)
82+
if [[ -z "${OPENAPI_VERSION}" ]]; then
83+
echo "Error: Could not extract version from OpenAPI file"
84+
exit 1
85+
fi
86+
87+
echo "Generating Python SDK..."
88+
echo " OpenAPI file: ${OPENAPI_ABSOLUTE_PATH}"
89+
echo " OpenAPI version: ${OPENAPI_VERSION}"
90+
echo " Package name: ${PACKAGE_NAME}"
91+
echo " Client name: ${CLIENT_NAME}"
92+
echo " Temp directory: ${TEMP_OUTPUT_DIR}"
93+
echo ""
94+
95+
# Download OpenAPI Generator CLI JAR if not present
96+
GENERATOR_JAR="${SCRIPT_DIR}/openapi-generator-cli.jar"
97+
if [[ ! -f "${GENERATOR_JAR}" ]]; then
98+
echo "Downloading OpenAPI Generator CLI..."
99+
curl -L -o "${GENERATOR_JAR}" https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.2.0/openapi-generator-cli-7.2.0.jar
100+
fi
101+
102+
# Generate SDK using OpenAPI Generator CLI
103+
java -jar "${GENERATOR_JAR}" generate \
104+
-i "${OPENAPI_ABSOLUTE_PATH}" \
105+
-g python \
106+
-o "${TEMP_OUTPUT_DIR}" \
107+
--package-name="${PACKAGE_NAME}" \
108+
--additional-properties=packageName="${PACKAGE_NAME}" \
109+
--additional-properties=clientPackage="${PACKAGE_NAME}" \
110+
--additional-properties=projectName="${PACKAGE_NAME}" \
111+
--additional-properties=packageUrl="https://github.com/Permify/permify-python" \
112+
--additional-properties=packageVersion="${OPENAPI_VERSION}" \
113+
--additional-properties=packageDescription="""Permify is an open source authorization service for creating fine-grained and scalable authorization systems.""" \
114+
--additional-properties=library=urllib3 \
115+
--additional-properties=hideGenerationTimestamp=true \
116+
--additional-properties=generateSourceCodeOnly=false \
117+
--additional-properties=licenseName="Apache-2.0" \
118+
--skip-validate-spec
119+
120+
if [[ $? -ne 0 ]]; then
121+
echo ""
122+
echo "❌ Failed to generate Python SDK"
123+
exit 1
124+
fi
125+
126+
echo "Updating project directories..."
127+
128+
# Update the main package directory
129+
PACKAGE_DIR="${PROJECT_ROOT}/${PACKAGE_NAME}"
130+
if [[ -d "${TEMP_OUTPUT_DIR}/${PACKAGE_NAME}" ]]; then
131+
echo " Updating ${PACKAGE_DIR}"
132+
# Backup any custom files that shouldn't be overwritten
133+
if [[ -f "${PACKAGE_DIR}/py.typed" ]]; then
134+
cp "${PACKAGE_DIR}/py.typed" "${TEMP_OUTPUT_DIR}/${PACKAGE_NAME}/py.typed"
135+
fi
136+
137+
rm -rf "${PACKAGE_DIR}"
138+
cp -r "${TEMP_OUTPUT_DIR}/${PACKAGE_NAME}" "${PACKAGE_DIR}"
139+
fi
140+
141+
# Update documentation
142+
DOCS_DIR="${PROJECT_ROOT}/docs"
143+
if [[ -d "${TEMP_OUTPUT_DIR}/docs" ]]; then
144+
echo " Updating ${DOCS_DIR}"
145+
rm -rf "${DOCS_DIR}"/*.md
146+
mkdir -p "${DOCS_DIR}"
147+
cp "${TEMP_OUTPUT_DIR}/docs/"*.md "${DOCS_DIR}/"
148+
fi
149+
150+
# Update tests
151+
TEST_DIR="${PROJECT_ROOT}/test"
152+
if [[ -d "${TEMP_OUTPUT_DIR}/test" ]]; then
153+
echo " Updating ${TEST_DIR}"
154+
rm -rf "${TEST_DIR}"
155+
mkdir -p "${TEST_DIR}"
156+
cp -r "${TEMP_OUTPUT_DIR}/test/"* "${TEST_DIR}/"
157+
fi
158+
159+
# Function to update setup.py with repository information
160+
update_setup_py() {
161+
local generated_setup="${TEMP_OUTPUT_DIR}/setup.py"
162+
local target_setup="${PROJECT_ROOT}/setup.py"
163+
164+
if [[ ! -f "${generated_setup}" ]]; then
165+
echo " ⚠️ Warning: Generated setup.py not found, skipping update"
166+
return
167+
fi
168+
169+
echo " Updating setup.py"
170+
171+
# Create a backup
172+
if [[ -f "${target_setup}" ]]; then
173+
cp "${target_setup}" "${target_setup}.bak"
174+
fi
175+
176+
# Directly copy the generated setup.py without any modifications
177+
cp "${generated_setup}" "${target_setup}"
178+
179+
echo " ✅ Updated setup.py"
180+
}
181+
182+
# Function to update pyproject.toml
183+
update_pyproject_toml() {
184+
local target_pyproject="${PROJECT_ROOT}/pyproject.toml"
185+
186+
if [[ ! -f "${target_pyproject}" ]]; then
187+
echo " ⚠️ Warning: pyproject.toml not found, skipping update"
188+
return
189+
fi
190+
191+
echo " Updating pyproject.toml version"
192+
193+
# Strip 'v' prefix from version if present
194+
VERSION_WITHOUT_V="${OPENAPI_VERSION#v}"
195+
196+
# Update version in pyproject.toml
197+
if [[ "$OSTYPE" == "darwin"* ]]; then
198+
sed -i '' "s/^version = \"[^\"]*\"/version = \"${VERSION_WITHOUT_V}\"/" "${target_pyproject}"
199+
else
200+
sed -i "s/^version = \"[^\"]*\"/version = \"${VERSION_WITHOUT_V}\"/" "${target_pyproject}"
201+
fi
202+
203+
echo " ✅ Updated pyproject.toml version to ${VERSION_WITHOUT_V}"
204+
}
205+
206+
# Function to extract and update requirements
207+
update_requirements() {
208+
local generated_requirements="${TEMP_OUTPUT_DIR}/requirements.txt"
209+
local target_requirements="${PROJECT_ROOT}/requirements.txt"
210+
211+
if [[ -f "${generated_requirements}" ]] && [[ -f "${target_requirements}" ]]; then
212+
echo " Updating requirements.txt"
213+
214+
# Create backup
215+
cp "${target_requirements}" "${target_requirements}.bak"
216+
217+
# Extract non-dev requirements from generated file
218+
grep -v "pytest\|tox\|flake8" "${generated_requirements}" > "${target_requirements}" || true
219+
220+
echo " ✅ Updated requirements.txt"
221+
fi
222+
}
223+
224+
# Update package files
225+
update_setup_py
226+
update_pyproject_toml
227+
update_requirements
228+
229+
echo ""
230+
echo "✅ Python SDK updated successfully!"
231+
echo "📁 Updated directories:"
232+
echo " - ${PACKAGE_DIR}"
233+
echo " - ${DOCS_DIR}"
234+
echo " - ${TEST_DIR}"
235+
echo "📝 Updated version to ${VERSION_WITHOUT_V}"
236+
echo "🔗 Updated package configuration in:"
237+
echo " - setup.py"
238+
echo " - pyproject.toml"
239+
echo " - requirements.txt"
25.8 MB
Binary file not shown.

0 commit comments

Comments
 (0)