diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 0000000..5d53bff --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,58 @@ +name: Bench Build Test + +on: + pull_request: + +concurrency: + group: ${{ github.repository }}-${{ github.event.number }} + cancel-in-progress: true + +jobs: + Bench-Build-Test: + runs-on: ubuntu-latest + container: + image: docker.io/frappe/bench:latest + options: --user root + + steps: + - name: Setup Github ENV + run: | + echo "HOME=/home/frappe" >> $GITHUB_ENV + echo "PATH=/home/frappe/.local/bin:$PATH" >> $GITHUB_ENV + + - name: Create a new minimal bench + run: | + cd /home/frappe + su frappe bash -c "bench init frappe-bench --skip-redis-config-generation --no-procfile --skip-assets" + + - name: Get Dependent Apps + run: | + cd /home/frappe/frappe-bench + # Use public URL for public repos, authenticated URL for private repos + if [ "${{ github.event.pull_request.head.repo.private }}" = "false" ]; then + # This is a public repository (could be a fork or not) + git clone https://github.com/${{ github.event.pull_request.head.repo.full_name }} -b ${{ github.event.pull_request.head.ref }} --depth=1 app_repo + else + # Private repository, use authentication + git clone https://rtbot:${{ secrets.RTBOT_TOKEN }}@github.com/${{ github.event.pull_request.head.repo.full_name }} -b ${{ github.event.pull_request.head.ref }} --depth=1 app_repo + fi + DEPS=$(grep -E "required_apps\s*=\s*\[" app_repo/*/hooks.py | sed 's/.*\[\(.*\)\]/\1/g' | tr -d '"' | tr -d "'" | tr ',' '\n' | awk '{$1=$1};1') + rm -rf app_repo + for dep in $DEPS; do + su frappe bash -c "bench get-app $dep" + done + + - name: Get APP and Build + run: | + cd /home/frappe/frappe-bench + if [ "${{ github.event.pull_request.head.repo.private }}" = "false" ]; then + # Public fork + su frappe bash -c "bench get-app https://github.com/${{ github.event.pull_request.head.repo.full_name }} --branch ${{ github.event.pull_request.head.ref }}" + else + # Private fork (requires token) + su frappe bash -c "bench get-app https://rtbot:${{ secrets.RTBOT_TOKEN }}@github.com/${{ github.event.pull_request.head.repo.full_name }} --branch ${{ github.event.pull_request.head.ref }}" + fi + + - name: Cleanup + if: ${{ always() }} + uses: rtCamp/action-cleanup@master \ No newline at end of file diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml new file mode 100644 index 0000000..df18c08 --- /dev/null +++ b/.github/workflows/gitleaks.yml @@ -0,0 +1,26 @@ +name: Gitleaks + +on: + push: + branches: + - version-16 + - version-16-hotfix + pull_request: + branches: + - version-16 + - version-16-hotfix + +jobs: + gitleaks: + name: Gitleaks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Run Gitleaks + uses: gitleaks/gitleaks-action@v3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml new file mode 100644 index 0000000..ece57ff --- /dev/null +++ b/.github/workflows/linters.yml @@ -0,0 +1,52 @@ +name: Linters + +on: + pull_request: + workflow_dispatch: +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + pre-commit: + name: "Frappe Linter" + runs-on: ubuntu-latest + container: + image: alpine:latest # latest used here for simplicity, not recommended + defaults: + run: + shell: sh + steps: + - name: fix tar dependency in alpine container image + run: | + apk --no-cache add tar nodejs npm python3 git bash py3-pip + npm install -g prettier + # check python modules installed versions + python3 -m pip freeze --local + pip install pre-commit --break-system-packages + + - uses: actions/checkout@v6 + - run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* + + - name: Get changed files + id: file_changes + run: | + export DIFF=$(git diff --name-only origin/${{ github.base_ref }} ${{ github.sha }}) + echo "Diff between ${{ github.base_ref }} and ${{ github.sha }}" + echo "files=$( echo "$DIFF" | xargs echo )" >> $GITHUB_OUTPUT + + + - name: Cache pre-commit since we use pre-commit from container + uses: actions/cache@v5 + with: + path: ~/.cache/pre-commit + key: pre-commit-3|${{ hashFiles('.pre-commit-config.yaml') }} + + - name: Execute pre-commit + run: | + pre-commit run --color=always --show-diff-on-failure --files ${{ steps.file_changes.outputs.files }} diff --git a/.github/workflows/semantic-commits.yml b/.github/workflows/semantic-commits.yml new file mode 100644 index 0000000..577c9b5 --- /dev/null +++ b/.github/workflows/semantic-commits.yml @@ -0,0 +1,28 @@ +name: Semantic Commits + +on: + pull_request: + +jobs: + commitlint: + name: Semantic Commits + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install commitlint + run: npm install --no-save @commitlint/cli @commitlint/config-conventional + + - name: Check commit titles + run: >- + npx commitlint --verbose + --from ${{ github.event.pull_request.base.sha }} + --to ${{ github.event.pull_request.head.sha }} diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..bd5cebc --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,25 @@ +module.exports = { + parserPreset: "conventional-changelog-conventionalcommits", + rules: { + "subject-empty": [2, "never"], + "type-case": [2, "always", "lower-case"], + "type-empty": [2, "never"], + "type-enum": [ + 2, + "always", + [ + "build", + "chore", + "ci", + "docs", + "feat", + "fix", + "perf", + "refactor", + "revert", + "style", + "test", + ], + ], + }, +}; diff --git a/eslint.config.js b/eslint.config.js index b8404cb..a3f075e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -5,4 +5,4 @@ export default [ sourceType: "module", }, }, -]; \ No newline at end of file +]; diff --git a/frappe_openapi/frappe_openapi/generate_api_docs.py b/frappe_openapi/frappe_openapi/generate_api_docs.py index 5a4663d..4f02ae5 100644 --- a/frappe_openapi/frappe_openapi/generate_api_docs.py +++ b/frappe_openapi/frappe_openapi/generate_api_docs.py @@ -59,7 +59,7 @@ def extract_returns_from_docstring(docstring): def parse_functions_from_file(file_path): - with open(file_path, encoding="utf-8") as f: + with open(file_path, encoding="utf-8") as f: # nosemgrep schema is in json file which needs to be read. tree = ast.parse(f.read(), filename=file_path) return [ { @@ -193,7 +193,7 @@ def generate_openapi_for_all_apps(): openapi["info"]["version"] = app_version output_file = os.path.join(public_folder, f"openapi_{app_name}.json") try: - with open(output_file, "w", encoding="utf-8") as f: + with open(output_file, "w", encoding="utf-8") as f: # nosemgrep schema needs to be written. json.dump(openapi, f, indent=2) update_progress_bar("Generating OpenAPI spec", i, total) except Exception as e: