From 33f001a1a00feabdd58db24dbb3ee9edb0e67046 Mon Sep 17 00:00:00 2001 From: Klesh Wong Date: Wed, 2 Sep 2026 19:44:46 +0800 Subject: [PATCH] chore(python): deprecate Python plugin framework (PyDevLake) Phase 1 of the deprecation plan in #9092. Adds deprecation warnings across the codebase to inform users that the Python plugin framework will be removed in 3 months in favor of Go-based plugins. Changes: - backend/python/README.md: add DEPRECATED banner + migration guidance - backend/python/plugins/azuredevops/README.md: mark plugin deprecated, point users to azuredevops_go - backend/core/runner/loader.go: emit a WARN log line at server startup when remote (Python) plugins are being loaded - backend/core/plugin/plugin_meta.go: add PluginDeprecation interface - backend/server/services/remote/plugin/plugin_impl.go: implement PluginDeprecation on RemotePlugin so all Python plugins are flagged - backend/server/api/plugininfo/plugininifo.go: expose field on GET /plugins so config-ui can detect deprecated plugins - config-ui: add isDeprecated/deprecationMessage to IPluginConfig, mark the azuredevops (Python) plugin deprecated, and render a 'Deprecated' badge + message in the Connections page --- backend/core/plugin/plugin_meta.go | 8 +++++++ backend/core/runner/loader.go | 1 + backend/python/README.md | 22 +++++++++++++++++++ backend/python/plugins/azuredevops/README.md | 15 ++++++++++++- backend/server/api/plugininfo/plugininifo.go | 9 ++++++-- .../services/remote/plugin/plugin_impl.go | 12 ++++++++++ .../src/plugins/register/azure/config.tsx | 3 +++ .../src/routes/connection/connections.tsx | 8 +++++++ config-ui/src/routes/connection/styled.ts | 20 +++++++++++++++++ config-ui/src/types/plugin.ts | 2 ++ 10 files changed, 97 insertions(+), 3 deletions(-) diff --git a/backend/core/plugin/plugin_meta.go b/backend/core/plugin/plugin_meta.go index 4047f7e54d3..1807f3833b3 100644 --- a/backend/core/plugin/plugin_meta.go +++ b/backend/core/plugin/plugin_meta.go @@ -44,6 +44,14 @@ type PluginIcon interface { SvgIcon() string } +// PluginDeprecation is implemented by plugins that have been deprecated. +// The DeprecationMessage should describe why the plugin is deprecated and +// what users should migrate to. Returns an empty string for non-deprecated +// plugins. +type PluginDeprecation interface { + DeprecationMessage() string +} + // PluginSource abstracts data sources type PluginSource interface { Connection() dal.Tabler diff --git a/backend/core/runner/loader.go b/backend/core/runner/loader.go index f05a78632dc..9c6a32af9c5 100644 --- a/backend/core/runner/loader.go +++ b/backend/core/runner/loader.go @@ -91,6 +91,7 @@ func LoadGoPlugins(basicRes context.BasicRes) errors.Error { func LoadRemotePlugins(basicRes context.BasicRes) errors.Error { remotePluginDir := basicRes.GetConfig("REMOTE_PLUGIN_DIR") if remotePluginDir != "" { + basicRes.GetLogger().Warn(nil, "DEPRECATION WARNING: The Python plugin framework (PyDevLake) is deprecated and will be removed in 3 months. See https://github.com/apache/devlake/issues/9092 for the deprecation plan and migration guide. Please migrate Python plugins (e.g. azuredevops) to the Go-based equivalents (e.g. azuredevops_go).") basicRes.GetLogger().Info("Loading remote plugins") remote.Init(basicRes) walkErr := filepath.WalkDir(remotePluginDir, func(path string, d fs.DirEntry, err error) error { diff --git a/backend/python/README.md b/backend/python/README.md index 17bf0cee7b3..5c2f1288556 100644 --- a/backend/python/README.md +++ b/backend/python/README.md @@ -16,6 +16,28 @@ limitations under the License. --> # Pydevlake +> **⚠️ DEPRECATED — Scheduled for removal.** +> The Python plugin framework (PyDevLake) is deprecated and will be removed from +> Apache DevLake in 3 months per the deprecation plan in +> [#9092](https://github.com/apache/devlake/issues/9092). +> +> Reasons: +> - Only one plugin (`azuredevops`) ever shipped on this framework; the `dbt` +> plugin was already removed (#8970). +> - No feature/fix commits to Python plugins since Dec 2025; only dependency +> refreshes and runtime bumps land. +> - A fully-featured Go implementation, `azuredevops_go`, now supersedes the +> Python `azuredevops` plugin (including on-premises support, #9014). +> +> **What you should do:** +> - New plugins: write them in **Go**. See `backend/plugins/` for 40+ reference +> implementations. +> - Existing `azuredevops` (Python) users: migrate to `azuredevops_go` (a +> migration guide will be published during the deprecation window). +> +> No new Python plugins will be accepted. Only critical security fixes will land +> during the deprecation window. + Pydevlake is a framework for writing plugins for [DevLake](https://devlake.apache.org/) in Python. The framework source code can be found in [here](./pydevlake). diff --git a/backend/python/plugins/azuredevops/README.md b/backend/python/plugins/azuredevops/README.md index ed5366bfa1c..172bc64f574 100644 --- a/backend/python/plugins/azuredevops/README.md +++ b/backend/python/plugins/azuredevops/README.md @@ -14,4 +14,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> -# Azure Devops Python Plugin \ No newline at end of file +# Azure Devops Python Plugin + +> **⚠️ DEPRECATED — Scheduled for removal in 3 months.** +> This Python `azuredevops` plugin is deprecated in favor of the Go-based +> [`azuredevops_go`](../../plugins/azuredevops_go) plugin, which has broader +> feature coverage (including Azure DevOps Server / on-premises support, #9014). +> +> Please migrate existing connections and scopes to `azuredevops_go`. A migration +> guide will be published during the deprecation window — see +> [#9092](https://github.com/apache/devlake/issues/9092) for the full plan and +> timeline. +> +> No new features or fixes (other than critical security fixes) will be accepted +> on this plugin. \ No newline at end of file diff --git a/backend/server/api/plugininfo/plugininifo.go b/backend/server/api/plugininfo/plugininifo.go index de32fbc9476..285b6fd2ca2 100644 --- a/backend/server/api/plugininfo/plugininifo.go +++ b/backend/server/api/plugininfo/plugininifo.go @@ -75,8 +75,9 @@ type PluginMetric struct { } type PluginMeta struct { - Plugin string `json:"plugin"` - Metric PluginMetric `json:"metric"` + Plugin string `json:"plugin"` + Metric PluginMetric `json:"metric"` + Deprecated bool `json:"deprecated"` } type PluginMetas []PluginMeta @@ -207,6 +208,10 @@ func GetPluginMetas(c *gin.Context) { Plugin: name, } + if dp, ok := p.(plugin.PluginDeprecation); ok { + pluginMeta.Deprecated = dp.DeprecationMessage() != "" + } + // if this plugin has the plugin task info if pt, ok := p.(plugin.PluginMetric); ok { var err1 errors.Error diff --git a/backend/server/services/remote/plugin/plugin_impl.go b/backend/server/services/remote/plugin/plugin_impl.go index 1cf768305d3..fe8e429709a 100644 --- a/backend/server/services/remote/plugin/plugin_impl.go +++ b/backend/server/services/remote/plugin/plugin_impl.go @@ -238,4 +238,16 @@ func (p *remotePluginImpl) MigrationScripts() []plugin.MigrationScript { return append(p.migrationScripts, migrationscripts.All(p.name)...) } +// DeprecationMessage implements plugin.PluginDeprecation. All remote (Python) +// plugins are deprecated and scheduled for removal in 3 months per the +// deprecation plan in issue #9092. +func (p *remotePluginImpl) DeprecationMessage() string { + return fmt.Sprintf( + "This Python plugin (%s) is DEPRECATED and will be removed in 3 months. "+ + "Please migrate to the Go-based equivalent. "+ + "See https://github.com/apache/devlake/issues/9092 for the deprecation plan and migration guide.", + p.name, + ) +} + var _ models.RemotePlugin = (*remotePluginImpl)(nil) diff --git a/config-ui/src/plugins/register/azure/config.tsx b/config-ui/src/plugins/register/azure/config.tsx index 978a6af0934..3818226a2df 100644 --- a/config-ui/src/plugins/register/azure/config.tsx +++ b/config-ui/src/plugins/register/azure/config.tsx @@ -28,6 +28,9 @@ export const AzureConfig: IPluginConfig = { name: 'Azure DevOps', icon: ({ color }) => , sort: 2, + isDeprecated: true, + deprecationMessage: + 'This Python-based Azure DevOps plugin is DEPRECATED and will be removed in 3 months. Please migrate to the Go-based "Azure DevOps Go" plugin. See https://github.com/apache/devlake/issues/9092 for the deprecation plan and migration guide.', connection: { docLink: DOC_URL.PLUGIN.AZUREDEVOPS.BASIS, initialValues: {}, diff --git a/config-ui/src/routes/connection/connections.tsx b/config-ui/src/routes/connection/connections.tsx index ce6a3e0d90a..b660b070df1 100644 --- a/config-ui/src/routes/connection/connections.tsx +++ b/config-ui/src/routes/connection/connections.tsx @@ -95,8 +95,12 @@ export const Connections = () => { return (
  • handleShowListDialog(plugin)}> {pluginConfig.isBeta && Beta} + {pluginConfig.isDeprecated && Deprecated} {pluginConfig.icon({ color: colorPrimary })} {pluginConfig.name} + {pluginConfig.isDeprecated && pluginConfig.deprecationMessage && ( + {pluginConfig.deprecationMessage} + )} {connectionCount ? ( @@ -116,8 +120,12 @@ export const Connections = () => { return (
  • handleShowListDialog(plugin)}> {pluginConfig.isBeta && Beta} + {pluginConfig.isDeprecated && Deprecated} {pluginConfig.icon({ color: colorPrimary })} {pluginConfig.name} + {pluginConfig.isDeprecated && pluginConfig.deprecationMessage && ( + {pluginConfig.deprecationMessage} + )} {connectionCount ? ( diff --git a/config-ui/src/routes/connection/styled.ts b/config-ui/src/routes/connection/styled.ts index 2bc88b8cab3..5c53a1c4fc8 100644 --- a/config-ui/src/routes/connection/styled.ts +++ b/config-ui/src/routes/connection/styled.ts @@ -82,6 +82,26 @@ export const Wrapper = styled.div` border-radius: 8px; } + & > .deprecated { + position: absolute; + top: 0; + left: 0; + padding: 4px 8px; + font-size: 12px; + color: ${({ theme }) => theme.colors.textInverse}; + background-color: ${({ theme }) => theme.colors.error}; + border-radius: 8px; + } + + & > .deprecation-note { + margin-top: 4px; + padding: 0 8px; + font-size: 11px; + line-height: 1.4; + color: ${({ theme }) => theme.colors.error}; + text-align: center; + } + & > .logo { width: 60px; height: 60px; diff --git a/config-ui/src/types/plugin.ts b/config-ui/src/types/plugin.ts index 3639fc96043..4748276ad01 100644 --- a/config-ui/src/types/plugin.ts +++ b/config-ui/src/types/plugin.ts @@ -22,6 +22,8 @@ export interface IPluginConfig { icon: ({ color }: { color: string }) => React.ReactNode; sort: number; isBeta?: boolean; + isDeprecated?: boolean; + deprecationMessage?: string; connection: { docLink: string; initialValues?: Record;