diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 176b207db40..7573367eb1f 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,17 +1,17 @@ -title: "General Discussion" +title: 'General Discussion' body: - type: checkboxes attributes: label: Self Checks - description: "To make sure we get to you in time, please check the following :)" + description: 'To make sure we get to you in time, please check the following :)' options: - label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. required: true - label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)). required: true - - label: "[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)" + - label: '[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)' required: true - - label: "Please do not modify this template :) and fill in all the required fields." + - label: 'Please do not modify this template :) and fill in all the required fields.' required: true - type: textarea attributes: diff --git a/.github/DISCUSSION_TEMPLATE/help.yml b/.github/DISCUSSION_TEMPLATE/help.yml index 85c0debb828..7426ad197ca 100644 --- a/.github/DISCUSSION_TEMPLATE/help.yml +++ b/.github/DISCUSSION_TEMPLATE/help.yml @@ -1,17 +1,17 @@ -title: "Help" +title: 'Help' body: - type: checkboxes attributes: label: Self Checks - description: "To make sure we get to you in time, please check the following :)" + description: 'To make sure we get to you in time, please check the following :)' options: - label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. required: true - label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)). required: true - - label: "[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)" + - label: '[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)' required: true - - label: "Please do not modify this template :) and fill in all the required fields." + - label: 'Please do not modify this template :) and fill in all the required fields.' required: true - type: textarea attributes: diff --git a/.github/DISCUSSION_TEMPLATE/suggestion.yml b/.github/DISCUSSION_TEMPLATE/suggestion.yml index 86b5b3e98b6..31a8736d8dc 100644 --- a/.github/DISCUSSION_TEMPLATE/suggestion.yml +++ b/.github/DISCUSSION_TEMPLATE/suggestion.yml @@ -3,15 +3,15 @@ body: - type: checkboxes attributes: label: Self Checks - description: "To make sure we get to you in time, please check the following :)" + description: 'To make sure we get to you in time, please check the following :)' options: - label: I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. required: true - label: I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)). required: true - - label: "[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)" + - label: '[FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)' required: true - - label: "Please do not modify this template :) and fill in all the required fields." + - label: 'Please do not modify this template :) and fill in all the required fields.' required: true - type: textarea attributes: diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index d684fe91443..467d75ad153 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,4 +1,4 @@ -name: "🕷️ Bug report" +name: '🕷️ Bug report' description: Report errors or unexpected behavior labels: - bug @@ -6,7 +6,7 @@ body: - type: checkboxes attributes: label: Self Checks - description: "To make sure we get to you in time, please check the following :)" + description: 'To make sure we get to you in time, please check the following :)' options: - label: I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). required: true @@ -18,7 +18,7 @@ body: required: true - label: 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) required: true - - label: "Please do not modify this template :) and fill in all the required fields." + - label: 'Please do not modify this template :) and fill in all the required fields.' required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 859f499b8e8..c38441f09a3 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,13 +1,13 @@ blank_issues_enabled: false contact_links: - name: "\U0001F510 Security Vulnerabilities" - url: "https://github.com/langgenius/dify/security/advisories/new" + url: 'https://github.com/langgenius/dify/security/advisories/new' about: Report security vulnerabilities through GitHub Security Advisories to ensure responsible disclosure. 💡 Please do not report security vulnerabilities in public issues. - name: "\U0001F4A1 Model Providers & Plugins" - url: "https://github.com/langgenius/dify-official-plugins/issues/new/choose" + url: 'https://github.com/langgenius/dify-official-plugins/issues/new/choose' about: Report issues with official plugins or model providers, you will need to provide the plugin version and other relevant details. - name: "\U0001F4AC Documentation Issues" - url: "https://github.com/langgenius/dify-docs/issues/new" + url: 'https://github.com/langgenius/dify-docs/issues/new' about: Report issues with the documentation, such as typos, outdated information, or missing content. Please provide the specific section and details of the issue. - name: "\U0001F4E7 Discussions" url: https://github.com/langgenius/dify/discussions/categories/general diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index bd293e24429..05cad470e7c 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,4 +1,4 @@ -name: "⭐ Feature or enhancement request" +name: '⭐ Feature or enhancement request' description: Propose something new. labels: - enhancement @@ -6,7 +6,7 @@ body: - type: checkboxes attributes: label: Self Checks - description: "To make sure we get to you in time, please check the following :)" + description: 'To make sure we get to you in time, please check the following :)' options: - label: I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). required: true @@ -14,7 +14,7 @@ body: required: true - label: I confirm that I am using English to submit this report, otherwise it will be closed. required: true - - label: "Please do not modify this template :) and fill in all the required fields." + - label: 'Please do not modify this template :) and fill in all the required fields.' required: true - type: textarea attributes: diff --git a/.github/ISSUE_TEMPLATE/refactor.yml b/.github/ISSUE_TEMPLATE/refactor.yml index dbe8cbb6027..7b70b1d6290 100644 --- a/.github/ISSUE_TEMPLATE/refactor.yml +++ b/.github/ISSUE_TEMPLATE/refactor.yml @@ -1,11 +1,11 @@ -name: "✨ Refactor or Chore" +name: '✨ Refactor or Chore' description: Refactor existing code or perform maintenance chores to improve readability and reliability. -title: "[Refactor/Chore] " +title: '[Refactor/Chore] ' body: - type: checkboxes attributes: label: Self Checks - description: "To make sure we get to you in time, please check the following :)" + description: 'To make sure we get to you in time, please check the following :)' options: - label: I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). required: true @@ -17,26 +17,26 @@ body: required: true - label: 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) required: true - - label: "Please do not modify this template :) and fill in all the required fields." + - label: 'Please do not modify this template :) and fill in all the required fields.' required: true - type: textarea id: description attributes: label: Description - placeholder: "Describe the refactor or chore you are proposing." + placeholder: 'Describe the refactor or chore you are proposing.' validations: required: true - type: textarea id: motivation attributes: label: Motivation - placeholder: "Explain why this refactor or chore is necessary." + placeholder: 'Explain why this refactor or chore is necessary.' validations: required: false - type: textarea id: additional-context attributes: label: Additional Context - placeholder: "Add any other context or screenshots about the request here." + placeholder: 'Add any other context or screenshots about the request here.' validations: required: false diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3c22088ffe5..945cfab861e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,223 +1,223 @@ version: 2 updates: - - package-ecosystem: "uv" - directory: "/api" + - package-ecosystem: 'uv' + directory: '/api' open-pull-requests-limit: 10 schedule: - interval: "weekly" + interval: 'weekly' groups: flask: patterns: - - "flask" - - "flask-*" - - "werkzeug" - - "gunicorn" + - 'flask' + - 'flask-*' + - 'werkzeug' + - 'gunicorn' google: patterns: - - "google-*" - - "googleapis-*" + - 'google-*' + - 'googleapis-*' opentelemetry: patterns: - - "opentelemetry-*" + - 'opentelemetry-*' pydantic: patterns: - - "pydantic" - - "pydantic-*" + - 'pydantic' + - 'pydantic-*' llm: patterns: - - "langfuse" - - "langsmith" - - "litellm" - - "mlflow*" - - "opik" - - "weave*" - - "arize*" - - "tiktoken" - - "transformers" + - 'langfuse' + - 'langsmith' + - 'litellm' + - 'mlflow*' + - 'opik' + - 'weave*' + - 'arize*' + - 'tiktoken' + - 'transformers' database: patterns: - - "sqlalchemy" - - "psycopg2*" - - "psycogreen" - - "redis*" - - "alembic*" + - 'sqlalchemy' + - 'psycopg2*' + - 'psycogreen' + - 'redis*' + - 'alembic*' storage: patterns: - - "boto3*" - - "botocore*" - - "azure-*" - - "bce-*" - - "cos-python-*" - - "esdk-obs-*" - - "google-cloud-storage" - - "opendal" - - "oss2" - - "supabase*" - - "tos*" + - 'boto3*' + - 'botocore*' + - 'azure-*' + - 'bce-*' + - 'cos-python-*' + - 'esdk-obs-*' + - 'google-cloud-storage' + - 'opendal' + - 'oss2' + - 'supabase*' + - 'tos*' vdb: patterns: - - "alibabacloud*" - - "chromadb" - - "clickhouse-*" - - "clickzetta-*" - - "couchbase" - - "elasticsearch" - - "opensearch-py" - - "oracledb" - - "pgvect*" - - "pymilvus" - - "pymochow" - - "pyobvector" - - "qdrant-client" - - "intersystems-*" - - "tablestore" - - "tcvectordb" - - "tidb-vector" - - "upstash-*" - - "volcengine-*" - - "weaviate-*" - - "xinference-*" - - "mo-vector" - - "mysql-connector-*" + - 'alibabacloud*' + - 'chromadb' + - 'clickhouse-*' + - 'clickzetta-*' + - 'couchbase' + - 'elasticsearch' + - 'opensearch-py' + - 'oracledb' + - 'pgvect*' + - 'pymilvus' + - 'pymochow' + - 'pyobvector' + - 'qdrant-client' + - 'intersystems-*' + - 'tablestore' + - 'tcvectordb' + - 'tidb-vector' + - 'upstash-*' + - 'volcengine-*' + - 'weaviate-*' + - 'xinference-*' + - 'mo-vector' + - 'mysql-connector-*' dev: patterns: - - "coverage" - - "dotenv-linter" - - "faker" - - "lxml-stubs" - - "basedpyright" - - "ruff" - - "pytest*" - - "types-*" - - "boto3-stubs" - - "hypothesis" - - "pandas-stubs" - - "scipy-stubs" - - "import-linter" - - "celery-types" - - "mypy*" - - "pyrefly" + - 'coverage' + - 'dotenv-linter' + - 'faker' + - 'lxml-stubs' + - 'basedpyright' + - 'ruff' + - 'pytest*' + - 'types-*' + - 'boto3-stubs' + - 'hypothesis' + - 'pandas-stubs' + - 'scipy-stubs' + - 'import-linter' + - 'celery-types' + - 'mypy*' + - 'pyrefly' python-packages: patterns: - - "*" - - package-ecosystem: "github-actions" - directory: "/" + - '*' + - package-ecosystem: 'github-actions' + directory: '/' open-pull-requests-limit: 5 schedule: - interval: "weekly" + interval: 'weekly' groups: github-actions-dependencies: patterns: - - "*" - - package-ecosystem: "uv" - directory: "/api" - target-branch: "lts/1.13.x" + - '*' + - package-ecosystem: 'uv' + directory: '/api' + target-branch: 'lts/1.13.x' open-pull-requests-limit: 10 schedule: - interval: "weekly" + interval: 'weekly' groups: flask: patterns: - - "flask" - - "flask-*" - - "werkzeug" - - "gunicorn" + - 'flask' + - 'flask-*' + - 'werkzeug' + - 'gunicorn' google: patterns: - - "google-*" - - "googleapis-*" + - 'google-*' + - 'googleapis-*' opentelemetry: patterns: - - "opentelemetry-*" + - 'opentelemetry-*' pydantic: patterns: - - "pydantic" - - "pydantic-*" + - 'pydantic' + - 'pydantic-*' llm: patterns: - - "langfuse" - - "langsmith" - - "litellm" - - "mlflow*" - - "opik" - - "weave*" - - "arize*" - - "tiktoken" - - "transformers" + - 'langfuse' + - 'langsmith' + - 'litellm' + - 'mlflow*' + - 'opik' + - 'weave*' + - 'arize*' + - 'tiktoken' + - 'transformers' database: patterns: - - "sqlalchemy" - - "psycopg2*" - - "psycogreen" - - "redis*" - - "alembic*" + - 'sqlalchemy' + - 'psycopg2*' + - 'psycogreen' + - 'redis*' + - 'alembic*' storage: patterns: - - "boto3*" - - "botocore*" - - "azure-*" - - "bce-*" - - "cos-python-*" - - "esdk-obs-*" - - "google-cloud-storage" - - "opendal" - - "oss2" - - "supabase*" - - "tos*" + - 'boto3*' + - 'botocore*' + - 'azure-*' + - 'bce-*' + - 'cos-python-*' + - 'esdk-obs-*' + - 'google-cloud-storage' + - 'opendal' + - 'oss2' + - 'supabase*' + - 'tos*' vdb: patterns: - - "alibabacloud*" - - "chromadb" - - "clickhouse-*" - - "clickzetta-*" - - "couchbase" - - "elasticsearch" - - "opensearch-py" - - "oracledb" - - "pgvect*" - - "pymilvus" - - "pymochow" - - "pyobvector" - - "qdrant-client" - - "intersystems-*" - - "tablestore" - - "tcvectordb" - - "tidb-vector" - - "upstash-*" - - "volcengine-*" - - "weaviate-*" - - "xinference-*" - - "mo-vector" - - "mysql-connector-*" + - 'alibabacloud*' + - 'chromadb' + - 'clickhouse-*' + - 'clickzetta-*' + - 'couchbase' + - 'elasticsearch' + - 'opensearch-py' + - 'oracledb' + - 'pgvect*' + - 'pymilvus' + - 'pymochow' + - 'pyobvector' + - 'qdrant-client' + - 'intersystems-*' + - 'tablestore' + - 'tcvectordb' + - 'tidb-vector' + - 'upstash-*' + - 'volcengine-*' + - 'weaviate-*' + - 'xinference-*' + - 'mo-vector' + - 'mysql-connector-*' dev: patterns: - - "coverage" - - "dotenv-linter" - - "faker" - - "lxml-stubs" - - "basedpyright" - - "ruff" - - "pytest*" - - "types-*" - - "boto3-stubs" - - "hypothesis" - - "pandas-stubs" - - "scipy-stubs" - - "import-linter" - - "celery-types" - - "mypy*" - - "pyrefly" + - 'coverage' + - 'dotenv-linter' + - 'faker' + - 'lxml-stubs' + - 'basedpyright' + - 'ruff' + - 'pytest*' + - 'types-*' + - 'boto3-stubs' + - 'hypothesis' + - 'pandas-stubs' + - 'scipy-stubs' + - 'import-linter' + - 'celery-types' + - 'mypy*' + - 'pyrefly' python-packages: patterns: - - "*" - - package-ecosystem: "github-actions" - directory: "/" - target-branch: "lts/1.13.x" + - '*' + - package-ecosystem: 'github-actions' + directory: '/' + target-branch: 'lts/1.13.x' open-pull-requests-limit: 5 schedule: - interval: "weekly" + interval: 'weekly' groups: github-actions-dependencies: patterns: - - "*" + - '*' diff --git a/.github/linters/.hadolint.yaml b/.github/linters/.hadolint.yaml index a607204b136..c17c41d5cea 100644 --- a/.github/linters/.hadolint.yaml +++ b/.github/linters/.hadolint.yaml @@ -1 +1 @@ -failure-threshold: "error" +failure-threshold: 'error' diff --git a/.github/linters/.yaml-lint.yml b/.github/linters/.yaml-lint.yml index c886e67b6ad..1fb6ff1a09b 100644 --- a/.github/linters/.yaml-lint.yml +++ b/.github/linters/.yaml-lint.yml @@ -1,5 +1,4 @@ --- - extends: default rules: diff --git a/.github/linters/editorconfig-checker.json b/.github/linters/editorconfig-checker.json index ce6e9ae3411..e8377c6bf56 100644 --- a/.github/linters/editorconfig-checker.json +++ b/.github/linters/editorconfig-checker.json @@ -1,22 +1,22 @@ { - "Verbose": false, - "Debug": false, - "IgnoreDefaults": false, - "SpacesAfterTabs": false, - "NoColor": false, - "Exclude": [ - "^web/public/vs/", - "^web/public/pdf.worker.min.mjs$", - "web/app/components/base/icons/src/vender/" - ], - "AllowedContentTypes": [], - "PassedFiles": [], - "Disable": { - "EndOfLine": false, - "Indentation": false, - "IndentSize": true, - "InsertFinalNewline": false, - "TrimTrailingWhitespace": false, - "MaxLineLength": false - } + "Verbose": false, + "Debug": false, + "IgnoreDefaults": false, + "SpacesAfterTabs": false, + "NoColor": false, + "Exclude": [ + "^web/public/vs/", + "^web/public/pdf.worker.min.mjs$", + "web/app/components/base/icons/src/vender/" + ], + "AllowedContentTypes": [], + "PassedFiles": [], + "Disable": { + "EndOfLine": false, + "Indentation": false, + "IndentSize": true, + "InsertFinalNewline": false, + "TrimTrailingWhitespace": false, + "MaxLineLength": false + } } diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1e848612ec5..eecbb919659 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,8 +12,8 @@ ## Screenshots | Before | After | -|--------|-------| -| ... | ... | +| ------ | ----- | +| ... | ... | ## Checklist diff --git a/.github/scripts/generate-i18n-changes.mjs b/.github/scripts/generate-i18n-changes.mjs index 3d25115ac34..9fb3f979db9 100644 --- a/.github/scripts/generate-i18n-changes.mjs +++ b/.github/scripts/generate-i18n-changes.mjs @@ -8,31 +8,31 @@ const headSha = process.env.HEAD_SHA || '' const files = (process.env.CHANGED_FILES || '').split(/\s+/).filter(Boolean) const outputPath = process.env.I18N_CHANGES_OUTPUT_PATH || '/tmp/i18n-changes.json' -const englishPath = fileStem => path.join(repoRoot, 'web', 'i18n', 'en-US', `${fileStem}.json`) +const englishPath = (fileStem) => path.join(repoRoot, 'web', 'i18n', 'en-US', `${fileStem}.json`) const readCurrentJson = (fileStem) => { const filePath = englishPath(fileStem) - if (!fs.existsSync(filePath)) - return null + if (!fs.existsSync(filePath)) return null return JSON.parse(fs.readFileSync(filePath, 'utf8')) } const readBaseJson = (fileStem) => { - if (!baseSha) - return null + if (!baseSha) return null try { const relativePath = `web/i18n/en-US/${fileStem}.json` - const content = execFileSync('git', ['show', `${baseSha}:${relativePath}`], { encoding: 'utf8' }) + const content = execFileSync('git', ['show', `${baseSha}:${relativePath}`], { + encoding: 'utf8', + }) return JSON.parse(content) - } - catch { + } catch { return null } } -const compareJson = (beforeValue, afterValue) => JSON.stringify(beforeValue) === JSON.stringify(afterValue) +const compareJson = (beforeValue, afterValue) => + JSON.stringify(beforeValue) === JSON.stringify(afterValue) const changes = {} @@ -59,8 +59,7 @@ for (const fileStem of files) { } for (const key of Object.keys(beforeJson)) { - if (!(key in afterJson)) - deleted.push(key) + if (!(key in afterJson)) deleted.push(key) } changes[fileStem] = { @@ -78,5 +77,5 @@ fs.writeFileSync( headSha, files, changes, - }) + }), ) diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 866d27fe822..54009a040e3 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: python-version: - - "3.12" + - '3.12' steps: - name: Checkout code @@ -84,7 +84,7 @@ jobs: strategy: matrix: python-version: - - "3.12" + - '3.12' steps: - name: Checkout code @@ -148,7 +148,7 @@ jobs: uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: true - python-version: "3.12" + python-version: '3.12' cache-dependency-glob: api/uv.lock - name: Install dependencies diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index e5fed0398a4..6b3f297f482 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -1,12 +1,12 @@ name: autofix.ci on: pull_request: - branches: ["main"] + branches: ['main'] merge_group: - branches: ["main"] + branches: ['main'] types: [checks_requested] push: - branches: ["main"] + branches: ['main'] permissions: contents: read @@ -53,8 +53,7 @@ jobs: oxlint-suppressions.json eslint-suppressions.json .vscode/** - .github/workflows/autofix.yml - .github/workflows/style.yml + .github/** - name: Check api inputs if: github.event_name != 'merge_group' id: api-changes @@ -86,7 +85,7 @@ jobs: - if: github.event_name != 'merge_group' uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: - python-version: "3.11" + python-version: '3.11' - if: github.event_name != 'merge_group' uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml index 1dfc560f1f3..61d654bd375 100644 --- a/.github/workflows/build-push.yml +++ b/.github/workflows/build-push.yml @@ -3,13 +3,13 @@ name: Build and Push API & Web on: push: branches: - - "main" - - "deploy/**" - - "build/**" - - "release/e-*" - - "hotfix/**" + - 'main' + - 'deploy/**' + - 'build/**' + - 'release/e-*' + - 'hotfix/**' tags: - - "*" + - '*' concurrency: group: build-push-${{ github.head_ref || github.run_id }} @@ -33,60 +33,60 @@ jobs: strategy: matrix: include: - - service_name: "build-api-amd64" - image_name_env: "DIFY_API_IMAGE_NAME" - artifact_context: "api" - build_context: "{{defaultContext}}" - file: "api/Dockerfile" + - service_name: 'build-api-amd64' + image_name_env: 'DIFY_API_IMAGE_NAME' + artifact_context: 'api' + build_context: '{{defaultContext}}' + file: 'api/Dockerfile' platform: linux/amd64 runs_on: depot-ubuntu-24.04-4 - - service_name: "build-api-arm64" - image_name_env: "DIFY_API_IMAGE_NAME" - artifact_context: "api" - build_context: "{{defaultContext}}" - file: "api/Dockerfile" + - service_name: 'build-api-arm64' + image_name_env: 'DIFY_API_IMAGE_NAME' + artifact_context: 'api' + build_context: '{{defaultContext}}' + file: 'api/Dockerfile' platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 - - service_name: "build-web-amd64" - image_name_env: "DIFY_WEB_IMAGE_NAME" - artifact_context: "web" - build_context: "{{defaultContext}}" - file: "web/Dockerfile" + - service_name: 'build-web-amd64' + image_name_env: 'DIFY_WEB_IMAGE_NAME' + artifact_context: 'web' + build_context: '{{defaultContext}}' + file: 'web/Dockerfile' platform: linux/amd64 runs_on: depot-ubuntu-24.04-4 - - service_name: "build-web-arm64" - image_name_env: "DIFY_WEB_IMAGE_NAME" - artifact_context: "web" - build_context: "{{defaultContext}}" - file: "web/Dockerfile" + - service_name: 'build-web-arm64' + image_name_env: 'DIFY_WEB_IMAGE_NAME' + artifact_context: 'web' + build_context: '{{defaultContext}}' + file: 'web/Dockerfile' platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 - - service_name: "build-agent-amd64" - image_name_env: "DIFY_AGENT_IMAGE_NAME" - artifact_context: "agent" - build_context: "{{defaultContext}}" - file: "dify-agent/Dockerfile" + - service_name: 'build-agent-amd64' + image_name_env: 'DIFY_AGENT_IMAGE_NAME' + artifact_context: 'agent' + build_context: '{{defaultContext}}' + file: 'dify-agent/Dockerfile' platform: linux/amd64 runs_on: depot-ubuntu-24.04-4 - - service_name: "build-agent-arm64" - image_name_env: "DIFY_AGENT_IMAGE_NAME" - artifact_context: "agent" - build_context: "{{defaultContext}}" - file: "dify-agent/Dockerfile" + - service_name: 'build-agent-arm64' + image_name_env: 'DIFY_AGENT_IMAGE_NAME' + artifact_context: 'agent' + build_context: '{{defaultContext}}' + file: 'dify-agent/Dockerfile' platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 - - service_name: "build-agent-local-sandbox-amd64" - image_name_env: "DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME" - artifact_context: "local-sandbox" - build_context: "{{defaultContext}}:dify-agent-runtime" - file: "docker/Dockerfile" + - service_name: 'build-agent-local-sandbox-amd64' + image_name_env: 'DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME' + artifact_context: 'local-sandbox' + build_context: '{{defaultContext}}:dify-agent-runtime' + file: 'docker/Dockerfile' platform: linux/amd64 runs_on: depot-ubuntu-24.04-4 - - service_name: "build-agent-local-sandbox-arm64" - image_name_env: "DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME" - artifact_context: "local-sandbox" - build_context: "{{defaultContext}}:dify-agent-runtime" - file: "docker/Dockerfile" + - service_name: 'build-agent-local-sandbox-arm64' + image_name_env: 'DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME' + artifact_context: 'local-sandbox' + build_context: '{{defaultContext}}:dify-agent-runtime' + file: 'docker/Dockerfile' platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 @@ -146,18 +146,18 @@ jobs: strategy: matrix: include: - - service_name: "validate-api-amd64" - build_context: "{{defaultContext}}" - file: "api/Dockerfile" - - service_name: "validate-web-amd64" - build_context: "{{defaultContext}}" - file: "web/Dockerfile" - - service_name: "validate-agent-amd64" - build_context: "{{defaultContext}}" - file: "dify-agent/Dockerfile" - - service_name: "validate-agent-local-sandbox-amd64" - build_context: "{{defaultContext}}:dify-agent-runtime" - file: "docker/Dockerfile" + - service_name: 'validate-api-amd64' + build_context: '{{defaultContext}}' + file: 'api/Dockerfile' + - service_name: 'validate-web-amd64' + build_context: '{{defaultContext}}' + file: 'web/Dockerfile' + - service_name: 'validate-agent-amd64' + build_context: '{{defaultContext}}' + file: 'dify-agent/Dockerfile' + - service_name: 'validate-agent-local-sandbox-amd64' + build_context: '{{defaultContext}}:dify-agent-runtime' + file: 'docker/Dockerfile' steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 @@ -178,18 +178,18 @@ jobs: strategy: matrix: include: - - service_name: "merge-api-images" - image_name_env: "DIFY_API_IMAGE_NAME" - context: "api" - - service_name: "merge-web-images" - image_name_env: "DIFY_WEB_IMAGE_NAME" - context: "web" - - service_name: "merge-agent-images" - image_name_env: "DIFY_AGENT_IMAGE_NAME" - context: "agent" - - service_name: "merge-agent-local-sandbox-images" - image_name_env: "DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME" - context: "local-sandbox" + - service_name: 'merge-api-images' + image_name_env: 'DIFY_API_IMAGE_NAME' + context: 'api' + - service_name: 'merge-web-images' + image_name_env: 'DIFY_WEB_IMAGE_NAME' + context: 'web' + - service_name: 'merge-agent-images' + image_name_env: 'DIFY_AGENT_IMAGE_NAME' + context: 'agent' + - service_name: 'merge-agent-local-sandbox-images' + image_name_env: 'DIFY_AGENT_LOCAL_SANDBOX_IMAGE_NAME' + context: 'local-sandbox' steps: - name: Download digests uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 diff --git a/.github/workflows/cli-e2e.yml b/.github/workflows/cli-e2e.yml index 73fe68332d2..0c23cda5f58 100644 --- a/.github/workflows/cli-e2e.yml +++ b/.github/workflows/cli-e2e.yml @@ -4,19 +4,19 @@ on: workflow_dispatch: inputs: cli_ref: - description: "Git ref (default: current branch)" + description: 'Git ref (default: current branch)' type: string required: false edition: - description: "Dify edition" + description: 'Dify edition' type: choice required: false default: ee options: [ee, ce] test_scope: - description: "smoke = [P0] only / full = all cases" + description: 'smoke = [P0] only / full = all cases' type: choice required: false default: full @@ -24,23 +24,23 @@ on: # ── Suite on/off ──────────────────────────────────────────────────────── suite_framework_output_error: - description: "framework + output + error-handling suites" + description: 'framework + output + error-handling suites' type: boolean default: true suite_discovery: - description: "discovery suite (get app / describe app)" + description: 'discovery suite (get app / describe app)' type: boolean default: true suite_run: - description: "run suite (basic / streaming / conversation / file / hitl)" + description: 'run suite (basic / streaming / conversation / file / hitl)' type: boolean default: true suite_auth: - description: "auth suite (login / status / whoami / use / devices / logout)" + description: 'auth suite (login / status / whoami / use / devices / logout)' type: boolean default: true suite_agent: - description: "agent suite" + description: 'agent suite' type: boolean default: true @@ -51,32 +51,31 @@ permissions: # Each job reads DIFY_E2E_TOKEN + app IDs from the provision job outputs, # so global-setup skips minting and finds existing apps in < 10 s. env: - DIFY_E2E_NO_KEYRING: "1" # Linux CI has no keychain; skip probe - VITEST_RETRY: "2" # Retry flaky staging responses + DIFY_E2E_NO_KEYRING: '1' # Linux CI has no keychain; skip probe + VITEST_RETRY: '2' # Retry flaky staging responses jobs: - -# ════════════════════════════════════════════════════════════════════════════ -# 0. PROVISION — mint token + import DSL fixtures (runs once, outputs IDs) -# ════════════════════════════════════════════════════════════════════════════ + # ════════════════════════════════════════════════════════════════════════════ + # 0. PROVISION — mint token + import DSL fixtures (runs once, outputs IDs) + # ════════════════════════════════════════════════════════════════════════════ provision: - name: "Provision: mint token + DSL apps" + name: 'Provision: mint token + DSL apps' runs-on: ubuntu-latest timeout-minutes: 10 outputs: - token: ${{ steps.out.outputs.DIFY_E2E_TOKEN }} - workspace_id: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_ID }} - workspace_name: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_NAME }} - ws2_id: ${{ steps.out.outputs.DIFY_E2E_WS2_ID }} - chat_app_id: ${{ steps.out.outputs.DIFY_E2E_CHAT_APP_ID }} - workflow_app_id: ${{ steps.out.outputs.DIFY_E2E_WORKFLOW_APP_ID }} - file_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_APP_ID }} - file_chat_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_CHAT_APP_ID }} - hitl_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_APP_ID }} - hitl_external_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_EXTERNAL_APP_ID }} - hitl_single_action_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_SINGLE_ACTION_APP_ID }} - hitl_multi_node_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_MULTI_NODE_APP_ID }} - ws2_app_id: ${{ steps.out.outputs.DIFY_E2E_WS2_APP_ID }} + token: ${{ steps.out.outputs.DIFY_E2E_TOKEN }} + workspace_id: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_ID }} + workspace_name: ${{ steps.out.outputs.DIFY_E2E_WORKSPACE_NAME }} + ws2_id: ${{ steps.out.outputs.DIFY_E2E_WS2_ID }} + chat_app_id: ${{ steps.out.outputs.DIFY_E2E_CHAT_APP_ID }} + workflow_app_id: ${{ steps.out.outputs.DIFY_E2E_WORKFLOW_APP_ID }} + file_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_APP_ID }} + file_chat_app_id: ${{ steps.out.outputs.DIFY_E2E_FILE_CHAT_APP_ID }} + hitl_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_APP_ID }} + hitl_external_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_EXTERNAL_APP_ID }} + hitl_single_action_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_SINGLE_ACTION_APP_ID }} + hitl_multi_node_app_id: ${{ steps.out.outputs.DIFY_E2E_HITL_MULTI_NODE_APP_ID }} + ws2_app_id: ${{ steps.out.outputs.DIFY_E2E_WS2_APP_ID }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4 @@ -101,18 +100,18 @@ jobs: id: out working-directory: cli env: - DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} - DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} + DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} + DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} - DIFY_E2E_TOKEN: ${{ secrets.DIFY_E2E_TOKEN }} - DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} + DIFY_E2E_TOKEN: ${{ secrets.DIFY_E2E_TOKEN }} + DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} run: bun scripts/e2e-provision.ts -# ════════════════════════════════════════════════════════════════════════════ -# 1-B. framework + output + error-handling (parallel with run/discovery) -# ════════════════════════════════════════════════════════════════════════════ + # ════════════════════════════════════════════════════════════════════════════ + # 1-B. framework + output + error-handling (parallel with run/discovery) + # ════════════════════════════════════════════════════════════════════════════ suite-framework-output-error: - name: "Suite: framework + output + error-handling" + name: 'Suite: framework + output + error-handling' if: ${{ inputs.suite_framework_output_error != 'false' }} needs: provision runs-on: ubuntu-latest @@ -138,16 +137,16 @@ jobs: - name: Run framework + output + error-handling env: - DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} - DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} - DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} - DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} - DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} - DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} + DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} + DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} + DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} + DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} + DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} + DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }} - DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} + DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }} - DIFY_E2E_INCLUDE: "test/e2e/suites/framework/**/*.e2e.ts,test/e2e/suites/output/**/*.e2e.ts,test/e2e/suites/error-handling/**/*.e2e.ts" + DIFY_E2E_INCLUDE: 'test/e2e/suites/framework/**/*.e2e.ts,test/e2e/suites/output/**/*.e2e.ts,test/e2e/suites/error-handling/**/*.e2e.ts' run: | if [ "${{ inputs.test_scope }}" = "smoke" ]; then pnpm test:e2e -- -t "\[P0\]" @@ -155,11 +154,11 @@ jobs: pnpm test:e2e fi -# ════════════════════════════════════════════════════════════════════════════ -# 1-C. Discovery (parallel) -# ════════════════════════════════════════════════════════════════════════════ + # ════════════════════════════════════════════════════════════════════════════ + # 1-C. Discovery (parallel) + # ════════════════════════════════════════════════════════════════════════════ suite-discovery: - name: "Suite: discovery" + name: 'Suite: discovery' if: ${{ inputs.suite_discovery != 'false' }} needs: provision runs-on: ubuntu-latest @@ -185,17 +184,17 @@ jobs: - name: Run discovery suite env: - DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} - DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} - DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} - DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} - DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} - DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} + DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} + DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} + DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} + DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} + DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} + DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }} - DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }} - DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} + DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }} + DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }} - DIFY_E2E_INCLUDE: "test/e2e/suites/discovery/**/*.e2e.ts" + DIFY_E2E_INCLUDE: 'test/e2e/suites/discovery/**/*.e2e.ts' run: | if [ "${{ inputs.test_scope }}" = "smoke" ]; then pnpm test:e2e -- -t "\[P0\]" @@ -203,11 +202,11 @@ jobs: pnpm test:e2e fi -# ════════════════════════════════════════════════════════════════════════════ -# 1-D. Run suite — 5 files in matrix (parallel) -# ════════════════════════════════════════════════════════════════════════════ + # ════════════════════════════════════════════════════════════════════════════ + # 1-D. Run suite — 5 files in matrix (parallel) + # ════════════════════════════════════════════════════════════════════════════ suite-run: - name: "Suite: run / ${{ matrix.name }}" + name: 'Suite: run / ${{ matrix.name }}' if: ${{ inputs.suite_run != 'false' }} needs: provision runs-on: ubuntu-latest @@ -246,25 +245,25 @@ jobs: - run: pnpm install --frozen-lockfile - run: pnpm tree:gen - - name: "Run run/${{ matrix.name }}" + - name: 'Run run/${{ matrix.name }}' env: - DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} - DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} - DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} - DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} - DIFY_E2E_SSO_TOKEN: ${{ secrets.DIFY_E2E_SSO_TOKEN }} - DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} - DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} - DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }} - DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} - DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }} - DIFY_E2E_FILE_APP_ID: ${{ needs.provision.outputs.file_app_id }} - DIFY_E2E_FILE_CHAT_APP_ID: ${{ needs.provision.outputs.file_chat_app_id }} - DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }} - DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }} + DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} + DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} + DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} + DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} + DIFY_E2E_SSO_TOKEN: ${{ secrets.DIFY_E2E_SSO_TOKEN }} + DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} + DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} + DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }} + DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} + DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }} + DIFY_E2E_FILE_APP_ID: ${{ needs.provision.outputs.file_app_id }} + DIFY_E2E_FILE_CHAT_APP_ID: ${{ needs.provision.outputs.file_chat_app_id }} + DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }} + DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }} DIFY_E2E_HITL_SINGLE_ACTION_APP_ID: ${{ needs.provision.outputs.hitl_single_action_app_id }} - DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }} - DIFY_E2E_INCLUDE: "test/e2e/suites/run/${{ matrix.file }}" + DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }} + DIFY_E2E_INCLUDE: 'test/e2e/suites/run/${{ matrix.file }}' run: | if [ "${{ inputs.test_scope }}" = "smoke" ]; then pnpm test:e2e -- -t "\[P0\]" @@ -280,11 +279,11 @@ jobs: path: cli/test-results/ retention-days: 3 -# ════════════════════════════════════════════════════════════════════════════ -# 1-E. auth/login + status + whoami (parallel, read-only, safe) -# ════════════════════════════════════════════════════════════════════════════ + # ════════════════════════════════════════════════════════════════════════════ + # 1-E. auth/login + status + whoami (parallel, read-only, safe) + # ════════════════════════════════════════════════════════════════════════════ suite-auth-safe: - name: "Suite: auth (login / status / whoami)" + name: 'Suite: auth (login / status / whoami)' if: ${{ inputs.suite_auth != 'false' }} needs: provision runs-on: ubuntu-latest @@ -310,15 +309,15 @@ jobs: - name: Run auth/login + status + whoami env: - DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} - DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} - DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} - DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} - DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} - DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} + DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} + DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} + DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} + DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} + DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} + DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }} - DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }} - DIFY_E2E_INCLUDE: "test/e2e/suites/auth/login.e2e.ts,test/e2e/suites/auth/status.e2e.ts,test/e2e/suites/auth/whoami.e2e.ts" + DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }} + DIFY_E2E_INCLUDE: 'test/e2e/suites/auth/login.e2e.ts,test/e2e/suites/auth/status.e2e.ts,test/e2e/suites/auth/whoami.e2e.ts' run: | if [ "${{ inputs.test_scope }}" = "smoke" ]; then pnpm test:e2e -- -t "\[P0\]" @@ -326,13 +325,13 @@ jobs: pnpm test:e2e fi -# ════════════════════════════════════════════════════════════════════════════ -# 2. DESTRUCTIVE — auth/use + devices + logout + agent (serial, runs LAST) -# Must wait for ALL parallel suites to finish to avoid token revocation -# invalidating other in-flight requests. -# ════════════════════════════════════════════════════════════════════════════ + # ════════════════════════════════════════════════════════════════════════════ + # 2. DESTRUCTIVE — auth/use + devices + logout + agent (serial, runs LAST) + # Must wait for ALL parallel suites to finish to avoid token revocation + # invalidating other in-flight requests. + # ════════════════════════════════════════════════════════════════════════════ suite-last: - name: "Suite: auth-use + devices + logout + agent (last, serial)" + name: 'Suite: auth-use + devices + logout + agent (last, serial)' # Runs when auth is selected; also runs after all parallel jobs finish if: ${{ inputs.suite_auth != 'false' || inputs.suite_agent != 'false' }} needs: @@ -366,20 +365,20 @@ jobs: - name: Run use / devices / logout / agent (serial) env: - DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} - DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} - DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} - DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} - DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} - DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} - DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }} - DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }} - DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} - DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }} - DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }} - DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }} + DIFY_E2E_HOST: ${{ secrets.DIFY_E2E_HOST }} + DIFY_E2E_EMAIL: ${{ secrets.DIFY_E2E_EMAIL }} + DIFY_E2E_PASSWORD: ${{ secrets.DIFY_E2E_PASSWORD }} + DIFY_E2E_EDITION: ${{ inputs.edition || 'ee' }} + DIFY_E2E_TOKEN: ${{ needs.provision.outputs.token }} + DIFY_E2E_WORKSPACE_ID: ${{ needs.provision.outputs.workspace_id }} + DIFY_E2E_WORKSPACE_NAME: ${{ needs.provision.outputs.workspace_name }} + DIFY_E2E_WS2_ID: ${{ needs.provision.outputs.ws2_id }} + DIFY_E2E_CHAT_APP_ID: ${{ needs.provision.outputs.chat_app_id }} + DIFY_E2E_WORKFLOW_APP_ID: ${{ needs.provision.outputs.workflow_app_id }} + DIFY_E2E_HITL_APP_ID: ${{ needs.provision.outputs.hitl_app_id }} + DIFY_E2E_HITL_EXTERNAL_APP_ID: ${{ needs.provision.outputs.hitl_external_app_id }} DIFY_E2E_HITL_SINGLE_ACTION_APP_ID: ${{ needs.provision.outputs.hitl_single_action_app_id }} - DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }} + DIFY_E2E_HITL_MULTI_NODE_APP_ID: ${{ needs.provision.outputs.hitl_multi_node_app_id }} run: | # Collect files in safe order: use → devices → logout (revokes last) → agent FILES=() diff --git a/.github/workflows/cli-smoke.yml b/.github/workflows/cli-smoke.yml index 3437d7a52c3..7c70a52428b 100644 --- a/.github/workflows/cli-smoke.yml +++ b/.github/workflows/cli-smoke.yml @@ -4,11 +4,11 @@ on: workflow_dispatch: inputs: dify_version: - description: "Dify image tag to test against (e.g. 1.7.0)" + description: 'Dify image tag to test against (e.g. 1.7.0)' type: string required: true cli_ref: - description: "Git ref to build the cli from (default: current branch)" + description: 'Git ref to build the cli from (default: current branch)' type: string required: false diff --git a/.github/workflows/db-migration-test.yml b/.github/workflows/db-migration-test.yml index 38b8b9540c5..dbc9c085f75 100644 --- a/.github/workflows/db-migration-test.yml +++ b/.github/workflows/db-migration-test.yml @@ -22,7 +22,7 @@ jobs: uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: true - python-version: "3.12" + python-version: '3.12' cache-dependency-glob: api/uv.lock - name: Install dependencies @@ -72,7 +72,7 @@ jobs: uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: true - python-version: "3.12" + python-version: '3.12' cache-dependency-glob: api/uv.lock - name: Install dependencies diff --git a/.github/workflows/deploy-agent.yml b/.github/workflows/deploy-agent.yml index e244bb3f949..75844b1a1d1 100644 --- a/.github/workflows/deploy-agent.yml +++ b/.github/workflows/deploy-agent.yml @@ -5,9 +5,9 @@ permissions: on: workflow_run: - workflows: ["Build and Push API & Web"] + workflows: ['Build and Push API & Web'] branches: - - "deploy/agent" + - 'deploy/agent' types: - completed diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index c2ff8c63324..cddf5edc351 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -2,9 +2,9 @@ name: Deploy Dev on: workflow_run: - workflows: ["Build and Push API & Web"] + workflows: ['Build and Push API & Web'] branches: - - "deploy/dev" + - 'deploy/dev' types: - completed diff --git a/.github/workflows/deploy-enterprise.yml b/.github/workflows/deploy-enterprise.yml index 2740541f0ff..3d57efcbc2e 100644 --- a/.github/workflows/deploy-enterprise.yml +++ b/.github/workflows/deploy-enterprise.yml @@ -5,9 +5,9 @@ permissions: on: workflow_run: - workflows: ["Build and Push API & Web"] + workflows: ['Build and Push API & Web'] branches: - - "deploy/enterprise" + - 'deploy/enterprise' types: - completed diff --git a/.github/workflows/deploy-knowledge.yml b/.github/workflows/deploy-knowledge.yml index 7e2b3a086ac..0c85fe7dc49 100644 --- a/.github/workflows/deploy-knowledge.yml +++ b/.github/workflows/deploy-knowledge.yml @@ -6,9 +6,9 @@ permissions: on: workflow_run: - workflows: ["Build and Push API & Web"] + workflows: ['Build and Push API & Web'] branches: - - "deploy/konwledge" + - 'deploy/konwledge' types: - completed diff --git a/.github/workflows/deploy-saas.yml b/.github/workflows/deploy-saas.yml index b00883c8c79..f0165c35ed4 100644 --- a/.github/workflows/deploy-saas.yml +++ b/.github/workflows/deploy-saas.yml @@ -5,9 +5,9 @@ permissions: on: workflow_run: - workflows: ["Build and Push API & Web"] + workflows: ['Build and Push API & Web'] branches: - - "deploy/saas" + - 'deploy/saas' types: - completed diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 9fb71a42cfd..4e70609b7e1 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -3,7 +3,7 @@ name: Build docker image on: pull_request: branches: - - "main" + - 'main' paths: - api/Dockerfile - api/Dockerfile.dockerignore @@ -33,36 +33,36 @@ jobs: strategy: matrix: include: - - service_name: "api-amd64" + - service_name: 'api-amd64' platform: linux/amd64 runs_on: depot-ubuntu-24.04-4 - context: "{{defaultContext}}" - file: "api/Dockerfile" - - service_name: "api-arm64" + context: '{{defaultContext}}' + file: 'api/Dockerfile' + - service_name: 'api-arm64' platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 - context: "{{defaultContext}}" - file: "api/Dockerfile" - - service_name: "web-amd64" + context: '{{defaultContext}}' + file: 'api/Dockerfile' + - service_name: 'web-amd64' platform: linux/amd64 runs_on: depot-ubuntu-24.04-4 - context: "{{defaultContext}}" - file: "web/Dockerfile" - - service_name: "web-arm64" + context: '{{defaultContext}}' + file: 'web/Dockerfile' + - service_name: 'web-arm64' platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 - context: "{{defaultContext}}" - file: "web/Dockerfile" - - service_name: "local-sandbox-amd64" + context: '{{defaultContext}}' + file: 'web/Dockerfile' + - service_name: 'local-sandbox-amd64' platform: linux/amd64 runs_on: depot-ubuntu-24.04-4 - context: "{{defaultContext}}:dify-agent-runtime" - file: "docker/Dockerfile" - - service_name: "local-sandbox-arm64" + context: '{{defaultContext}}:dify-agent-runtime' + file: 'docker/Dockerfile' + - service_name: 'local-sandbox-arm64' platform: linux/arm64 runs_on: depot-ubuntu-24.04-4 - context: "{{defaultContext}}:dify-agent-runtime" - file: "docker/Dockerfile" + context: '{{defaultContext}}:dify-agent-runtime' + file: 'docker/Dockerfile' steps: - name: Set up Depot CLI uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1 @@ -85,15 +85,15 @@ jobs: strategy: matrix: include: - - service_name: "api-amd64" - context: "{{defaultContext}}" - file: "api/Dockerfile" - - service_name: "web-amd64" - context: "{{defaultContext}}" - file: "web/Dockerfile" - - service_name: "local-sandbox-amd64" - context: "{{defaultContext}}:dify-agent-runtime" - file: "docker/Dockerfile" + - service_name: 'api-amd64' + context: '{{defaultContext}}' + file: 'api/Dockerfile' + - service_name: 'web-amd64' + context: '{{defaultContext}}' + file: 'web/Dockerfile' + - service_name: 'local-sandbox-amd64' + context: '{{defaultContext}}:dify-agent-runtime' + file: 'docker/Dockerfile' steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 181fc2db007..fb7fd284b65 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,4 +1,4 @@ -name: "Pull Request Labeler" +name: 'Pull Request Labeler' on: pull_request_target: diff --git a/.github/workflows/main-ci.yml b/.github/workflows/main-ci.yml index 1c2e9028edb..72b1f496c71 100644 --- a/.github/workflows/main-ci.yml +++ b/.github/workflows/main-ci.yml @@ -2,9 +2,9 @@ name: Main CI Pipeline on: pull_request: - branches: ["main"] + branches: ['main'] merge_group: - branches: ["main"] + branches: ['main'] types: [checks_requested] permissions: diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index 41e1bba8f7b..de1fce7977c 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -2,7 +2,7 @@ name: Post-Merge Checks on: push: - branches: ["main"] + branches: ['main'] permissions: contents: read diff --git a/.github/workflows/semantic-pull-request.yml b/.github/workflows/semantic-pull-request.yml index 6f3193bbf53..51f5b373593 100644 --- a/.github/workflows/semantic-pull-request.yml +++ b/.github/workflows/semantic-pull-request.yml @@ -8,7 +8,7 @@ on: - reopened - synchronize merge_group: - branches: ["main"] + branches: ['main'] types: [checks_requested] jobs: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 0973f2340f0..b1c4e85322d 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,7 +11,6 @@ on: jobs: stale: - runs-on: depot-ubuntu-24.04 permissions: issues: write @@ -23,8 +22,8 @@ jobs: days-before-issue-stale: 15 days-before-issue-close: 3 repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: "Closed due to inactivity. If you have any questions, you can reopen it." - stale-pr-message: "Closed due to inactivity. If you have any questions, you can reopen it." + stale-issue-message: 'Closed due to inactivity. If you have any questions, you can reopen it.' + stale-pr-message: 'Closed due to inactivity. If you have any questions, you can reopen it.' stale-issue-label: 'no-issue-activity' stale-pr-label: 'no-pr-activity' any-of-labels: '🌚 invalid,🙋‍♂️ question,wont-fix,no-issue-activity,no-pr-activity,💪 enhancement,🤔 cant-reproduce,🙏 help wanted' diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index e496371e83d..5507baaba7b 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -44,7 +44,7 @@ jobs: uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: false - python-version: "3.12" + python-version: '3.12' cache-dependency-glob: api/uv.lock - name: Install dependencies @@ -169,9 +169,7 @@ jobs: oxlint-suppressions.json eslint-suppressions.json .vscode/** - .github/workflows/autofix.yml - .github/workflows/style.yml - .github/actions/setup-web/** + .github/** - name: Setup web environment if: steps.changed-files.outputs.any_changed == 'true' diff --git a/.github/workflows/vdb-tests-full.yml b/.github/workflows/vdb-tests-full.yml index 0a33cc7beb0..e5680416058 100644 --- a/.github/workflows/vdb-tests-full.yml +++ b/.github/workflows/vdb-tests-full.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: python-version: - - "3.12" + - '3.12' steps: - name: Checkout code @@ -48,16 +48,16 @@ jobs: - name: Install dependencies run: uv sync --project api --dev -# - name: Set up Vector Store (TiDB) -# uses: hoverkraft-tech/compose-action@v2.0.2 -# with: -# compose-file: docker/tidb/docker-compose.yaml -# services: | -# tidb -# tiflash + # - name: Set up Vector Store (TiDB) + # uses: hoverkraft-tech/compose-action@v2.0.2 + # with: + # compose-file: docker/tidb/docker-compose.yaml + # services: | + # tidb + # tiflash -# - name: Check VDB Ready (TiDB) -# run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py + # - name: Check VDB Ready (TiDB) + # run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py - name: Test Vector Stores run: | diff --git a/.github/workflows/vdb-tests.yml b/.github/workflows/vdb-tests.yml index e4d85b7d4ee..0fa646ad8e5 100644 --- a/.github/workflows/vdb-tests.yml +++ b/.github/workflows/vdb-tests.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: python-version: - - "3.12" + - '3.12' steps: - name: Checkout code @@ -45,16 +45,16 @@ jobs: - name: Install dependencies run: uv sync --project api --dev -# - name: Set up Vector Store (TiDB) -# uses: hoverkraft-tech/compose-action@v2.0.2 -# with: -# compose-file: docker/tidb/docker-compose.yaml -# services: | -# tidb -# tiflash + # - name: Set up Vector Store (TiDB) + # uses: hoverkraft-tech/compose-action@v2.0.2 + # with: + # compose-file: docker/tidb/docker-compose.yaml + # services: | + # tidb + # tiflash -# - name: Check VDB Ready (TiDB) -# run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py + # - name: Check VDB Ready (TiDB) + # run: uv run --project api python api/providers/vdb/tidb-vector/tests/integration_tests/check_tiflash_ready.py - name: Test Vector Stores run: | diff --git a/.github/workflows/web-e2e.yml b/.github/workflows/web-e2e.yml index fce28856f45..9d0eb2e02ed 100644 --- a/.github/workflows/web-e2e.yml +++ b/.github/workflows/web-e2e.yml @@ -33,7 +33,7 @@ jobs: uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: true - python-version: "3.12" + python-version: '3.12' cache-dependency-glob: | api/uv.lock dify-agent/uv.lock @@ -65,7 +65,7 @@ jobs: E2E_ADMIN_EMAIL: e2e-admin@example.com E2E_ADMIN_NAME: E2E Admin E2E_ADMIN_PASSWORD: E2eAdmin12345 - E2E_FORCE_WEB_BUILD: "1" + E2E_FORCE_WEB_BUILD: '1' E2E_INIT_PASSWORD: E2eInit12345 run: vp run e2e:full @@ -125,7 +125,7 @@ jobs: E2E_AGENT_DECISION_MODEL_NAME: ${{ vars.E2E_AGENT_DECISION_MODEL_NAME || 'gpt-5.5' }} E2E_AGENT_DECISION_MODEL_PROVIDER: ${{ vars.E2E_AGENT_DECISION_MODEL_PROVIDER || 'openai' }} E2E_AGENT_DECISION_MODEL_TYPE: ${{ vars.E2E_AGENT_DECISION_MODEL_TYPE || 'llm' }} - E2E_FORCE_WEB_BUILD: "1" + E2E_FORCE_WEB_BUILD: '1' E2E_INIT_PASSWORD: E2eInit12345 E2E_MARKETPLACE_API_URL: ${{ vars.E2E_MARKETPLACE_API_URL }} E2E_MARKETPLACE_PLUGIN_IDS: ${{ vars.E2E_MARKETPLACE_PLUGIN_IDS }} diff --git a/vite.config.ts b/vite.config.ts index 5165e58bafe..2ca40cf7f6b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -11,7 +11,6 @@ const eslintFix = const nonFrontendIgnores = [ '.agents/**', '.devcontainer/**', - '.github/**', '/*.md', 'api/**', 'codecov.yml',