Skip to content

Commit 8dd877b

Browse files
committed
init
0 parents  commit 8dd877b

33 files changed

+35109
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Run OAS API Tests (Vitest)
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
api_base_url:
7+
description: 'Base URL for the API'
8+
required: false
9+
default: ''
10+
debug_mode:
11+
description: 'Enable debug mode (true/false)'
12+
required: false
13+
default: 'false'
14+
default_x_data_source:
15+
description: 'Default value for the X-Data-Source header'
16+
required: false
17+
default: 'test'
18+
default_x_branch:
19+
description: 'Default value for the X-Branch header'
20+
required: false
21+
default: 'staging'
22+
pull_request:
23+
branches:
24+
- main
25+
- staging
26+
- prod
27+
push:
28+
branches:
29+
- main
30+
- staging
31+
- prod
32+
- dev
33+
34+
jobs:
35+
run-tests:
36+
runs-on: ubuntu-latest
37+
38+
steps:
39+
- name: Checkout code
40+
uses: actions/checkout@v4
41+
42+
- name: Set up Node.js
43+
uses: actions/setup-node@v4
44+
with:
45+
node-version: 'latest'
46+
47+
- name: Install dependencies
48+
run: npm install
49+
50+
- name: Run tests
51+
id: run-tests
52+
env:
53+
API_BASE_URL: ${{ github.event.inputs.api_base_url }}
54+
DEBUG_MODE: ${{ github.event.inputs.debug_mode }}
55+
DEFAULT_X_DATA_SOURCE: ${{ github.event.inputs.default_x_data_source }}
56+
DEFAULT_X_BRANCH: ${{ github.event.inputs.default_x_branch }}
57+
API_SPEC_TOKEN: ${{ secrets.API_SPEC_TOKEN }}
58+
DEMO_ADMIN_PASSWORD: ${{ secrets.DEMO_ADMIN_PASSWORD }}
59+
run: npm run test
60+
continue-on-error: true
61+
62+
- name: Upload Test Reports
63+
if: ${{ always() }}
64+
uses: actions/upload-artifact@v4
65+
with:
66+
name: test-reports-json
67+
path: reports/json/test-output.json
68+
retention-days: 30
69+
70+
- name: Upload JUnit Test Results
71+
if: ${{ always() }}
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: test-reports-junit
75+
path: reports/junit/test-results.xml
76+
retention-days: 30
77+
78+
- name: Fail run if tests failed
79+
if: ${{ steps.run-tests.conclusion == 'failure' }}
80+
run: |
81+
echo "Tests failed. Please check the test reports for details."
82+
exit 1

.github/workflows/sync-xano.yml

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
name: Sync from Xano
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
fromBranchName:
7+
description: 'From branch name'
8+
required: false
9+
default: 'dev'
10+
toBranchName:
11+
description: 'To branch'
12+
required: true
13+
default: 'prod'
14+
toBranchUrl:
15+
description: "GCP Signed URL for the 'to' branch"
16+
required: true
17+
actionType:
18+
description: "What is the action that happened, available options: 'merge', 'new'"
19+
required: true
20+
default: 'merge'
21+
type: choice
22+
options:
23+
- merge
24+
- new
25+
26+
permissions:
27+
contents: write
28+
pull-requests: write
29+
30+
jobs:
31+
merge:
32+
if: ${{ github.event.inputs.actionType == 'merge' }}
33+
runs-on: ubuntu-latest
34+
35+
steps:
36+
- name: Checkout repository
37+
uses: actions/checkout@v4
38+
39+
- name: Set up Node.js
40+
uses: actions/[email protected]
41+
with:
42+
node-version: 'latest'
43+
44+
- name: Install dependencies
45+
run: npm install
46+
47+
- name: Configure Git user
48+
run: |
49+
git config --global user.email "[email protected]"
50+
git config --global user.name "Tóth Mihály"
51+
52+
- name: Ensure target branch exists
53+
run: |
54+
git fetch origin
55+
if git ls-remote --exit-code origin ${{ github.event.inputs.toBranchName }}; then
56+
git checkout ${{ github.event.inputs.toBranchName }}
57+
git pull origin ${{ github.event.inputs.toBranchName }}
58+
else
59+
git checkout -b ${{ github.event.inputs.toBranchName }}
60+
git push origin ${{ github.event.inputs.toBranchName }}
61+
fi
62+
63+
- name: Fetch workspace schema for target branch
64+
env:
65+
BRANCH_NAME: ${{ github.event.inputs.toBranchName }}
66+
BRANCH_URL: ${{ github.event.inputs.toBranchUrl }}
67+
ACTION_TYPE: ${{ github.event.inputs.actionType }}
68+
USE_LOCAL_YAML: 'false'
69+
run: node src/index.js
70+
71+
- name: Clear the repo folder
72+
run: |
73+
rm -rf repo
74+
echo "Cleared the repo folder to ensure a clean state."
75+
76+
- name: Rebuild the repo folder
77+
env:
78+
BRANCH_NAME: ${{ github.event.inputs.toBranchName }}
79+
BRANCH_URL: ${{ github.event.inputs.toBranchUrl }}
80+
ACTION_TYPE: ${{ github.event.inputs.actionType }}
81+
USE_LOCAL_YAML: 'false'
82+
run: node src/index.js
83+
84+
- name: Commit and push changes to target branch
85+
run: |
86+
git add .
87+
git diff-index --quiet HEAD || git commit -m "Merge from ${{ github.event.inputs.fromBranchName }} to ${{ github.event.inputs.toBranchName }}"
88+
git push origin ${{ github.event.inputs.toBranchName }} || true
89+
90+
new:
91+
if: ${{ github.event.inputs.actionType == 'new' }}
92+
runs-on: ubuntu-latest
93+
94+
steps:
95+
- name: Checkout repository
96+
uses: actions/checkout@v4
97+
98+
- name: Set up Node.js
99+
uses: actions/[email protected]
100+
with:
101+
node-version: 'latest'
102+
103+
- name: Install dependencies
104+
run: npm install
105+
106+
- name: Configure Git user
107+
run: |
108+
git config --global user.email "[email protected]"
109+
git config --global user.name "Tóth Mihály"
110+
111+
- name: Create new branch and run syncing script
112+
env:
113+
BRANCH_NAME: ${{ github.event.inputs.toBranchName || 'prod' }}
114+
BRANCH_URL: ${{ github.event.inputs.toBranchUrl || '' }}
115+
ACTION_TYPE: ${{ github.event.inputs.actionType || 'new' }}
116+
USE_LOCAL_YAML: 'false'
117+
run: |
118+
git fetch origin
119+
if git ls-remote --exit-code origin ${{ github.event.inputs.toBranchName }}; then
120+
git checkout ${{ github.event.inputs.toBranchName }}
121+
git pull origin ${{ github.event.inputs.toBranchName }}
122+
else
123+
git checkout -b ${{ github.event.inputs.toBranchName }}
124+
fi
125+
node src/index.js
126+
git add .
127+
git diff-index --quiet HEAD || git commit -m "Initial commit for ${{ github.event.inputs.toBranchName }}"
128+
git push origin ${{ github.event.inputs.toBranchName }} || true

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Standalone files
2+
.env
3+
.workspace.yaml
4+
5+
# Generated folders:
6+
output/
7+
repo/
8+
reports/
9+
src/helpers/temp.dbml
10+
11+
# Node modules:
12+
node_modules/
13+
14+
# Input folders:
15+
yaml-files/
16+
17+
# Other
18+
debug_requests.json

README.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# xano-community-cli
2+
3+
**A tool to improve dev experience with XANO, especially for teams where clarity, transparency, and version control is important. Furthermore, this cli should help automate currently manual apsects of XANO. Why a CLI when we have AI? I am bullish on the AI, but in all honesty using AI so much without proper human control can cause a lot of issues. The idea behind this CLI is to reduce the need of reliance on AI and that we have our most crucial parts (testing, documentation) in place in any case, environment, system, either in part of a git provider or local system. The goal is to make it flexible and if there's need, then obiously LLM-ready.**
4+
_(Work In Progress)_
5+
6+
---
7+
8+
## 🚀 Quick Start
9+
10+
- Clone the repo
11+
- Run
12+
```
13+
pnpm install
14+
```
15+
- check the `src/config/xcc.config.js` file and adjust to your liking
16+
- place a workspace.yaml (downloaded and extracted from XANO Metadata API) into the path which you specified in the config.
17+
- run the default command to see available options
18+
19+
```
20+
pnpm run xano-community-cli
21+
```
22+
23+
- run the `process` to generate a 'repo' from your XANO workspace
24+
25+
```
26+
pnpm run xano-community-cli process
27+
```
28+
29+
- see the output in the path specified in your config.
30+
31+
---
32+
33+
## 🤔 Why converting to Repo-like structure instead of just XANO UI?
34+
35+
XANO visual UI is extremely helpful for the lesser technical people, who are willing to read through and click through each step.
36+
However, the UX of XANO in terms of navigating through each step and in the meantime potentially loosing context can become
37+
cumbersome in some more complex logic and make it more difficult to grasp what's going on.
38+
This is the reason why we try to traverse the XANO instance into a Github-like repo structure, which makes it
39+
much more consumable in Code editors and IDEs. This may also result with a much easier integration with LLMs, which tend to
40+
understand markdown or yaml (xanoscript) better than extremely verbose json objects.
41+
42+
---
43+
44+
### 🗂️ Structure of exports
45+
46+
- Each **`app`** in [`repo/`](repo/) is an API group (see [`repo/app/`](repo/app/)).
47+
- **Functions** (service-like logic) are in [`repo/function/`](repo/function).
48+
- Every major entity is parsed into its own path with a descriptive `.json` file and a README.
49+
50+
---
51+
52+
## 🚧 Status
53+
54+
> **WORK IN PROGRESS:**
55+
> Expect frequent changes!
56+
> - Main entities (queries, functions, tables) are now parsed into their own paths and documented.
57+
> - Plans to support dynamic setup
58+
> - !!! The Github Actions workflows are copies from our live system, so they are not at all refactored to this new cli-like repo. They depend on a much less clear and messy node script implementation that fetches workspace files from GCP and then processes them as Github Action.
59+
60+
---
61+
62+
## 📝 Notes
63+
64+
- We use **pnpm** for performance and disk efficiency.
65+
66+
---
67+
68+
## ✔️ What Works Now?
69+
70+
- [x] Linting with custom rulesets
71+
- [x] Processing Xano queries, functions, and tables into a browsable repo structure
72+
73+
---
74+
75+
## 🛠️ TODOs
76+
77+
- [X] Build Config file to configure non-secret configurations.
78+
- [X] Create the CLI command handler.
79+
- [ ] Add the automated testing also to the configurable features
80+
- [ ] Improve path handling (support custom output: `.zip`, directories, etc.)
81+
- [ ] Improve input handling (custom file locations for workspace.yaml, test.local.json, OAS specs, etc.)
82+
- [ ] Create a `.env.example`
83+
- [ ] Create a CLI setup walkthrough guide
84+
- [ ] Bring the XANO default docs to the future with ajv. (AJV create schema from the Examples set in XANO + updated the OAS to v3.1, clean up the tags)
85+
86+
---
87+
88+
**Contributions, feedback, and ideas are welcome!**

eslint.config.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// I'm not fully sure if this is needed yet.
2+
// [ ] TODO: check and remove in redundant.
3+
import importPlugin from 'eslint-plugin-import';
4+
5+
export default [
6+
{
7+
plugins: {
8+
import: importPlugin,
9+
},
10+
rules: {
11+
'import/no-unresolved': 'error',
12+
},
13+
},
14+
];

package.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "xano-community-cli",
3+
"version": "0.0.1",
4+
"main": "src/xano-community-cli.js",
5+
"type": "module",
6+
"description": "A tool to improve dev experience with XANO, especially for teams where clarity, transparency, and version control is important. Furthermore, this cli should help automate currently manual apsects of XANO. Why a CLI when we have AI? I am bullish on the AI, but in all honesty using AI so much without proper human control can cause a lot of issues. The idea behind this CLI is to reduce the need of reliance on AI and that we have our most crucial parts (testing, documentation) in place in any case, environment, system, either in part of a git provider or local system. The goal is to make it flexible and if there's need, then obiously LLM-ready.",
7+
"scripts": {
8+
"xano-community-cli": "node src/xano-community-cli.js",
9+
"process-backend": "node src/xano-community-cli.js process",
10+
"lint-backend": "node src/xano-community-cli.js lint",
11+
"test-backend": "vitest run --config vitest.config.js"
12+
},
13+
"keywords": ["XANO", "cli", "xano-community-cli", "dev-tool"],
14+
"author": "Mihály Tóth",
15+
"dependencies": {
16+
"@faker-js/faker": "^8.0.2",
17+
"adm-zip": "^0.5.16",
18+
"ajv": "^8.17.1",
19+
"ajv-errors": "^3.0.0",
20+
"axios": "^1.7.7",
21+
"chalk": "^4.1.0",
22+
"chokidar": "^4.0.1",
23+
"cli-progress": "^3.12.0",
24+
"commander": "^14.0.0",
25+
"dotenv": "^16.4.5",
26+
"fs": "^0.0.1-security",
27+
"js-yaml": "^4.1.0",
28+
"node-fetch": "^3.3.2",
29+
"openapi-types": "^12.1.3",
30+
"simple-git": "^3.27.0",
31+
"swagger-client": "^3.34.4",
32+
"tar": "^7.4.3"
33+
},
34+
"devDependencies": {
35+
"@vitest/ui": "^3.1.1",
36+
"eslint": "^9.12.0",
37+
"eslint-plugin-import": "^2.32.0",
38+
"vitest": "^3.1.1"
39+
}
40+
}

0 commit comments

Comments
 (0)