diff --git a/backend/.sqlx/query-362419eb262c83d6a98a0200b116e831ada60399fe5f55a56d930cc69aff2675.json b/backend/.sqlx/query-362419eb262c83d6a98a0200b116e831ada60399fe5f55a56d930cc69aff2675.json new file mode 100644 index 0000000000..183062aa6d --- /dev/null +++ b/backend/.sqlx/query-362419eb262c83d6a98a0200b116e831ada60399fe5f55a56d930cc69aff2675.json @@ -0,0 +1,29 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT s.hash as hash, dm.deployment_msg as deployment_msg \n FROM script s LEFT JOIN deployment_metadata dm ON s.hash = dm.script_hash\n WHERE s.workspace_id = $1 AND s.path = $2\n ORDER by created_at DESC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "hash", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "deployment_msg", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + false, + true + ] + }, + "hash": "362419eb262c83d6a98a0200b116e831ada60399fe5f55a56d930cc69aff2675" +} diff --git a/backend/.sqlx/query-652835b2b7f801532a591988ac76d385188991c6654d529f6d65f6f03794844a.json b/backend/.sqlx/query-652835b2b7f801532a591988ac76d385188991c6654d529f6d65f6f03794844a.json new file mode 100644 index 0000000000..91e268889d --- /dev/null +++ b/backend/.sqlx/query-652835b2b7f801532a591988ac76d385188991c6654d529f6d65f6f03794844a.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO deployment_metadata (workspace_id, path, app_version, deployment_msg) VALUES ($1, $2, $3, $4) ON CONFLICT (workspace_id, path, app_version) WHERE app_version IS NOT NULL DO UPDATE SET deployment_msg = $4", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Int8", + "Text" + ] + }, + "nullable": [] + }, + "hash": "652835b2b7f801532a591988ac76d385188991c6654d529f6d65f6f03794844a" +} diff --git a/backend/.sqlx/query-abb56dec024600d0d7a63212f63c3296196898003707f2cb3a890690173a51a5.json b/backend/.sqlx/query-abb56dec024600d0d7a63212f63c3296196898003707f2cb3a890690173a51a5.json new file mode 100644 index 0000000000..df1b7fab40 --- /dev/null +++ b/backend/.sqlx/query-abb56dec024600d0d7a63212f63c3296196898003707f2cb3a890690173a51a5.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT path FROM app WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "path", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + }, + "hash": "abb56dec024600d0d7a63212f63c3296196898003707f2cb3a890690173a51a5" +} diff --git a/backend/.sqlx/query-d02c1cfefc7d5f87ca4555a092f5fbc777a91271b80d0e488a8cae79afd56d8f.json b/backend/.sqlx/query-d02c1cfefc7d5f87ca4555a092f5fbc777a91271b80d0e488a8cae79afd56d8f.json new file mode 100644 index 0000000000..f90af3cca7 --- /dev/null +++ b/backend/.sqlx/query-d02c1cfefc7d5f87ca4555a092f5fbc777a91271b80d0e488a8cae79afd56d8f.json @@ -0,0 +1,35 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT a.id as app_id, av.id as version_id, dm.deployment_msg as deployment_msg\n FROM app a LEFT JOIN app_version av ON a.id = av.app_id LEFT JOIN deployment_metadata dm ON av.id = dm.app_version\n WHERE a.workspace_id = $1 AND a.path = $2\n ORDER BY created_at DESC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "app_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "version_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "deployment_msg", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + false, + false, + true + ] + }, + "hash": "d02c1cfefc7d5f87ca4555a092f5fbc777a91271b80d0e488a8cae79afd56d8f" +} diff --git a/backend/.sqlx/query-db558b5ecdc4c3b1af0def511f1bcd91a548f00376f644c8ba38f73812b462d0.json b/backend/.sqlx/query-db558b5ecdc4c3b1af0def511f1bcd91a548f00376f644c8ba38f73812b462d0.json new file mode 100644 index 0000000000..1e36101464 --- /dev/null +++ b/backend/.sqlx/query-db558b5ecdc4c3b1af0def511f1bcd91a548f00376f644c8ba38f73812b462d0.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO deployment_metadata (workspace_id, path, script_hash, deployment_msg) VALUES ($1, $2, $3, $4) ON CONFLICT (workspace_id, script_hash) WHERE script_hash IS NOT NULL DO UPDATE SET deployment_msg = $4", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Int8", + "Text" + ] + }, + "nullable": [] + }, + "hash": "db558b5ecdc4c3b1af0def511f1bcd91a548f00376f644c8ba38f73812b462d0" +} diff --git a/backend/windmill-api/openapi-deref.yaml b/backend/windmill-api/openapi-deref.yaml index 230eb7371d..c7f091e90a 100644 --- a/backend/windmill-api/openapi-deref.yaml +++ b/backend/windmill-api/openapi-deref.yaml @@ -231,34 +231,34 @@ paths: - name: before description: filter on created before (exclusive) timestamp in: query - schema: &ref_99 + schema: &ref_100 type: string format: date-time - name: after description: filter on created after (exclusive) timestamp in: query - schema: &ref_98 + schema: &ref_99 type: string format: date-time - name: username description: filter on exact username of user in: query - schema: &ref_100 + schema: &ref_101 type: string - name: operation description: filter on exact or prefix name of operation in: query - schema: &ref_101 + schema: &ref_102 type: string - name: resource description: filter on exact or prefix name of resource in: query - schema: &ref_102 + schema: &ref_103 type: string - name: action_kind description: filter on type of operation in: query - schema: &ref_103 + schema: &ref_104 type: string enum: - Create @@ -290,12 +290,12 @@ paths: application/json: schema: type: object - properties: &ref_113 + properties: &ref_116 email: type: string password: type: string - required: &ref_114 + required: &ref_117 - email - password responses: @@ -351,14 +351,14 @@ paths: application/json: schema: type: object - properties: &ref_115 + properties: &ref_118 email: type: string username: type: string is_admin: type: boolean - required: &ref_116 + required: &ref_119 - email - username - is_admin @@ -393,7 +393,7 @@ paths: application/json: schema: type: object - properties: &ref_117 + properties: &ref_120 is_admin: type: boolean operator: @@ -616,7 +616,7 @@ paths: application/json: schema: type: object - properties: &ref_145 + properties: &ref_148 email: type: string workspaces: @@ -634,7 +634,7 @@ paths: - id - name - username - required: &ref_146 + required: &ref_149 - email - workspaces /workspaces/list_as_superadmin: @@ -676,14 +676,14 @@ paths: application/json: schema: type: object - properties: &ref_147 + properties: &ref_150 id: type: string name: type: string username: type: string - required: &ref_148 + required: &ref_151 - id - name - username @@ -1124,7 +1124,7 @@ paths: type: string usage: type: object - properties: &ref_112 + properties: &ref_115 executions: type: number required: &ref_9 @@ -1972,7 +1972,7 @@ paths: application/json: schema: type: object - properties: &ref_120 + properties: &ref_123 label: type: string expiration: @@ -2002,7 +2002,7 @@ paths: application/json: schema: type: object - properties: &ref_121 + properties: &ref_124 label: type: string expiration: @@ -2010,7 +2010,7 @@ paths: format: date-time impersonate_email: type: string - required: &ref_122 + required: &ref_125 - impersonate_email responses: '201': @@ -2058,7 +2058,7 @@ paths: type: array items: type: object - properties: &ref_118 + properties: &ref_121 label: type: string expiration: @@ -2076,7 +2076,7 @@ paths: type: array items: type: string - required: &ref_119 + required: &ref_122 - token_prefix - created_at - last_used_at @@ -2102,7 +2102,7 @@ paths: application/json: schema: type: object - properties: &ref_125 + properties: &ref_128 path: type: string value: @@ -2115,7 +2115,7 @@ paths: type: integer is_oauth: type: boolean - required: &ref_126 + required: &ref_129 - path - value - is_secret @@ -2200,7 +2200,7 @@ paths: application/json: schema: type: object - properties: &ref_127 + properties: &ref_130 path: type: string value: @@ -2363,14 +2363,14 @@ paths: type: array items: type: object - properties: &ref_123 + properties: &ref_126 name: type: string value: type: string description: type: string - required: &ref_124 + required: &ref_127 - name - value - description @@ -2481,7 +2481,7 @@ paths: application/json: schema: type: object - properties: &ref_159 + properties: &ref_164 access_token: type: string expires_in: @@ -2492,7 +2492,7 @@ paths: type: array items: type: string - required: &ref_160 + required: &ref_165 - access_token /w/{workspace}/oauth/create_account: post: @@ -2673,7 +2673,7 @@ paths: application/json: schema: type: object - properties: &ref_130 + properties: &ref_133 path: type: string value: {} @@ -2681,7 +2681,7 @@ paths: type: string resource_type: type: string - required: &ref_131 + required: &ref_134 - path - value - resource_type @@ -2736,7 +2736,7 @@ paths: application/json: schema: type: object - properties: &ref_132 + properties: &ref_135 path: type: string description: @@ -2802,7 +2802,7 @@ paths: application/json: schema: type: object - properties: &ref_133 + properties: &ref_136 workspace_id: type: string path: @@ -2818,7 +2818,7 @@ paths: type: object additionalProperties: type: boolean - required: &ref_134 + required: &ref_137 - path - resource_type - is_oauth @@ -2930,7 +2930,7 @@ paths: type: array items: type: object - properties: &ref_135 + properties: &ref_138 workspace_id: type: string path: @@ -2956,7 +2956,7 @@ paths: type: boolean account: type: number - required: &ref_136 + required: &ref_139 - path - resource_type - is_oauth @@ -3101,7 +3101,7 @@ paths: application/json: schema: type: object - properties: &ref_137 + properties: &ref_140 schema: {} description: type: string @@ -3345,32 +3345,32 @@ paths: id: type: string value: - oneOf: &ref_186 + oneOf: &ref_191 - type: object - properties: &ref_170 + properties: &ref_175 input_transforms: type: object additionalProperties: oneOf: &ref_26 - type: object - properties: &ref_166 + properties: &ref_171 value: {} type: type: string enum: - javascript - required: &ref_167 + required: &ref_172 - expr - type - type: object - properties: &ref_168 + properties: &ref_173 expr: type: string type: type: string enum: - javascript - required: &ref_169 + required: &ref_174 - expr - type discriminator: &ref_27 @@ -3410,13 +3410,13 @@ paths: type: number concurrency_time_window_s: type: number - required: &ref_171 + required: &ref_176 - type - content - language - input_transforms - type: object - properties: &ref_172 + properties: &ref_177 input_transforms: type: object additionalProperties: @@ -3430,12 +3430,12 @@ paths: type: string enum: - script - required: &ref_173 + required: &ref_178 - type - path - input_transforms - type: object - properties: &ref_174 + properties: &ref_179 input_transforms: type: object additionalProperties: @@ -3447,12 +3447,12 @@ paths: type: string enum: - flow - required: &ref_175 + required: &ref_180 - type - path - input_transforms - type: object - properties: &ref_176 + properties: &ref_181 modules: type: array items: @@ -3474,13 +3474,13 @@ paths: type: boolean parallelism: type: integer - required: &ref_177 + required: &ref_182 - modules - iterator - skip_failures - type - type: object - properties: &ref_178 + properties: &ref_183 branches: type: array items: @@ -3511,12 +3511,12 @@ paths: type: string enum: - branchone - required: &ref_179 + required: &ref_184 - branches - default - type - type: object - properties: &ref_180 + properties: &ref_185 branches: type: array items: @@ -3541,28 +3541,28 @@ paths: - branchall parallel: type: boolean - required: &ref_181 + required: &ref_186 - branches - type - type: object - properties: &ref_182 + properties: &ref_187 type: type: string enum: - identity flow: type: boolean - required: &ref_183 + required: &ref_188 - type - type: object - properties: &ref_184 + properties: &ref_189 type: type: string enum: - graphql - required: &ref_185 + required: &ref_190 - type - discriminator: &ref_187 + discriminator: &ref_192 propertyName: type mapping: rawscript: '#/components/schemas/RawScript' @@ -3620,7 +3620,7 @@ paths: type: number retry: type: object - properties: &ref_188 + properties: &ref_193 constant: type: object properties: @@ -4551,7 +4551,7 @@ paths: content: application/json: schema: - allOf: &ref_106 + allOf: &ref_107 - type: object properties: *ref_35 required: *ref_36 @@ -4565,6 +4565,73 @@ paths: type: string required: - hash + /w/{workspace}/scripts/history/p/{path}: + get: + summary: get history of a script by path + operationId: getScriptHistoryByPath + tags: + - script + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_30 + responses: + '200': + description: script history + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_108 + script_hash: + type: string + deployment_msg: + type: string + required: &ref_109 + - script_hash + /w/{workspace}/scripts/history_update/h/{hash}/p/{path}: + post: + summary: update history of a script + operationId: updateScriptHistory + tags: + - script + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: hash + in: path + required: true + schema: *ref_34 + - name: path + in: path + required: true + schema: *ref_30 + requestBody: + description: Script deployment message + required: true + content: + application/json: + schema: + type: object + properties: + deployment_msg: + type: string + responses: + '200': + description: success + content: + text/plain: + schema: + type: string /w/{workspace}/scripts/raw/p/{path}: get: summary: raw script by path @@ -5201,7 +5268,7 @@ paths: properties: *ref_43 required: *ref_44 - type: object - properties: &ref_149 + properties: &ref_152 workspace_id: type: string path: @@ -5231,7 +5298,7 @@ paths: type: boolean timeout: type: number - required: &ref_150 + required: &ref_153 - path - edited_by - edited_at @@ -5586,7 +5653,7 @@ paths: type: array items: type: object - properties: &ref_156 + properties: &ref_159 workspace_id: type: string path: @@ -5604,7 +5671,7 @@ paths: edited_at: type: string format: date-time - required: &ref_157 + required: &ref_160 - workspace_id - path - summary @@ -5740,7 +5807,7 @@ paths: type: array items: type: object - properties: &ref_154 + properties: &ref_157 id: type: integer workspace_id: @@ -5766,7 +5833,7 @@ paths: - viewer - publisher - anonymous - required: &ref_155 + required: &ref_158 - id - workspace_id - path @@ -5939,7 +6006,7 @@ paths: content: application/json: schema: - allOf: &ref_158 + allOf: &ref_161 - type: object properties: *ref_48 required: *ref_49 @@ -5948,6 +6015,74 @@ paths: draft_only: type: boolean draft: {} + /w/{workspace}/apps/history/p/{path}: + get: + summary: get app history by path + operationId: getAppHistoryByPath + tags: + - app + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_30 + responses: + '200': + description: app history + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_162 + version: + type: integer + deployment_msg: + type: string + required: &ref_163 + - version + /w/{workspace}/apps/history_update/a/{id}/v/{version}: + post: + summary: update app history + operationId: updateAppHistory + tags: + - app + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: id + in: path + required: true + schema: *ref_25 + - name: version + in: path + required: true + schema: &ref_95 + type: integer + requestBody: + description: App deployment message + required: true + content: + application/json: + schema: + type: object + properties: + deployment_msg: + type: string + responses: + '200': + description: success + content: + text/plain: + schema: + type: string /w/{workspace}/apps_u/public_app/{path}: get: summary: get public app by secret @@ -6512,7 +6647,7 @@ paths: application/json: schema: type: object - properties: &ref_128 + properties: &ref_131 content: type: string path: @@ -6546,7 +6681,7 @@ paths: - http dedicated_worker: type: boolean - required: &ref_129 + required: &ref_132 - args responses: '201': @@ -6596,7 +6731,7 @@ paths: application/json: schema: type: object - properties: &ref_151 + properties: &ref_154 value: type: object properties: *ref_50 @@ -6610,7 +6745,7 @@ paths: type: string restarted_from: type: object - properties: &ref_153 + properties: &ref_156 flow_job_id: type: string format: uuid @@ -6618,7 +6753,7 @@ paths: type: string branch_or_iteration_n: type: integer - required: &ref_152 + required: &ref_155 - value - content - args @@ -6702,7 +6837,7 @@ paths: - name: suspended description: filter on suspended jobs in: query - schema: &ref_97 + schema: &ref_98 type: boolean - name: running description: filter on running jobs @@ -7267,7 +7402,7 @@ paths: filter on created_at for non non started job and started_at otherwise before (inclusive) timestamp in: query - schema: &ref_96 + schema: &ref_97 type: string format: date-time - name: running @@ -7279,7 +7414,7 @@ paths: filter on created_at for non non started job and started_at otherwise after (exclusive) timestamp in: query - schema: &ref_95 + schema: &ref_96 type: string format: date-time - name: job_kinds @@ -7503,7 +7638,7 @@ paths: schema: *ref_72 - name: get_started in: query - schema: &ref_105 + schema: &ref_106 type: boolean responses: '200': @@ -7976,7 +8111,7 @@ paths: application/json: schema: type: object - properties: &ref_139 + properties: &ref_142 path: type: string schedule: @@ -8010,7 +8145,7 @@ paths: additionalProperties: *ref_14 ws_error_handler_muted: type: boolean - required: &ref_140 + required: &ref_143 - path - schedule - timezone @@ -8046,7 +8181,7 @@ paths: application/json: schema: type: object - properties: &ref_141 + properties: &ref_144 schedule: type: string timezone: @@ -8072,7 +8207,7 @@ paths: additionalProperties: *ref_14 ws_error_handler_muted: type: boolean - required: &ref_142 + required: &ref_145 - schedule - timezone - script_path @@ -8309,7 +8444,7 @@ paths: schema: type: array items: - allOf: &ref_138 + allOf: &ref_141 - type: object properties: *ref_76 required: *ref_77 @@ -8976,7 +9111,7 @@ paths: type: array items: type: object - properties: &ref_143 + properties: &ref_146 worker: type: string worker_instance: @@ -8998,7 +9133,7 @@ paths: type: string wm_version: type: string - required: &ref_144 + required: &ref_147 - worker - worker_instance - ping_at @@ -9361,7 +9496,7 @@ paths: in: query schema: &ref_88 type: string - enum: &ref_111 + enum: &ref_114 - ScriptHash - ScriptPath - FlowPath @@ -9444,12 +9579,12 @@ paths: application/json: schema: type: object - properties: &ref_107 + properties: &ref_110 name: type: string args: type: object - required: &ref_108 + required: &ref_111 - name - args - created_by @@ -9479,14 +9614,14 @@ paths: application/json: schema: type: object - properties: &ref_109 + properties: &ref_112 id: type: string name: type: string is_public: type: boolean - required: &ref_110 + required: &ref_113 - id - name - is_public @@ -9512,7 +9647,7 @@ paths: - name: input in: path required: true - schema: &ref_104 + schema: &ref_105 type: string responses: '200': @@ -9794,10 +9929,10 @@ paths: type: array items: type: object - properties: &ref_161 + properties: &ref_166 s3: type: string - required: &ref_162 + required: &ref_167 - s3 required: - windmill_large_files @@ -9824,7 +9959,7 @@ paths: application/json: schema: type: object - properties: &ref_163 + properties: &ref_168 mime_type: type: string size_in_bytes: @@ -9884,7 +10019,7 @@ paths: application/json: schema: type: object - properties: &ref_164 + properties: &ref_169 msg: type: string content: @@ -9896,7 +10031,7 @@ paths: - Csv - Parquet - Unknown - required: &ref_165 + required: &ref_170 - content_type components: securitySchemes: @@ -9963,6 +10098,11 @@ components: in: path required: true schema: *ref_25 + PathVersion: + name: version + in: path + required: true + schema: *ref_95 Name: name: name in: path @@ -10065,14 +10205,14 @@ components: filter on created_at for non non started job and started_at otherwise after (exclusive) timestamp in: query - schema: *ref_95 + schema: *ref_96 CreatedOrStartedBefore: name: created_or_started_before description: >- filter on created_at for non non started job and started_at otherwise before (inclusive) timestamp in: query - schema: *ref_96 + schema: *ref_97 Success: name: success description: filter on successful jobs @@ -10082,7 +10222,7 @@ components: name: suspended description: filter on suspended jobs in: query - schema: *ref_97 + schema: *ref_98 Running: name: running description: filter on running jobs @@ -10107,32 +10247,32 @@ components: name: after description: filter on created after (exclusive) timestamp in: query - schema: *ref_98 + schema: *ref_99 Before: name: before description: filter on created before (exclusive) timestamp in: query - schema: *ref_99 + schema: *ref_100 Username: name: username description: filter on exact username of user in: query - schema: *ref_100 + schema: *ref_101 Operation: name: operation description: filter on exact or prefix name of operation in: query - schema: *ref_101 + schema: *ref_102 ResourceName: name: resource description: filter on exact or prefix name of resource in: query - schema: *ref_102 + schema: *ref_103 ActionKind: name: action_kind description: filter on type of operation in: query - schema: *ref_103 + schema: *ref_104 JobKinds: name: job_kinds description: >- @@ -10152,11 +10292,11 @@ components: name: input in: path required: true - schema: *ref_104 + schema: *ref_105 GetStarted: name: get_started in: query - schema: *ref_105 + schema: *ref_106 schemas: Script: type: object @@ -10167,7 +10307,11 @@ components: properties: *ref_35 required: *ref_36 NewScriptWithDraft: - allOf: *ref_106 + allOf: *ref_107 + ScriptHistory: + type: object + properties: *ref_108 + required: *ref_109 ScriptArgs: type: object additionalProperties: *ref_14 @@ -10177,15 +10321,15 @@ components: required: *ref_86 CreateInput: type: object - properties: *ref_107 - required: *ref_108 + properties: *ref_110 + required: *ref_111 UpdateInput: type: object - properties: *ref_109 - required: *ref_110 + properties: *ref_112 + required: *ref_113 RunnableType: type: string - enum: *ref_111 + enum: *ref_114 QueuedJob: type: object properties: *ref_70 @@ -10203,44 +10347,44 @@ components: required: *ref_9 Usage: type: object - properties: *ref_112 + properties: *ref_115 Login: type: object - properties: *ref_113 - required: *ref_114 + properties: *ref_116 + required: *ref_117 NewUser: - type: object - properties: *ref_115 - required: *ref_116 - EditWorkspaceUser: - type: object - properties: *ref_117 - TruncatedToken: type: object properties: *ref_118 required: *ref_119 - NewToken: + EditWorkspaceUser: type: object properties: *ref_120 - NewTokenImpersonate: + TruncatedToken: type: object properties: *ref_121 required: *ref_122 + NewToken: + type: object + properties: *ref_123 + NewTokenImpersonate: + type: object + properties: *ref_124 + required: *ref_125 ListableVariable: type: object properties: *ref_19 required: *ref_20 ContextualVariable: type: object - properties: *ref_123 - required: *ref_124 + properties: *ref_126 + required: *ref_127 CreateVariable: type: object - properties: *ref_125 - required: *ref_126 + properties: *ref_128 + required: *ref_129 EditVariable: type: object - properties: *ref_127 + properties: *ref_130 AuditLog: type: object properties: *ref_1 @@ -10364,44 +10508,44 @@ components: - error Preview: type: object - properties: *ref_128 - required: *ref_129 + properties: *ref_131 + required: *ref_132 CreateResource: - type: object - properties: *ref_130 - required: *ref_131 - EditResource: - type: object - properties: *ref_132 - Resource: type: object properties: *ref_133 required: *ref_134 - ListableResource: + EditResource: type: object properties: *ref_135 - required: *ref_136 + Resource: + type: object + properties: *ref_136 + required: *ref_137 + ListableResource: + type: object + properties: *ref_138 + required: *ref_139 ResourceType: type: object properties: *ref_23 required: *ref_24 EditResourceType: type: object - properties: *ref_137 + properties: *ref_140 Schedule: type: object properties: *ref_76 required: *ref_77 ScheduleWJobs: - allOf: *ref_138 + allOf: *ref_141 NewSchedule: type: object - properties: *ref_139 - required: *ref_140 + properties: *ref_142 + required: *ref_143 EditSchedule: type: object - properties: *ref_141 - required: *ref_142 + properties: *ref_144 + required: *ref_145 Group: type: object properties: *ref_81 @@ -10416,16 +10560,16 @@ components: required: *ref_84 WorkerPing: type: object - properties: *ref_143 - required: *ref_144 + properties: *ref_146 + required: *ref_147 UserWorkspaceList: type: object - properties: *ref_145 - required: *ref_146 + properties: *ref_148 + required: *ref_149 CreateWorkspace: type: object - properties: *ref_147 - required: *ref_148 + properties: *ref_150 + required: *ref_151 Workspace: type: object properties: *ref_5 @@ -10442,34 +10586,38 @@ components: allOf: *ref_45 FlowMetadata: type: object - properties: *ref_149 - required: *ref_150 + properties: *ref_152 + required: *ref_153 OpenFlowWPath: allOf: *ref_46 FlowPreview: type: object - properties: *ref_151 - required: *ref_152 + properties: *ref_154 + required: *ref_155 RestartedFrom: type: object - properties: *ref_153 + properties: *ref_156 Policy: type: object properties: *ref_47 ListableApp: type: object - properties: *ref_154 - required: *ref_155 + properties: *ref_157 + required: *ref_158 ListableRawApp: type: object - properties: *ref_156 - required: *ref_157 + properties: *ref_159 + required: *ref_160 AppWithLastVersion: type: object properties: *ref_48 required: *ref_49 AppWithLastVersionWDraft: - allOf: *ref_158 + allOf: *ref_161 + AppHistory: + type: object + properties: *ref_162 + required: *ref_163 SlackToken: type: object properties: @@ -10491,8 +10639,8 @@ components: - bot TokenResponse: type: object - properties: *ref_159 - required: *ref_160 + properties: *ref_164 + required: *ref_165 HubScriptKind: name: kind schema: *ref_31 @@ -10505,15 +10653,15 @@ components: properties: *ref_15 WindmillLargeFile: type: object - properties: *ref_161 - required: *ref_162 + properties: *ref_166 + required: *ref_167 WindmillFileMetadata: type: object - properties: *ref_163 + properties: *ref_168 WindmillFilePreview: type: object - properties: *ref_164 - required: *ref_165 + properties: *ref_169 + required: *ref_170 S3Resource: type: object properties: *ref_89 @@ -10524,57 +10672,57 @@ components: required: *ref_17 StaticTransform: type: object - properties: *ref_166 - required: *ref_167 + properties: *ref_171 + required: *ref_172 JavascriptTransform: type: object - properties: *ref_168 - required: *ref_169 + properties: *ref_173 + required: *ref_174 InputTransform: oneOf: *ref_26 discriminator: *ref_27 RawScript: type: object - properties: *ref_170 - required: *ref_171 + properties: *ref_175 + required: *ref_176 PathScript: type: object - properties: *ref_172 - required: *ref_173 + properties: *ref_177 + required: *ref_178 PathFlow: type: object - properties: *ref_174 - required: *ref_175 + properties: *ref_179 + required: *ref_180 FlowModule: type: object properties: *ref_28 required: *ref_29 ForloopFlow: type: object - properties: *ref_176 - required: *ref_177 + properties: *ref_181 + required: *ref_182 BranchOne: type: object - properties: *ref_178 - required: *ref_179 + properties: *ref_183 + required: *ref_184 BranchAll: type: object - properties: *ref_180 - required: *ref_181 + properties: *ref_185 + required: *ref_186 Identity: type: object - properties: *ref_182 - required: *ref_183 + properties: *ref_187 + required: *ref_188 Graphql: type: object - properties: *ref_184 - required: *ref_185 + properties: *ref_189 + required: *ref_190 FlowModuleValue: - oneOf: *ref_186 - discriminator: *ref_187 + oneOf: *ref_191 + discriminator: *ref_192 Retry: type: object - properties: *ref_188 + properties: *ref_193 FlowValue: type: object properties: *ref_50 diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 64c375a968..1ac5c0dcdb 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -3225,6 +3225,53 @@ paths: schema: $ref: "#/components/schemas/NewScriptWithDraft" + /w/{workspace}/scripts/history/p/{path}: + get: + summary: get history of a script by path + operationId: getScriptHistoryByPath + tags: + - script + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/ScriptPath" + responses: + "200": + description: script history + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/ScriptHistory" + + /w/{workspace}/scripts/history_update/h/{hash}/p/{path}: + post: + summary: update history of a script + operationId: updateScriptHistory + tags: + - script + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/ScriptHash" + - $ref: "#/components/parameters/ScriptPath" + requestBody: + description: Script deployment message + required: true + content: + application/json: + schema: + type: object + properties: + deployment_msg: + type: string + responses: + "200": + description: success + content: + text/plain: + schema: + type: string + /w/{workspace}/scripts/raw/p/{path}: get: summary: raw script by path @@ -4065,6 +4112,53 @@ paths: schema: $ref: "#/components/schemas/AppWithLastVersionWDraft" + /w/{workspace}/apps/history/p/{path}: + get: + summary: get app history by path + operationId: getAppHistoryByPath + tags: + - app + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/ScriptPath" + responses: + "200": + description: app history + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/AppHistory" + + /w/{workspace}/apps/history_update/a/{id}/v/{version}: + post: + summary: update app history + operationId: updateAppHistory + tags: + - app + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/PathId" + - $ref: "#/components/parameters/PathVersion" + requestBody: + description: App deployment message + required: true + content: + application/json: + schema: + type: object + properties: + deployment_msg: + type: string + responses: + "200": + description: success + content: + text/plain: + schema: + type: string + /w/{workspace}/apps_u/public_app/{path}: get: summary: get public app by secret @@ -6695,6 +6789,12 @@ components: required: true schema: type: integer + PathVersion: + name: version + in: path + required: true + schema: + type: integer Name: name: name in: path @@ -7133,6 +7233,16 @@ components: required: - hash + ScriptHistory: + type: object + properties: + script_hash: + type: string + deployment_msg: + type: string + required: + - script_hash + ScriptArgs: type: object additionalProperties: {} @@ -8572,6 +8682,16 @@ components: type: boolean draft: {} + AppHistory: + type: object + properties: + version: + type: integer + deployment_msg: + type: string + required: + - version + SlackToken: type: object properties: diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index 2890fe4266..dbf06cc646 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -55,6 +55,8 @@ pub fn workspaced_service() -> Router { .route("/update/*path", post(update_app)) .route("/delete/*path", delete(delete_app)) .route("/create", post(create_app)) + .route("/history/p/*path", get(get_app_history)) + .route("/history_update/a/:id/v/:version", post(update_app_history)) } pub fn unauthed_service() -> Router { @@ -125,6 +127,19 @@ pub struct AppWithLastVersionAndDraft { pub draft_only: Option, } +#[derive(Serialize)] +pub struct AppHistory { + pub app_id: i64, + pub version: i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub deployment_msg: Option, +} + +#[derive(Deserialize)] +pub struct AppHistoryUpdate { + pub deployment_msg: Option, +} + pub type StaticFields = HashMap>; #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] @@ -313,6 +328,64 @@ async fn get_app_w_draft( Ok(Json(app)) } +async fn get_app_history( + authed: ApiAuthed, + Extension(user_db): Extension, + Path((w_id, path)): Path<(String, StripPath)>, +) -> JsonResult> { + let mut tx = user_db.begin(&authed).await?; + let query_result = sqlx::query!( + "SELECT a.id as app_id, av.id as version_id, dm.deployment_msg as deployment_msg + FROM app a LEFT JOIN app_version av ON a.id = av.app_id LEFT JOIN deployment_metadata dm ON av.id = dm.app_version + WHERE a.workspace_id = $1 AND a.path = $2 + ORDER BY created_at DESC", + w_id, + path.to_path(), + ).fetch_all(&mut *tx).await?; + tx.commit().await?; + + let result: Vec = query_result + .into_iter() + .map(|row| AppHistory { + app_id: row.app_id, + version: row.version_id, + deployment_msg: row.deployment_msg, + }) + .collect(); + return Ok(Json(result)); +} + +async fn update_app_history( + authed: ApiAuthed, + Extension(user_db): Extension, + Path((w_id, app_id, app_version)): Path<(String, i64, i64)>, + Json(app_history_update): Json, +) -> Result<()> { + let mut tx = user_db.begin(&authed).await?; + let app_path = sqlx::query_scalar!("SELECT path FROM app WHERE id = $1", app_id) + .fetch_optional(&mut *tx) + .await?; + + if app_path.is_none() { + tx.commit().await?; + return Err(Error::NotFound( + format!("App with ID {app_id} not found").to_string(), + )); + } + + sqlx::query!( + "INSERT INTO deployment_metadata (workspace_id, path, app_version, deployment_msg) VALUES ($1, $2, $3, $4) ON CONFLICT (workspace_id, path, app_version) WHERE app_version IS NOT NULL DO UPDATE SET deployment_msg = $4", + w_id, + app_path.unwrap(), + app_version, + app_history_update.deployment_msg, + ) + .fetch_optional(&mut *tx) + .await?; + tx.commit().await?; + return Ok(()); +} + async fn get_app_by_id( authed: ApiAuthed, Extension(user_db): Extension, diff --git a/backend/windmill-api/src/scripts.rs b/backend/windmill-api/src/scripts.rs index f7a9e3ca97..3965322645 100644 --- a/backend/windmill-api/src/scripts.rs +++ b/backend/windmill-api/src/scripts.rs @@ -40,7 +40,7 @@ use windmill_common::{ schedule::Schedule, scripts::{ to_i64, HubScript, ListScriptQuery, ListableScript, NewScript, Schema, Script, ScriptHash, - ScriptKind, ScriptLang, + ScriptHistory, ScriptHistoryUpdate, ScriptKind, ScriptLang, }, users::username_to_permissioned_as, utils::{ @@ -121,6 +121,11 @@ pub fn workspaced_service() -> Router { "/toggle_workspace_error_handler/p/*path", post(toggle_workspace_error_handler), ) + .route("/history/p/*path", get(get_script_history)) + .route( + "/history_update/h/:hash/p/*path", + post(update_script_history), + ) } #[derive(Serialize, FromRow)] @@ -724,6 +729,54 @@ async fn get_script_by_path_w_draft( Ok(Json(script)) } +async fn get_script_history( + authed: ApiAuthed, + Extension(user_db): Extension, + Path((w_id, path)): Path<(String, StripPath)>, +) -> JsonResult> { + let mut tx = user_db.begin(&authed).await?; + let query_result = sqlx::query!( + "SELECT s.hash as hash, dm.deployment_msg as deployment_msg + FROM script s LEFT JOIN deployment_metadata dm ON s.hash = dm.script_hash + WHERE s.workspace_id = $1 AND s.path = $2 + ORDER by created_at DESC", + w_id, + path.to_path(), + ) + .fetch_all(&mut *tx) + .await?; + tx.commit().await?; + + let result: Vec = query_result + .into_iter() + .map(|row| ScriptHistory { + script_hash: ScriptHash(row.hash), + deployment_msg: row.deployment_msg, + }) + .collect(); + return Ok(Json(result)); +} + +async fn update_script_history( + authed: ApiAuthed, + Extension(user_db): Extension, + Path((w_id, script_hash, script_path)): Path<(String, ScriptHash, StripPath)>, + Json(script_history_update): Json, +) -> Result<()> { + let mut tx = user_db.begin(&authed).await?; + sqlx::query!( + "INSERT INTO deployment_metadata (workspace_id, path, script_hash, deployment_msg) VALUES ($1, $2, $3, $4) ON CONFLICT (workspace_id, script_hash) WHERE script_hash IS NOT NULL DO UPDATE SET deployment_msg = $4", + w_id, + script_path.to_path(), + script_hash.0, + script_history_update.deployment_msg, + ) + .fetch_optional(&mut *tx) + .await?; + tx.commit().await?; + return Ok(()); +} + async fn list_paths( authed: ApiAuthed, Extension(user_db): Extension, diff --git a/backend/windmill-common/src/scripts.rs b/backend/windmill-common/src/scripts.rs index c1177ca7e6..a583a55195 100644 --- a/backend/windmill-common/src/scripts.rs +++ b/backend/windmill-common/src/scripts.rs @@ -204,6 +204,18 @@ pub struct ListableScript { pub ws_error_handler_muted: Option, } +#[derive(Serialize)] +pub struct ScriptHistory { + pub script_hash: ScriptHash, + #[serde(skip_serializing_if = "Option::is_none")] + pub deployment_msg: Option, +} + +#[derive(Deserialize)] +pub struct ScriptHistoryUpdate { + pub deployment_msg: Option, +} + #[derive(Serialize, Deserialize, Debug)] #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] #[cfg_attr(feature = "sqlx", sqlx)] diff --git a/frontend/src/lib/components/ScriptVersionHistory.svelte b/frontend/src/lib/components/ScriptVersionHistory.svelte index 08ccccf72a..97a60f62c0 100644 --- a/frontend/src/lib/components/ScriptVersionHistory.svelte +++ b/frontend/src/lib/components/ScriptVersionHistory.svelte @@ -1,32 +1,57 @@ @@ -42,15 +67,23 @@
(selectedVersion = version)} + on:click={() => { + selectedVersion = version + deploymentMsgUpdate = undefined + deploymentMsgUpdateMode = false + }} > - {version} + + {#if emptyString(version.deployment_msg)}Version {version.script_hash}{:else}{version.deployment_msg}{/if} + {#if openDetails} + +
+ {:else} + {#if selectedVersion.deployment_msg} + {selectedVersion.deployment_msg} + {:else} + Version {selectedVersion.script_hash} + {/if} + + {/if} + + + {/key} {:else}
Select a deployment version to see its details
diff --git a/frontend/src/lib/components/apps/editor/AppDeploymentHistory.svelte b/frontend/src/lib/components/apps/editor/AppDeploymentHistory.svelte index f8f55318e8..193da625b6 100644 --- a/frontend/src/lib/components/apps/editor/AppDeploymentHistory.svelte +++ b/frontend/src/lib/components/apps/editor/AppDeploymentHistory.svelte @@ -5,11 +5,11 @@ import { sendUserToast } from '$lib/toast' import DeploymentHistory from './DeploymentHistory.svelte' - let versions: number[] = [] + let appPath: string | undefined = undefined let historyBrowserDrawerOpen = false - export function open(newVersions: number[]) { - versions = newVersions + export function open(appPath: string) { + appPath = appPath historyBrowserDrawerOpen = true } @@ -33,7 +33,7 @@ sendUserToast('App restored from previous deployment') updateApp(e.detail) }} - {versions} + {appPath} on:close={() => { historyBrowserDrawerOpen = false }} diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte index ba449c938d..ad0b547331 100644 --- a/frontend/src/lib/components/apps/editor/AppEditor.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte @@ -61,7 +61,6 @@ export let policy: Policy export let summary: string export let fromHub: boolean = false - export let versions: number[] export let diffDrawer: DiffDrawer | undefined = undefined export let savedApp: | { @@ -493,7 +492,6 @@ {#if $appStore} (historyBrowserDrawerOpen = false)}> - + diff --git a/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte b/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte index e7740c8284..d40dcd7716 100644 --- a/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte +++ b/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte @@ -1,20 +1,42 @@
- {#if versions.length > 0} -
- {#each reversedVersions ?? [] as version} - -
(selectedVersion = version)} - > - {version} -
- {/each} -
+ {#if !loading} + {#if versions.length > 0} +
+ {#each versions ?? [] as version} + +
{ + selectedVersion = version + deploymentMsgUpdateMode = false + deploymentMsgUpdate = undefined + }} + > + + {#if emptyString(version.deployment_msg)}Version {version.version}{:else}{version.deployment_msg}{/if} + +
+ {/each} +
+ {:else} +
No items
+ {/if} {:else} -
No items
+ {/if}
@@ -56,14 +109,74 @@
{#if selectedVersion} {#if selected} -
-

Deployed {displayDate(selected.created_at)} by {selected.created_by}

-
- + +
+ {:else} + {#if selectedVersion.deployment_msg} + {selectedVersion.deployment_msg} + {:else} + Deployed {displayDate(selected.created_at)} by {selected.created_by} + {/if} + + {/if} + +
+ -
diff --git a/frontend/src/lib/components/common/table/AppRow.svelte b/frontend/src/lib/components/common/table/AppRow.svelte index 7c51bfec70..0e5eb46f81 100644 --- a/frontend/src/lib/components/common/table/AppRow.svelte +++ b/frontend/src/lib/components/common/table/AppRow.svelte @@ -66,7 +66,7 @@ path })) as unknown as AppWithLastVersion - appDeploymentHistory.open(app.versions) + appDeploymentHistory.open(app.path) } diff --git a/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte b/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte index 1860ee375c..15dde93d3f 100644 --- a/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte @@ -109,7 +109,7 @@ {#if value}
{#key value} - + {/key}
{/if} diff --git a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte index 1716a0a15c..0254d981b5 100644 --- a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte @@ -188,7 +188,6 @@ app = e.detail redraw++ }} - versions={app.versions} summary={app.summary} app={app.value} path={app.path}