From 6583c4be012fb4da83782428d597c9e615f6e2e5 Mon Sep 17 00:00:00 2001 From: Chad Woolley Date: Thu, 1 Dec 2022 23:19:46 -0800 Subject: [PATCH 01/18] Remote Development - The initial release of the Remote Development feature Changelog: added Skeleton stub for /internal/kubernetes/remote_dev/work endpoint DISABLE auth, error handling, and change to GET WIP - more tweaks WIP - structure of request and response matches current agentk structure make request and response structure match agent setting up persistence and graphql api add workspaces table and services, rename refactors, etc send config_to_apply as a single yaml string tweaks, user is current user and not passed in params, change migration More tweaking migrations and workspace model WIP - NOT WORKING YET - start implementing reconciliation logic Add error handling to work around current_user bug Starting to write spec for state_reconciliation_service check in correct structure.sql (workspaces was missing name, etc) Working unit test for reconciliation service Fix linting errors so we can push without LEFTHOOK=0 Write basic state machine with tests clean up rubymine warnings Cleanup and refactor, extract core logic from service to Processor class rename refactors to clear things up before adding more logic Refactoring, translate phase into state pull out shared context with configs to test drive processor uncomment kubernetes.rb authenticate_gitlab_kas_request update database schema refactors, add tests for processor fix rubocop errors Fix ActiveRecord inverse_of associations Handle receiving untracked workstations info from agent Restructure spec contexts Refactor spec and factories - to be consistent with fixture workspace state Add logic and tests for desired != actual state Change args interface b/w service and processor Attempt to set up EE model and associations correctly Add minimial spec for grape API declaration Extract actual info parser logic Move services to EE Move lib files under EE Add debug logs, handle missing phase Add exploratory testing helper scripts Get to 100 percent coverage Improve k8s watch script Switch devworkspace config example to ttyd Add running/failed states, vscode->ttyd Remove state machine, add consts Extract config generator, test coverage Remove sleep from watch_rails_workspaces.sh Handle case where no WS exist in k8s Make scripts executable Switch create_workspace script to ruby Add spec for DesiredConfigGenerator Fix scripts, and handling of namespace/version Suppress false rubymine inspection errors Add validation for states in model Add support for storing URL Make update test script do validation Add basic graphql support - needs tests Fix query_type_spec.rb Update graphql docs More GraphQL functionality - group association Minimal UI to list workspaces Fix navbar specs Add polling for workspaces list Regenerate locale/gitlab.pot Add Starting as supported actual_state Helper script to run specs Move Workspace out of EE namespace Move graphql classes out of EE namespace Add devfile in create_workspace helper script Fix rubocop linting error Add editor field to Workspace Move js app under correct directory Change workspace URL to link Fix rubocop failure Pass editor in desired_config_generator.rb Graphql create mutation, and other fixes Minimal create form with hardcoded agent ID Add clusterAgentId text field Update queries, pots, and api index Move services under Workspaces namespace Rename fullPath to groupFullPath Add TERMINATED state Make desiredStates a dropdown Agent field dropdown, other improvements Add missing test coverage for graphql Add update mutation and service Create graphql update query, other query/schema cleanup Order workspaces finder by ID Add loading state, fix list query name Fix list query, remove unneeded query type method Update form working UpdaTE pots Support terminated state Switch to source editor for devfile field Rename var and fix spec Add routes for vue to make reload work Make list update instantly after add Switch to graphql subscriptions - For workspace list update, instead of Apollo polling Fix local cyclic dependency classload errors See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#testing-tips-and-tricks and search 'cyclic' Fix group_updated_spec copy-pasta error Fix rubocop errors Fix ee version of subscription_type_spec Support Devfile in project, other cleanup - Includes other cleanup/fixes for upstream remote_dev branch Do not create Workspaces without devfiles Fix migration WIP - adding project support Fix handling of devfile options radio Devfile in project now working (*) - (*) Not yet tested with full GA4K integration running Fix some state-management bugs Fix spec Add index migration for project_id Single migration and reset db script Fix failing create mutation spec - Change WorkspaceType#agent to #cluster_agent Run gettext:regenerate Clean up / add Workspace GraphQL associations Improve workspace resolver and finder Move branch_hooks_service to EE Fix failing specs Add coverage for create/update mutations Add todo about detecting devfile changes Support selective updates of workspace attributes Update graphql docs for WorkspaceUpdateInput Update layout to fix linting error Fix linting error Update db/structure.sql Update scripts Fix rubocop errors Manually fix structure.sql Simplify graphql type - Thanks Paul Add test coverage for model terminated? method Remove unnecessary non-EE routes entry Fixing failing graphql mutation specs - See https://gitlab.slack.com/archives/C6MLS3XEU/p1677716828645539?thread_ts=1677710256.031839&cid=C6MLS3XEU Fix Workspace factory associations Remove feature specs from remote dev spec script Make devfile and editor immutable - Removes hook and worker for devfile in repo Remove DWO dependency Use devfile gem to create k8s resources instead of devworkspace resource. Remove references to default namespace. move labels and annotations to devfile gem. fix tests. add size for the ephemeral volume. add editor components in the spec fixture. add ingress class name while generating k8s resources update editor image tag Update gemfile to use git repository of devfile gem Extract workspace url during config generation add actual state calculator add edge cases around deployment completion and workspace failure Add nil default. Add specs for actual state calculator Refactor devfile processing Fix tests Remove unrequired lines Fix typo Fix error with factory duplicate name - See note in code, workspace factory was creating duplicated names for different workspaces, which failed validation when attempting to save them. Move shared context file to ee dir Update gemfile checksum Add specs to convenience script Fix rubocop complaints Update gemfile Update gemfile checksum Add domain template Update gemfile Add trailing whitespace to yaml to fix tests Add tests and fix typos Fix failing CI pipeline Remove fast_spec_helper from actual_state_calculator_spec.rb - It's causing problems, see notes Remove unreachable code - to fix undercoverage failure Fix create workspace script Change agent domain suffix to localdev.me Replace ttyd with webide Support workspace ordering by updated_at Fix spec that verifies finder behavior with id Temporarily disable pagination Re-enable pagination Fix linting issues Fix danger error Temp dev workspace url fix Remove all references of devworkspace Use assertions that dont trigger dangerbot warning Refactor shared context and devfile fixtures Pass terminated flag in WorkspaceAgentInfo Cleanup displayed state Cleanup devfile fixtures more Write a happy-path feature spec for rails regression coverage Add wip e2e spec to verify workspace creation Complete e2e spec to verify workspace creation Refactor to extract reusable logic into a flow Remove redundant log Support cleanup of created workspaces in spec Remove unnecessary todo Add comment describing how to run the spec Temporarily update kas version for verification Quarantine the e2e spec Update spec to use hardcoded devfile project Fix minor linting issue Update spec to create new devfile project Use webide as the editor instead of vscode Fix project reference Fix linting issues Fix the flakiness of the spec Fix more linting issues Fix issues from the static-analysis pipeline Fix all lint issues (finally) Update testcase description Update with link to testcase Revert changes to kas version Fix quarantine type Add --tag description to comment doc and move it Archive devfile project during teardown Add helper script and make the spec parameterizable Increase retries to reduce flakiness Fix comments for clarity Add TODO to reduce duplication Add tests for workspace url Rename sent_to_agent_at field to responded_to_agent_at Fix n+1 query problem in reconcile loop Rewrite actual state calculator spec with fixtures - TODO: some cases are failing and skipped. Rewrite actual state calculator spec with fixtures - TODO: some cases are failing and skipped. Add more test coverage for reconciliation scenarios - Missed these files in previous commit Add workspace_updates_processor_reconciliation_scenarios_spec.rb to script Remove unnecessary disable_ddl_transaction Remove unnecessary ActiveSupport::Concern Only allow webide as editor Adds support to propogate Agent Configuration to rails - New table and model called Remote Develelopment Agent Config - Changes to the Agent config API to write to this table Caw clean up service layer interfaces Improve error handling if cluster agent has no remote dev config Rename agent communication api fields Introduce namespacing to domain layer --- Gemfile | 3 + Gemfile.checksum | 3 + Gemfile.lock | 2 + .../javascripts/graphql_shared/constants.js | 1 + app/assets/stylesheets/utilities.scss | 4 + app/graphql/types/user_interface.rb | 2 + db/docs/remote_development_agent_configs.yml | 10 + db/docs/workspaces.yml | 10 + ...010101_create_remote_development_tables.rb | 54 ++ db/schema_migrations/20221225010101 | 1 + db/structure.sql | 94 +++ doc/api/graphql/reference/index.md | 227 +++++++ .../create/get_project_details_query.vue | 1 + .../list/start_workspace_button.vue | 6 +- .../list/workspace_state_indicator.vue | 14 +- .../remote_development/constants.js | 3 + .../workspace_create.mutation.graphql | 2 +- .../workspace_update.mutation.graphql | 4 +- .../user_workspaces_list.query.graphql | 2 +- .../remote_development/init_workspaces_app.js | 102 ++- .../remote_development/pages/create.vue | 5 +- .../remote_development/pages/list.vue | 19 +- .../remote_development/workspaces_finder.rb | 36 + ee/app/graphql/ee/types/mutation_type.rb | 2 + ee/app/graphql/ee/types/query_type.rb | 19 +- ee/app/graphql/ee/types/user_interface.rb | 15 + .../remote_development/workspaces/create.rb | 79 +++ .../remote_development/workspaces/update.rb | 49 ++ .../remote_development/workspaces_resolver.rb | 26 + .../remote_development/workspace_type.rb | 78 +++ ee/app/models/ee/clusters/agent.rb | 10 + ee/app/models/ee/project.rb | 2 + ee/app/models/ee/user.rb | 2 + .../remote_development_agent_config.rb | 25 + ee/app/models/remote_development/workspace.rb | 82 +++ ee/app/policies/ee/global_policy.rb | 4 +- ee/app/policies/ee/project_policy.rb | 1 + .../remote_development/workspace_policy.rb | 19 + .../agent_config/update_service.rb | 40 ++ .../workspaces/create_service.rb | 43 ++ .../workspaces/reconcile_service.rb | 70 ++ .../workspaces/update_service.rb | 42 ++ ee/lib/ee/api/internal/kubernetes.rb | 25 + .../agent_config/update_processor.rb | 27 + ee/lib/remote_development/error.rb | 12 + .../workspaces/create/create_processor.rb | 76 +++ .../workspaces/create/devfile_processor.rb | 200 ++++++ .../workspaces/create/devfile_validator.rb | 142 ++++ .../reconcile/actual_state_calculator.rb | 176 +++++ .../workspaces/reconcile/agent_info.rb | 27 + .../workspaces/reconcile/agent_info_parser.rb | 40 ++ .../reconcile/desired_config_generator.rb | 87 +++ .../workspaces/reconcile/devfile_parser.rb | 74 ++ .../workspaces/reconcile/params_parser.rb | 55 ++ .../reconcile/reconcile_processor.rb | 142 ++++ .../workspaces/reconcile/update_type.rb | 12 + .../remote_development/workspaces/states.rb | 48 ++ .../workspaces/update/update_processor.rb | 20 + ee/spec/factories/clusters/agents.rb | 9 + .../remote_development_agent_configs.rb | 10 + .../remote_development/workspaces.rb | 101 +++ .../remote_development/workspaces_spec.rb | 193 ++++++ .../workspaces_finder_spec.rb | 64 ++ .../remote_development/.example.devfile.yaml | 8 + ...-command-apply-component-name-devfile.yaml | 12 + ...x-command-exec-component-name-devfile.yaml | 14 + ...estricted-prefix-command-name-devfile.yaml | 14 + ...onent-container-endpoint-name-devfile.yaml | 13 + ...tricted-prefix-component-name-devfile.yaml | 8 + ...fix-event-type-poststart-name-devfile.yaml | 18 + ...efix-event-type-prestart-name-devfile.yaml | 18 + ...refix-event-type-prestop-name-devfile.yaml | 18 + ...stricted-prefix-variable-name-devfile.yaml | 10 + ...variable-name-with-underscore-devfile.yaml | 10 + ...upported-component-type-image-devfile.yaml | 15 + ...ted-component-type-kubernetes-devfile.yaml | 20 + ...rted-component-type-openshift-devfile.yaml | 20 + .../.example.processed-devfile.yaml | 67 ++ .../create/get_project_details_query_spec.js | 2 + .../create/search_projects_listbox_spec.js | 2 + .../components/list/empty_state_spec.js | 2 + .../list/start_workspace_button_spec.js | 2 +- .../list/terminate_workspace_button_spec.js | 1 + .../list/workspace_state_indicator_spec.js | 21 +- .../init_workspaces_app_spec.js | 5 +- .../remote_development/mock_data/index.js | 5 +- .../remote_development/pages/create_spec.js | 39 +- .../remote_development/pages/list_spec.js | 140 ++-- .../remote_development/router/index_spec.js | 8 +- ee/spec/graphql/api/workspace_spec.rb | 39 ++ ee/spec/graphql/types/query_type_spec.rb | 13 +- .../remote_development/workspace_type_spec.rb | 19 + ee/spec/graphql/types/user_type_spec.rb | 13 + .../agent_config/update_processor_spec.rb | 72 ++ .../create/create_processor_spec.rb | 107 +++ .../create/devfile_processor_spec.rb | 40 ++ .../create/devfile_validator_spec.rb | 51 ++ .../reconcile/actual_state_calculator_spec.rb | 481 +++++++++++++ .../reconcile/agent_info_parser_spec.rb | 86 +++ .../workspaces/reconcile/agent_info_spec.rb | 35 + .../desired_config_generator_spec.rb | 61 ++ .../reconcile/devfile_parser_spec.rb | 53 ++ .../reconcile/params_parser_spec.rb | 80 +++ .../reconcile_processor_scenarios_spec.rb | 238 +++++++ .../reconcile/reconcile_processor_spec.rb | 459 +++++++++++++ .../workspaces/states_spec.rb | 27 + .../update/update_processor_spec.rb | 47 ++ ee/spec/models/factories_spec.rb | 1 + .../remote_development_agent_config_spec.rb | 32 + .../remote_development/workspace_spec.rb | 120 ++++ ee/spec/policies/project_policy_spec.rb | 12 + .../workspace_policy_spec.rb | 49 ++ .../workspaces/create_spec.rb | 111 +++ .../workspaces/update_spec.rb | 99 +++ .../current_user_workspaces_spec.rb | 40 ++ .../workspace_by_id_spec.rb | 45 ++ .../workspaces_by_ids_spec.rb | 52 ++ .../requests/api/internal/kubernetes_spec.rb | 83 ++- .../agent_config/update_service_spec.rb | 36 + .../workspaces/create_service_spec.rb | 58 ++ .../workspaces/reconcile_service_spec.rb | 87 +++ .../workspaces/update_service_spec.rb | 57 ++ ...fo_status_fixture_not_implemented_error.rb | 8 + .../remote_development_shared_contexts.rb | 639 ++++++++++++++++++ lib/api/internal/kubernetes.rb | 9 +- locale/gitlab.pot | 6 + qa/qa/ee/flow/workspace.rb | 58 ++ qa/qa/ee/page/workspace/edit.rb | 39 ++ qa/qa/ee/page/workspace/index.rb | 49 ++ qa/qa/ee/page/workspace/new.rb | 63 ++ qa/qa/flow/project.rb | 11 + qa/qa/page/group/menu.rb | 6 + .../create_workspace_spec.rb | 109 +++ .../reset-remote-dev-db-tables.sh | 24 + scripts/remote_development/run-e2e-spec.sh | 34 + .../run-remote-development-specs.sh | 66 ++ .../watch-k8s-workspaces.sh | 5 + .../watch-rails-workspaces.sh | 2 + spec/graphql/types/user_type_spec.rb | 2 +- spec/lib/gitlab/import_export/all_models.yml | 1 + spec/support/helpers/graphql_helpers.rb | 6 +- spec/support/rspec_order_todo.yml | 6 +- ...quest_interactions_type_shared_examples.rb | 4 + 143 files changed, 6999 insertions(+), 196 deletions(-) create mode 100644 db/docs/remote_development_agent_configs.yml create mode 100644 db/docs/workspaces.yml create mode 100644 db/migrate/20221225010101_create_remote_development_tables.rb create mode 100644 db/schema_migrations/20221225010101 create mode 100644 ee/app/finders/remote_development/workspaces_finder.rb create mode 100644 ee/app/graphql/ee/types/user_interface.rb create mode 100644 ee/app/graphql/mutations/remote_development/workspaces/create.rb create mode 100644 ee/app/graphql/mutations/remote_development/workspaces/update.rb create mode 100644 ee/app/graphql/resolvers/remote_development/workspaces_resolver.rb create mode 100644 ee/app/graphql/types/remote_development/workspace_type.rb create mode 100644 ee/app/models/remote_development/remote_development_agent_config.rb create mode 100644 ee/app/models/remote_development/workspace.rb create mode 100644 ee/app/policies/remote_development/workspace_policy.rb create mode 100644 ee/app/services/remote_development/agent_config/update_service.rb create mode 100644 ee/app/services/remote_development/workspaces/create_service.rb create mode 100644 ee/app/services/remote_development/workspaces/reconcile_service.rb create mode 100644 ee/app/services/remote_development/workspaces/update_service.rb create mode 100644 ee/lib/remote_development/agent_config/update_processor.rb create mode 100644 ee/lib/remote_development/error.rb create mode 100644 ee/lib/remote_development/workspaces/create/create_processor.rb create mode 100644 ee/lib/remote_development/workspaces/create/devfile_processor.rb create mode 100644 ee/lib/remote_development/workspaces/create/devfile_validator.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/actual_state_calculator.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/agent_info.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/agent_info_parser.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/desired_config_generator.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/devfile_parser.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/params_parser.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/reconcile_processor.rb create mode 100644 ee/lib/remote_development/workspaces/reconcile/update_type.rb create mode 100644 ee/lib/remote_development/workspaces/states.rb create mode 100644 ee/lib/remote_development/workspaces/update/update_processor.rb create mode 100644 ee/spec/factories/clusters/agents.rb create mode 100644 ee/spec/factories/remote_development/remote_development_agent_configs.rb create mode 100644 ee/spec/factories/remote_development/workspaces.rb create mode 100644 ee/spec/features/remote_development/workspaces_spec.rb create mode 100644 ee/spec/finders/remote_development/workspaces_finder_spec.rb create mode 100644 ee/spec/fixtures/remote_development/.example.devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-command-apply-component-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-command-exec-component-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-command-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-component-container-endpoint-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-component-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-event-type-poststart-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-event-type-prestart-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-event-type-prestop-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-variable-name-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-restricted-prefix-variable-name-with-underscore-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-unsupported-component-type-image-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-unsupported-component-type-kubernetes-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.invalid-unsupported-component-type-openshift-devfile.yaml create mode 100644 ee/spec/fixtures/remote_development/.example.processed-devfile.yaml create mode 100644 ee/spec/graphql/api/workspace_spec.rb create mode 100644 ee/spec/graphql/types/remote_development/workspace_type_spec.rb create mode 100644 ee/spec/graphql/types/user_type_spec.rb create mode 100644 ee/spec/lib/remote_development/agent_config/update_processor_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/create/create_processor_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/create/devfile_processor_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/create/devfile_validator_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/actual_state_calculator_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/agent_info_parser_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/agent_info_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/desired_config_generator_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/devfile_parser_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/params_parser_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_scenarios_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/states_spec.rb create mode 100644 ee/spec/lib/remote_development/workspaces/update/update_processor_spec.rb create mode 100644 ee/spec/models/remote_development/remote_development_agent_config_spec.rb create mode 100644 ee/spec/models/remote_development/workspace_spec.rb create mode 100644 ee/spec/policies/remote_development/workspace_policy_spec.rb create mode 100644 ee/spec/requests/api/graphql/mutations/remote_development/workspaces/create_spec.rb create mode 100644 ee/spec/requests/api/graphql/mutations/remote_development/workspaces/update_spec.rb create mode 100644 ee/spec/requests/api/graphql/remote_development/current_user_workspaces_spec.rb create mode 100644 ee/spec/requests/api/graphql/remote_development/workspace_by_id_spec.rb create mode 100644 ee/spec/requests/api/graphql/remote_development/workspaces_by_ids_spec.rb create mode 100644 ee/spec/services/remote_development/agent_config/update_service_spec.rb create mode 100644 ee/spec/services/remote_development/workspaces/create_service_spec.rb create mode 100644 ee/spec/services/remote_development/workspaces/reconcile_service_spec.rb create mode 100644 ee/spec/services/remote_development/workspaces/update_service_spec.rb create mode 100644 ee/spec/support/shared_contexts/remote_development/agent_info_status_fixture_not_implemented_error.rb create mode 100644 ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb create mode 100644 qa/qa/ee/flow/workspace.rb create mode 100644 qa/qa/ee/page/workspace/edit.rb create mode 100644 qa/qa/ee/page/workspace/index.rb create mode 100644 qa/qa/ee/page/workspace/new.rb create mode 100644 qa/qa/specs/features/ee/browser_ui/3_create/remote_development/create_workspace_spec.rb create mode 100755 scripts/remote_development/reset-remote-dev-db-tables.sh create mode 100755 scripts/remote_development/run-e2e-spec.sh create mode 100755 scripts/remote_development/run-remote-development-specs.sh create mode 100755 scripts/remote_development/watch-k8s-workspaces.sh create mode 100755 scripts/remote_development/watch-rails-workspaces.sh diff --git a/Gemfile b/Gemfile index ecc2da6f0547b3..32d64b19f7cee2 100644 --- a/Gemfile +++ b/Gemfile @@ -587,6 +587,9 @@ gem 'cvss-suite', '~> 3.0.1', require: 'cvss_suite' # Work with RPM packages gem 'arr-pm', '~> 0.0.12' +# Remote Development +gem 'devfile', '~> 0.0.15.pre.alpha1' + # Apple plist parsing gem 'CFPropertyList', '~> 3.0.0' gem 'app_store_connect' diff --git a/Gemfile.checksum b/Gemfile.checksum index 69b15f3b3688b3..d260ad61dcd4c9 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -110,6 +110,9 @@ {"name":"deprecation_toolkit","version":"1.5.1","platform":"ruby","checksum":"a8a1ab1a19ae40ea12560b65010e099f3459ebde390b76621ef0c21c516a04ba"}, {"name":"derailed_benchmarks","version":"2.1.2","platform":"ruby","checksum":"eaadc6206ceeb5538ff8f5e04a0023d54ebdd95d04f33e8960fb95a5f189a14f"}, {"name":"descendants_tracker","version":"0.0.4","platform":"ruby","checksum":"e9c41dd4cfbb85829a9301ea7e7c48c2a03b26f09319db230e6479ccdc780897"}, +{"name":"devfile","version":"0.0.15.pre.alpha1","platform":"arm64-darwin","checksum":"8e8234d552310925758dd5f214e1fc059ecc7255f8d692300d1adb955c370198"}, +{"name":"devfile","version":"0.0.15.pre.alpha1","platform":"ruby","checksum":"69a058d9edb44efe2fb78769e531b324f3bd75b21d45be15d8b0335b691d093e"}, +{"name":"devfile","version":"0.0.15.pre.alpha1","platform":"x86_64-linux","checksum":"460ddad57cc69a293661bb82ebc19ca44147201c74f78b36bb4861b402ecff24"}, {"name":"device_detector","version":"1.0.0","platform":"ruby","checksum":"b800fb3150b00c23e87b6768011808ac1771fffaae74c3238ebaf2b782947a7d"}, {"name":"devise","version":"4.8.1","platform":"ruby","checksum":"fdd48bbe79a89e7c1152236a70479842ede48bea4fa7f4f2d8da1f872559803e"}, {"name":"devise-two-factor","version":"4.0.2","platform":"ruby","checksum":"6548d2696ed090d27046f888f4fa7380f151e0f823902d46fd9b91e7d0cac511"}, diff --git a/Gemfile.lock b/Gemfile.lock index 2d2f2fa783845f..1ca62011875b71 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -376,6 +376,7 @@ GEM thor (>= 0.19, < 2) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) + devfile (0.0.15.pre.alpha1) device_detector (1.0.0) devise (4.8.1) bcrypt (~> 3.0) @@ -1713,6 +1714,7 @@ DEPENDENCIES declarative_policy (~> 1.1.0) deprecation_toolkit (~> 1.5.1) derailed_benchmarks + devfile (~> 0.0.15.pre.alpha1) device_detector devise (~> 4.8.1) devise-pbkdf2-encryptable (~> 0.0.0)! diff --git a/app/assets/javascripts/graphql_shared/constants.js b/app/assets/javascripts/graphql_shared/constants.js index 5ba4669749603d..0642f157b385ac 100644 --- a/app/assets/javascripts/graphql_shared/constants.js +++ b/app/assets/javascripts/graphql_shared/constants.js @@ -27,5 +27,6 @@ export const TYPENAME_USER = 'User'; export const TYPENAME_VULNERABILITIES_SCANNER = 'Vulnerabilities::Scanner'; export const TYPENAME_VULNERABILITY = 'Vulnerability'; export const TYPENAME_WORK_ITEM = 'WorkItem'; +export const TYPE_CLUSTERS_AGENT = 'Clusters::Agent'; export const TYPE_USERS_SAVED_REPLY = 'Users::SavedReply'; export const TYPE_WORKSPACE = 'RemoteDevelopment::Workspace'; diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss index 267bd3f9506a37..08c4efce542ea1 100644 --- a/app/assets/stylesheets/utilities.scss +++ b/app/assets/stylesheets/utilities.scss @@ -149,3 +149,7 @@ .gl-fill-orange-500 { fill: $orange-500; } + +.gl-fill-red-500 { + fill: $red-500; +} diff --git a/app/graphql/types/user_interface.rb b/app/graphql/types/user_interface.rb index 83d2f3f830a81c..64fc069b508950 100644 --- a/app/graphql/types/user_interface.rb +++ b/app/graphql/types/user_interface.rb @@ -175,3 +175,5 @@ def redacted_name end end end + +Types::UserInterface.prepend_mod diff --git a/db/docs/remote_development_agent_configs.yml b/db/docs/remote_development_agent_configs.yml new file mode 100644 index 00000000000000..0de90d1777caf5 --- /dev/null +++ b/db/docs/remote_development_agent_configs.yml @@ -0,0 +1,10 @@ +--- +table_name: remote_development_agent_configs +classes: +- RemoteDevelopment::RemoteDevelopmentAgentConfig +feature_categories: +- remote_development +description: Remote Development Cluster Agent Configuration +introduced_by_url: +milestone: +gitlab_schema: gitlab_main diff --git a/db/docs/workspaces.yml b/db/docs/workspaces.yml new file mode 100644 index 00000000000000..e9983416e3181a --- /dev/null +++ b/db/docs/workspaces.yml @@ -0,0 +1,10 @@ +--- +table_name: workspaces +classes: +- RemoteDevelopment::Workspace +feature_categories: +- remote_development +description: Remote Development Workspaces +introduced_by_url: +milestone: +gitlab_schema: gitlab_main diff --git a/db/migrate/20221225010101_create_remote_development_tables.rb b/db/migrate/20221225010101_create_remote_development_tables.rb new file mode 100644 index 00000000000000..8c814020d80601 --- /dev/null +++ b/db/migrate/20221225010101_create_remote_development_tables.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +class CreateRemoteDevelopmentTables < Gitlab::Database::Migration[2.1] + def up + # TODO: Move foreign key creation to separate migration, to comply with + # https://docs.gitlab.com/ee/development/migration_style_guide.html#creating-a-new-table-when-we-have-two-foreign-keys + # rubocop:disable Migration/CreateTableWithForeignKeys + create_table :workspaces do |t| + t.timestamps_with_timezone null: false + # NOTE: All references are currently `on_delete: :cascade`, because we have no support or testing around null + # values. However, in the future we may want to switch these to nullify, especially once we start + # introducing logging, metrics, billing, etc. around workspaces. + t.references :user, null: false, index: true, foreign_key: { on_delete: :cascade } + t.references :cluster_agent, null: false, index: true, foreign_key: { on_delete: :cascade } + t.references :project, null: false, foreign_key: { on_delete: :cascade } + t.text :name, limit: 64, null: false, index: { unique: true } + t.text :namespace, limit: 64, null: false + t.text :desired_state, limit: 32, null: false + t.datetime_with_timezone :desired_state_updated_at, null: false + t.text :actual_state, limit: 32, null: false + t.datetime_with_timezone :responded_to_agent_at + t.text :editor, limit: 256, null: false + t.integer :max_hours_before_termination, limit: 2, null: false + t.text :devfile_ref, limit: 256, null: false + t.text :devfile_path, limit: 2048, null: false + # NOTE: The limit on the devfile field is arbitrary, and only added to avoid + # rubocop Migration/AddLimitToTextColumns error. We don't know what the upper bound to expect is, + # but 65535 allows for a YAML file with over 800 lines of an average 80-character length. + t.text :devfile, limit: 65535 + t.text :processed_devfile, limit: 65535 + t.text :url, limit: 1024, null: false + # NOTE: The resource version is currently backed by etcd's mod_revision. + # However, it's important to note that the application should not rely on the implementation details of + # the versioning system maintained by Kubernetes. We may change the implementation of resource version + # in the future, such as to change it to a timestamp or per-object counter. + # https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + # The limit of 64 is arbitrary. + t.text :deployment_resource_version, limit: 64 + end + # rubocop:enable Migration/CreateTableWithForeignKeys + + create_table :remote_development_agent_configs do |t| + t.timestamps_with_timezone null: false + t.references :cluster_agent, null: false, foreign_key: { on_delete: :cascade } + t.boolean :enabled, null: false + t.text :dns_zone, null: false, limit: 256 + end + end + + def down + drop_table :workspaces + drop_table :remote_development_agent_configs + end +end diff --git a/db/schema_migrations/20221225010101 b/db/schema_migrations/20221225010101 new file mode 100644 index 00000000000000..62d2d001438b77 --- /dev/null +++ b/db/schema_migrations/20221225010101 @@ -0,0 +1 @@ +94810a223f2d37a673d690ba326577068c18d6353021a78a8f820cf8a95c756c \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 695768fbfab1a0..47d39ae92b3f15 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -21783,6 +21783,25 @@ CREATE SEQUENCE releases_id_seq ALTER SEQUENCE releases_id_seq OWNED BY releases.id; +CREATE TABLE remote_development_agent_configs ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + cluster_agent_id bigint NOT NULL, + enabled boolean NOT NULL, + dns_zone text NOT NULL, + CONSTRAINT check_9f5cd54d1c CHECK ((char_length(dns_zone) <= 256)) +); + +CREATE SEQUENCE remote_development_agent_configs_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE remote_development_agent_configs_id_seq OWNED BY remote_development_agent_configs.id; + CREATE TABLE remote_mirrors ( id integer NOT NULL, project_id integer, @@ -24557,6 +24576,49 @@ CREATE SEQUENCE work_item_widget_definitions_id_seq ALTER SEQUENCE work_item_widget_definitions_id_seq OWNED BY work_item_widget_definitions.id; +CREATE TABLE workspaces ( + id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + user_id bigint NOT NULL, + cluster_agent_id bigint NOT NULL, + project_id bigint NOT NULL, + name text NOT NULL, + namespace text NOT NULL, + desired_state text NOT NULL, + desired_state_updated_at timestamp with time zone NOT NULL, + actual_state text NOT NULL, + responded_to_agent_at timestamp with time zone, + editor text NOT NULL, + max_hours_before_termination smallint NOT NULL, + devfile_ref text NOT NULL, + devfile_path text NOT NULL, + devfile text, + processed_devfile text, + url text NOT NULL, + deployment_resource_version text, + CONSTRAINT check_15543fb0fa CHECK ((char_length(name) <= 64)), + CONSTRAINT check_157d5f955c CHECK ((char_length(namespace) <= 64)), + CONSTRAINT check_2b401b0034 CHECK ((char_length(deployment_resource_version) <= 64)), + CONSTRAINT check_77d1a2ff50 CHECK ((char_length(processed_devfile) <= 65535)), + CONSTRAINT check_8e363ee3ad CHECK ((char_length(devfile_ref) <= 256)), + CONSTRAINT check_8e4db5ffc2 CHECK ((char_length(actual_state) <= 32)), + CONSTRAINT check_9e42558c35 CHECK ((char_length(url) <= 1024)), + CONSTRAINT check_b70eddcbc1 CHECK ((char_length(desired_state) <= 32)), + CONSTRAINT check_d7ed376e49 CHECK ((char_length(editor) <= 256)), + CONSTRAINT check_dc58d56169 CHECK ((char_length(devfile_path) <= 2048)), + CONSTRAINT check_eb32879a3d CHECK ((char_length(devfile) <= 65535)) +); + +CREATE SEQUENCE workspaces_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE workspaces_id_seq OWNED BY workspaces.id; + CREATE TABLE x509_certificates ( id bigint NOT NULL, created_at timestamp with time zone NOT NULL, @@ -25560,6 +25622,8 @@ ALTER TABLE ONLY release_links ALTER COLUMN id SET DEFAULT nextval('release_link ALTER TABLE ONLY releases ALTER COLUMN id SET DEFAULT nextval('releases_id_seq'::regclass); +ALTER TABLE ONLY remote_development_agent_configs ALTER COLUMN id SET DEFAULT nextval('remote_development_agent_configs_id_seq'::regclass); + ALTER TABLE ONLY remote_mirrors ALTER COLUMN id SET DEFAULT nextval('remote_mirrors_id_seq'::regclass); ALTER TABLE ONLY required_code_owners_sections ALTER COLUMN id SET DEFAULT nextval('required_code_owners_sections_id_seq'::regclass); @@ -25800,6 +25864,8 @@ ALTER TABLE ONLY work_item_types ALTER COLUMN id SET DEFAULT nextval('work_item_ ALTER TABLE ONLY work_item_widget_definitions ALTER COLUMN id SET DEFAULT nextval('work_item_widget_definitions_id_seq'::regclass); +ALTER TABLE ONLY workspaces ALTER COLUMN id SET DEFAULT nextval('workspaces_id_seq'::regclass); + ALTER TABLE ONLY x509_certificates ALTER COLUMN id SET DEFAULT nextval('x509_certificates_id_seq'::regclass); ALTER TABLE ONLY x509_commit_signatures ALTER COLUMN id SET DEFAULT nextval('x509_commit_signatures_id_seq'::regclass); @@ -27941,6 +28007,9 @@ ALTER TABLE releases ALTER TABLE ONLY releases ADD CONSTRAINT releases_pkey PRIMARY KEY (id); +ALTER TABLE ONLY remote_development_agent_configs + ADD CONSTRAINT remote_development_agent_configs_pkey PRIMARY KEY (id); + ALTER TABLE ONLY remote_mirrors ADD CONSTRAINT remote_mirrors_pkey PRIMARY KEY (id); @@ -28352,6 +28421,9 @@ ALTER TABLE ONLY work_item_types ALTER TABLE ONLY work_item_widget_definitions ADD CONSTRAINT work_item_widget_definitions_pkey PRIMARY KEY (id); +ALTER TABLE ONLY workspaces + ADD CONSTRAINT workspaces_pkey PRIMARY KEY (id); + ALTER TABLE ONLY x509_certificates ADD CONSTRAINT x509_certificates_pkey PRIMARY KEY (id); @@ -32167,6 +32239,8 @@ CREATE UNIQUE INDEX index_releases_on_project_tag_unique ON releases USING btree CREATE INDEX index_releases_on_released_at ON releases USING btree (released_at); +CREATE INDEX index_remote_development_agent_configs_on_cluster_agent_id ON remote_development_agent_configs USING btree (cluster_agent_id); + CREATE INDEX index_remote_mirrors_on_last_successful_update_at ON remote_mirrors USING btree (last_successful_update_at); CREATE INDEX index_remote_mirrors_on_project_id ON remote_mirrors USING btree (project_id); @@ -32975,6 +33049,14 @@ CREATE UNIQUE INDEX index_work_item_widget_definitions_on_namespace_type_and_nam CREATE INDEX index_work_item_widget_definitions_on_work_item_type_id ON work_item_widget_definitions USING btree (work_item_type_id); +CREATE INDEX index_workspaces_on_cluster_agent_id ON workspaces USING btree (cluster_agent_id); + +CREATE UNIQUE INDEX index_workspaces_on_name ON workspaces USING btree (name); + +CREATE INDEX index_workspaces_on_project_id ON workspaces USING btree (project_id); + +CREATE INDEX index_workspaces_on_user_id ON workspaces USING btree (user_id); + CREATE INDEX index_x509_certificates_on_subject_key_identifier ON x509_certificates USING btree (subject_key_identifier); CREATE INDEX index_x509_certificates_on_x509_issuer_id ON x509_certificates USING btree (x509_issuer_id); @@ -35624,6 +35706,9 @@ ALTER TABLE ONLY trending_projects ALTER TABLE ONLY security_orchestration_policy_configurations ADD CONSTRAINT fk_rails_0a22dcd52d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; +ALTER TABLE ONLY remote_development_agent_configs + ADD CONSTRAINT fk_rails_0a3c0ada56 FOREIGN KEY (cluster_agent_id) REFERENCES cluster_agents(id) ON DELETE CASCADE; + ALTER TABLE ONLY project_deploy_tokens ADD CONSTRAINT fk_rails_0aca134388 FOREIGN KEY (deploy_token_id) REFERENCES deploy_tokens(id) ON DELETE CASCADE; @@ -36836,6 +36921,9 @@ ALTER TABLE ONLY approval_merge_request_rules_users ALTER TABLE ONLY elasticsearch_indexed_projects ADD CONSTRAINT fk_rails_bd13bbdc3d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; +ALTER TABLE ONLY workspaces + ADD CONSTRAINT fk_rails_bdb0b31131 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + ALTER TABLE ONLY elasticsearch_indexed_namespaces ADD CONSTRAINT fk_rails_bdcf044f37 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; @@ -37028,6 +37116,9 @@ ALTER TABLE ONLY board_user_preferences ALTER TABLE ONLY vulnerability_occurrence_pipelines ADD CONSTRAINT fk_rails_dc3ae04693 FOREIGN KEY (occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE; +ALTER TABLE ONLY workspaces + ADD CONSTRAINT fk_rails_dc7c316be1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; + ALTER TABLE ONLY deployment_merge_requests ADD CONSTRAINT fk_rails_dcbce9f4df FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE; @@ -37232,6 +37323,9 @@ ALTER TABLE ONLY incident_management_oncall_shifts ALTER TABLE ONLY design_user_mentions ADD CONSTRAINT fk_rails_f7075a53c1 FOREIGN KEY (design_id) REFERENCES design_management_designs(id) ON DELETE CASCADE; +ALTER TABLE ONLY workspaces + ADD CONSTRAINT fk_rails_f78aeddc77 FOREIGN KEY (cluster_agent_id) REFERENCES cluster_agents(id) ON DELETE CASCADE; + ALTER TABLE ONLY internal_ids ADD CONSTRAINT fk_rails_f7d46b66c6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 8b8ac8a3d44601..dedd3dd82aa3cd 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -760,6 +760,34 @@ Returns [`WorkItem`](#workitem). | ---- | ---- | ----------- | | `id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. | +### `Query.workspace` + +Find a workspace. + +Returns [`Workspace`](#workspace). + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `id` | [`RemoteDevelopmentWorkspaceID!`](#remotedevelopmentworkspaceid) | Find a workspace by its ID. | + +### `Query.workspaces` + +Find Workspaces visible to the current user. + +Returns [`WorkspaceConnection`](#workspaceconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Array of global workspace IDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. | + ## `Mutation` type The `Mutation` type contains all the mutations you can execute. @@ -6835,6 +6863,51 @@ Input type: `WorkItemUpdateTaskInput` | `task` | [`WorkItem`](#workitem) | Updated task. | | `workItem` | [`WorkItem`](#workitem) | Updated work item. | +### `Mutation.workspaceCreate` + +Input type: `WorkspaceCreateInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `clusterAgentId` | [`ClustersAgentID!`](#clustersagentid) | ID of the cluster agent the created workspace will be associated with. | +| `desiredState` | [`String!`](#string) | Desired state of the created workspace. | +| `devfilePath` | [`String!`](#string) | Project repo git path containing the devfile used to configure the workspace. | +| `devfileRef` | [`String!`](#string) | Project repo git ref containing the devfile used to configure the workspace. | +| `editor` | [`String!`](#string) | Editor to inject into the created workspace. Must match a configured template. | +| `maxHoursBeforeTermination` | [`Int!`](#int) | Maximum hours the workspace can exist before it is automatically terminated. | +| `projectId` | [`ProjectID!`](#projectid) | ID of the project that will provide the Devfile for the created workspace. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +| `workspace` | [`Workspace`](#workspace) | Created workspace. | + +### `Mutation.workspaceUpdate` + +Input type: `WorkspaceUpdateInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `desiredState` | [`String!`](#string) | Desired state of the created workspace. | +| `id` | [`RemoteDevelopmentWorkspaceID!`](#remotedevelopmentworkspaceid) | Global ID of the workspace. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +| `workspace` | [`Workspace`](#workspace) | Created workspace. | + ## Connections Some types in our schema are `Connection` types - they represent a paginated @@ -11109,6 +11182,29 @@ The edge type for [`WorkItemType`](#workitemtype). | `cursor` | [`String!`](#string) | A cursor for use in pagination. | | `node` | [`WorkItemType`](#workitemtype) | The item at the end of the edge. | +#### `WorkspaceConnection` + +The connection type for [`Workspace`](#workspace). + +##### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `edges` | [`[WorkspaceEdge]`](#workspaceedge) | A list of edges. | +| `nodes` | [`[Workspace]`](#workspace) | A list of nodes. | +| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. | + +#### `WorkspaceEdge` + +The edge type for [`Workspace`](#workspace). + +##### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `cursor` | [`String!`](#string) | A cursor for use in pagination. | +| `node` | [`Workspace`](#workspace) | The item at the end of the edge. | + ## Object types Object types represent the resources that the GitLab GraphQL API can return. @@ -16745,6 +16841,22 @@ four standard [pagination arguments](#connection-pagination-arguments): | `state` | [`[TodoStateEnum!]`](#todostateenum) | State of the todo. | | `type` | [`[TodoTargetEnum!]`](#todotargetenum) | Type of the todo. | +##### `MergeRequestAssignee.workspaces` + +Workspaces owned by the user. + +Returns [`WorkspaceConnection`](#workspaceconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Array of global workspace IDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. | + ### `MergeRequestAuthor` The author of the merge request. @@ -16995,6 +17107,22 @@ four standard [pagination arguments](#connection-pagination-arguments): | `state` | [`[TodoStateEnum!]`](#todostateenum) | State of the todo. | | `type` | [`[TodoTargetEnum!]`](#todotargetenum) | Type of the todo. | +##### `MergeRequestAuthor.workspaces` + +Workspaces owned by the user. + +Returns [`WorkspaceConnection`](#workspaceconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Array of global workspace IDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. | + ### `MergeRequestDiffRegistry` Represents the Geo sync and verification state of a Merge Request diff. @@ -17264,6 +17392,22 @@ four standard [pagination arguments](#connection-pagination-arguments): | `state` | [`[TodoStateEnum!]`](#todostateenum) | State of the todo. | | `type` | [`[TodoTargetEnum!]`](#todotargetenum) | Type of the todo. | +##### `MergeRequestParticipant.workspaces` + +Workspaces owned by the user. + +Returns [`WorkspaceConnection`](#workspaceconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Array of global workspace IDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. | + ### `MergeRequestPermissions` Check permissions for the current user on a merge request. @@ -17533,6 +17677,22 @@ four standard [pagination arguments](#connection-pagination-arguments): | `state` | [`[TodoStateEnum!]`](#todostateenum) | State of the todo. | | `type` | [`[TodoTargetEnum!]`](#todotargetenum) | Type of the todo. | +##### `MergeRequestReviewer.workspaces` + +Workspaces owned by the user. + +Returns [`WorkspaceConnection`](#workspaceconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Array of global workspace IDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. | + ### `Metadata` #### Fields @@ -21948,6 +22108,22 @@ four standard [pagination arguments](#connection-pagination-arguments): | `state` | [`[TodoStateEnum!]`](#todostateenum) | State of the todo. | | `type` | [`[TodoTargetEnum!]`](#todotargetenum) | Type of the todo. | +##### `UserCore.workspaces` + +Workspaces owned by the user. + +Returns [`WorkspaceConnection`](#workspaceconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Array of global workspace IDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. | + ### `UserMergeRequestInteraction` Information about a merge request given a specific user. @@ -22932,6 +23108,35 @@ Represents a weight widget. | `type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. | | `weight` | [`Int`](#int) | Weight of the work item. | +### `Workspace` + +Represents a remote development workspace. + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `actualState` | [`String!`](#string) | Actual state of the workspace. | +| `clusterAgent` | [`ClusterAgent!`](#clusteragent) | Kubernetes Agent associated with the workspace. | +| `createdAt` | [`Time!`](#time) | Timestamp of workspace creation. | +| `deploymentResourceVersion` | [`Int`](#int) | ResourceVersion of the Deployment resource for the workspace. | +| `desiredState` | [`String!`](#string) | Desired state of the workspace. | +| `desiredStateUpdatedAt` | [`Time!`](#time) | Timestamp of last update to desired state. | +| `devfile` | [`String!`](#string) | Source YAML of the devfile used to configure the workspace. | +| `devfilePath` | [`String!`](#string) | Project repo git path containing the devfile used to configure the workspace. | +| `devfileRef` | [`String!`](#string) | Project repo git ref containing the devfile used to configure the workspace. | +| `editor` | [`String!`](#string) | Editor used to configure the workspace. Must match a configured template. | +| `id` | [`RemoteDevelopmentWorkspaceID!`](#remotedevelopmentworkspaceid) | Global ID of the workspace. | +| `maxHoursBeforeTermination` | [`Int!`](#int) | Maximum hours the workspace can exist before it is automatically terminated. | +| `name` | [`String!`](#string) | Name of the workspace in Kubernetes. | +| `namespace` | [`String!`](#string) | Namespace of the workspace in Kubernetes. | +| `processedDevfile` | [`String!`](#string) | Processed YAML of the devfile used to configure the workspace. | +| `projectId` | [`ID!`](#id) | ID of the Project providing the Devfile for the workspace. | +| `respondedToAgentAt` | [`Time`](#time) | Timestamp of last response sent to GA4K for the workspace. | +| `updatedAt` | [`Time!`](#time) | Timestamp of last update to any mutable workspace property. | +| `url` | [`String!`](#string) | URL of the workspace. | +| `user` | [`UserCore!`](#usercore) | Owner of the workspace. | + ### `X509Certificate` Represents an X.509 certificate. @@ -25857,6 +26062,12 @@ A `ReleasesLinkID` is a global ID. It is encoded as a string. An example `ReleasesLinkID` is: `"gid://gitlab/Releases::Link/1"`. +### `RemoteDevelopmentWorkspaceID` + +A `RemoteDevelopmentWorkspaceID` is a global ID. It is encoded as a string. + +An example `RemoteDevelopmentWorkspaceID` is: `"gid://gitlab/RemoteDevelopment::Workspace/1"`. + ### `SecurityTrainingProviderID` A `SecurityTrainingProviderID` is a global ID. It is encoded as a string. @@ -26637,6 +26848,22 @@ four standard [pagination arguments](#connection-pagination-arguments): | `state` | [`[TodoStateEnum!]`](#todostateenum) | State of the todo. | | `type` | [`[TodoTargetEnum!]`](#todotargetenum) | Type of the todo. | +###### `User.workspaces` + +Workspaces owned by the user. + +Returns [`WorkspaceConnection`](#workspaceconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +####### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Array of global workspace IDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. | + #### `WorkItemWidget` Implementations: diff --git a/ee/app/assets/javascripts/remote_development/components/create/get_project_details_query.vue b/ee/app/assets/javascripts/remote_development/components/create/get_project_details_query.vue index 5c6725273cd6f3..f14f20903c0155 100644 --- a/ee/app/assets/javascripts/remote_development/components/create/get_project_details_query.vue +++ b/ee/app/assets/javascripts/remote_development/components/create/get_project_details_query.vue @@ -71,6 +71,7 @@ export default { } try { + // noinspection JSCheckFunctionSignatures const { data, error } = await this.$apollo.query({ query: getGroupClusterAgentsQuery, variables: { groupPath }, diff --git a/ee/app/assets/javascripts/remote_development/components/list/start_workspace_button.vue b/ee/app/assets/javascripts/remote_development/components/list/start_workspace_button.vue index f25f1c30542d86..95989cad515b7b 100644 --- a/ee/app/assets/javascripts/remote_development/components/list/start_workspace_button.vue +++ b/ee/app/assets/javascripts/remote_development/components/list/start_workspace_button.vue @@ -28,7 +28,11 @@ export default { computed: { isVisible() { return ( - [WORKSPACE_STATES.stopped, WORKSPACE_STATES.starting].includes(this.actualState) && + [ + WORKSPACE_STATES.creationRequested, + WORKSPACE_STATES.stopped, + WORKSPACE_STATES.starting, + ].includes(this.actualState) && [WORKSPACE_DESIRED_STATES.running, WORKSPACE_DESIRED_STATES.stopped].includes( this.desiredState, ) diff --git a/ee/app/assets/javascripts/remote_development/components/list/workspace_state_indicator.vue b/ee/app/assets/javascripts/remote_development/components/list/workspace_state_indicator.vue index 666db17191ed29..07fc1950216627 100644 --- a/ee/app/assets/javascripts/remote_development/components/list/workspace_state_indicator.vue +++ b/ee/app/assets/javascripts/remote_development/components/list/workspace_state_indicator.vue @@ -1,7 +1,12 @@