Skip to content

Commit 33f001a

Browse files
committed
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
1 parent e355317 commit 33f001a

10 files changed

Lines changed: 97 additions & 3 deletions

File tree

‎backend/core/plugin/plugin_meta.go‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ type PluginIcon interface {
4444
SvgIcon() string
4545
}
4646

47+
// PluginDeprecation is implemented by plugins that have been deprecated.
48+
// The DeprecationMessage should describe why the plugin is deprecated and
49+
// what users should migrate to. Returns an empty string for non-deprecated
50+
// plugins.
51+
type PluginDeprecation interface {
52+
DeprecationMessage() string
53+
}
54+
4755
// PluginSource abstracts data sources
4856
type PluginSource interface {
4957
Connection() dal.Tabler

‎backend/core/runner/loader.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ func LoadGoPlugins(basicRes context.BasicRes) errors.Error {
9191
func LoadRemotePlugins(basicRes context.BasicRes) errors.Error {
9292
remotePluginDir := basicRes.GetConfig("REMOTE_PLUGIN_DIR")
9393
if remotePluginDir != "" {
94+
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).")
9495
basicRes.GetLogger().Info("Loading remote plugins")
9596
remote.Init(basicRes)
9697
walkErr := filepath.WalkDir(remotePluginDir, func(path string, d fs.DirEntry, err error) error {

‎backend/python/README.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,28 @@ limitations under the License.
1616
-->
1717
# Pydevlake
1818

19+
> **⚠️ DEPRECATED — Scheduled for removal.**
20+
> The Python plugin framework (PyDevLake) is deprecated and will be removed from
21+
> Apache DevLake in 3 months per the deprecation plan in
22+
> [#9092](https://github.com/apache/devlake/issues/9092).
23+
>
24+
> Reasons:
25+
> - Only one plugin (`azuredevops`) ever shipped on this framework; the `dbt`
26+
> plugin was already removed (#8970).
27+
> - No feature/fix commits to Python plugins since Dec 2025; only dependency
28+
> refreshes and runtime bumps land.
29+
> - A fully-featured Go implementation, `azuredevops_go`, now supersedes the
30+
> Python `azuredevops` plugin (including on-premises support, #9014).
31+
>
32+
> **What you should do:**
33+
> - New plugins: write them in **Go**. See `backend/plugins/` for 40+ reference
34+
> implementations.
35+
> - Existing `azuredevops` (Python) users: migrate to `azuredevops_go` (a
36+
> migration guide will be published during the deprecation window).
37+
>
38+
> No new Python plugins will be accepted. Only critical security fixes will land
39+
> during the deprecation window.
40+
1941
Pydevlake is a framework for writing plugins for [DevLake](https://devlake.apache.org/) in Python. The framework source code
2042
can be found in [here](./pydevlake).
2143

‎backend/python/plugins/azuredevops/README.md‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17-
# Azure Devops Python Plugin
17+
# Azure Devops Python Plugin
18+
19+
> **⚠️ DEPRECATED — Scheduled for removal in 3 months.**
20+
> This Python `azuredevops` plugin is deprecated in favor of the Go-based
21+
> [`azuredevops_go`](../../plugins/azuredevops_go) plugin, which has broader
22+
> feature coverage (including Azure DevOps Server / on-premises support, #9014).
23+
>
24+
> Please migrate existing connections and scopes to `azuredevops_go`. A migration
25+
> guide will be published during the deprecation window — see
26+
> [#9092](https://github.com/apache/devlake/issues/9092) for the full plan and
27+
> timeline.
28+
>
29+
> No new features or fixes (other than critical security fixes) will be accepted
30+
> on this plugin.

‎backend/server/api/plugininfo/plugininifo.go‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ type PluginMetric struct {
7575
}
7676

7777
type PluginMeta struct {
78-
Plugin string `json:"plugin"`
79-
Metric PluginMetric `json:"metric"`
78+
Plugin string `json:"plugin"`
79+
Metric PluginMetric `json:"metric"`
80+
Deprecated bool `json:"deprecated"`
8081
}
8182

8283
type PluginMetas []PluginMeta
@@ -207,6 +208,10 @@ func GetPluginMetas(c *gin.Context) {
207208
Plugin: name,
208209
}
209210

211+
if dp, ok := p.(plugin.PluginDeprecation); ok {
212+
pluginMeta.Deprecated = dp.DeprecationMessage() != ""
213+
}
214+
210215
// if this plugin has the plugin task info
211216
if pt, ok := p.(plugin.PluginMetric); ok {
212217
var err1 errors.Error

‎backend/server/services/remote/plugin/plugin_impl.go‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,4 +238,16 @@ func (p *remotePluginImpl) MigrationScripts() []plugin.MigrationScript {
238238
return append(p.migrationScripts, migrationscripts.All(p.name)...)
239239
}
240240

241+
// DeprecationMessage implements plugin.PluginDeprecation. All remote (Python)
242+
// plugins are deprecated and scheduled for removal in 3 months per the
243+
// deprecation plan in issue #9092.
244+
func (p *remotePluginImpl) DeprecationMessage() string {
245+
return fmt.Sprintf(
246+
"This Python plugin (%s) is DEPRECATED and will be removed in 3 months. "+
247+
"Please migrate to the Go-based equivalent. "+
248+
"See https://github.com/apache/devlake/issues/9092 for the deprecation plan and migration guide.",
249+
p.name,
250+
)
251+
}
252+
241253
var _ models.RemotePlugin = (*remotePluginImpl)(nil)

‎config-ui/src/plugins/register/azure/config.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export const AzureConfig: IPluginConfig = {
2828
name: 'Azure DevOps',
2929
icon: ({ color }) => <Icon fill={color} />,
3030
sort: 2,
31+
isDeprecated: true,
32+
deprecationMessage:
33+
'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.',
3134
connection: {
3235
docLink: DOC_URL.PLUGIN.AZUREDEVOPS.BASIS,
3336
initialValues: {},

‎config-ui/src/routes/connection/connections.tsx‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,12 @@ export const Connections = () => {
9595
return (
9696
<li key={plugin} onClick={() => handleShowListDialog(plugin)}>
9797
{pluginConfig.isBeta && <span className="beta">Beta</span>}
98+
{pluginConfig.isDeprecated && <span className="deprecated">Deprecated</span>}
9899
<span className="logo">{pluginConfig.icon({ color: colorPrimary })}</span>
99100
<span className="name">{pluginConfig.name}</span>
101+
{pluginConfig.isDeprecated && pluginConfig.deprecationMessage && (
102+
<span className="deprecation-note">{pluginConfig.deprecationMessage}</span>
103+
)}
100104
<span className="count">
101105
{connectionCount ? (
102106
<Badge color={colorPrimary} text={`${connectionCount} connections`} />
@@ -116,8 +120,12 @@ export const Connections = () => {
116120
return (
117121
<li key={plugin} onClick={() => handleShowListDialog(plugin)}>
118122
{pluginConfig.isBeta && <span className="beta">Beta</span>}
123+
{pluginConfig.isDeprecated && <span className="deprecated">Deprecated</span>}
119124
<span className="logo">{pluginConfig.icon({ color: colorPrimary })}</span>
120125
<span className="name">{pluginConfig.name}</span>
126+
{pluginConfig.isDeprecated && pluginConfig.deprecationMessage && (
127+
<span className="deprecation-note">{pluginConfig.deprecationMessage}</span>
128+
)}
121129
<span className="count">
122130
{connectionCount ? (
123131
<Badge color={colorPrimary} text={`${connectionCount} connections`} />

‎config-ui/src/routes/connection/styled.ts‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,26 @@ export const Wrapper = styled.div`
8282
border-radius: 8px;
8383
}
8484
85+
& > .deprecated {
86+
position: absolute;
87+
top: 0;
88+
left: 0;
89+
padding: 4px 8px;
90+
font-size: 12px;
91+
color: ${({ theme }) => theme.colors.textInverse};
92+
background-color: ${({ theme }) => theme.colors.error};
93+
border-radius: 8px;
94+
}
95+
96+
& > .deprecation-note {
97+
margin-top: 4px;
98+
padding: 0 8px;
99+
font-size: 11px;
100+
line-height: 1.4;
101+
color: ${({ theme }) => theme.colors.error};
102+
text-align: center;
103+
}
104+
85105
& > .logo {
86106
width: 60px;
87107
height: 60px;

‎config-ui/src/types/plugin.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export interface IPluginConfig {
2222
icon: ({ color }: { color: string }) => React.ReactNode;
2323
sort: number;
2424
isBeta?: boolean;
25+
isDeprecated?: boolean;
26+
deprecationMessage?: string;
2527
connection: {
2628
docLink: string;
2729
initialValues?: Record<string, any>;

0 commit comments

Comments
 (0)