diff --git a/ee/lib/remote_development/workspaces/create/devfile_processor.rb b/ee/lib/remote_development/workspaces/create/devfile_processor.rb index 9bfd00e399abc4e0e5eb7db1fc66ea0c7d6cd1b9..12b63cf203a3184d3b3d35d36c8f68d7f835d92d 100644 --- a/ee/lib/remote_development/workspaces/create/devfile_processor.rb +++ b/ee/lib/remote_development/workspaces/create/devfile_processor.rb @@ -136,17 +136,24 @@ def add_project_cloner(flattened_devfile:, project:, volume_reference:, volume_m # reasons image_name = 'alpine/git' image_tag = '2.36.3' - clone_dir = "#{volume_mount_dir}/#{project.path}" - - # project is cloned only if one doesn't exist already - # this done to avoid resetting user's modifications to the workspace project_url = project.http_url_to_repo project_ref = project.default_branch + + # The project is cloned only if one doesn't exist already. + # This done to avoid resetting user's modifications to the workspace. + # After cloning the project, set the user's git configuration - name and email. + # The name and email are read from environment variable because we do not want to + # store PII in the processed devfile in the database. + # The environment variables are injected into the gl-cloner-injector container component + # when the Kubernetes resources are generated. container_args = <<~SH.chomp if [ ! -d '#{clone_dir}' ]; then git clone --branch #{Shellwords.shellescape(project_ref)} #{Shellwords.shellescape(project_url)} #{Shellwords.shellescape(clone_dir)}; + cd #{Shellwords.shellescape(clone_dir)}; + git config user.name "${GIT_AUTHOR_NAME}"; + git config user.email "${GIT_AUTHOR_EMAIL}"; fi SH diff --git a/ee/lib/remote_development/workspaces/reconcile/desired_config_generator.rb b/ee/lib/remote_development/workspaces/reconcile/desired_config_generator.rb index 8414924bead1ec8af520aaa5b4e6103cedf1dc1b..ab806ff2fb53b91b6fdfdc1e93b6214cc2e3754d 100644 --- a/ee/lib/remote_development/workspaces/reconcile/desired_config_generator.rb +++ b/ee/lib/remote_development/workspaces/reconcile/desired_config_generator.rb @@ -12,6 +12,7 @@ def generate_desired_config(workspace:) namespace = workspace.namespace agent = workspace.agent desired_state = workspace.desired_state + user = workspace.user domain_template = "{{.port}}-#{name}.#{workspace.dns_zone}" @@ -33,7 +34,8 @@ def generate_desired_config(workspace:) replicas: replicas, domain_template: domain_template, labels: labels, - annotations: annotations + annotations: annotations, + user: user ) workspace_resources.insert(0, workspace_inventory_config_map) diff --git a/ee/lib/remote_development/workspaces/reconcile/devfile_parser.rb b/ee/lib/remote_development/workspaces/reconcile/devfile_parser.rb index 72573af2dac7fbf1d37eec663c2158545f61b3f0..4c3ac8d81f7b5e45923dfabdbe8d7a6c5639f5d3 100644 --- a/ee/lib/remote_development/workspaces/reconcile/devfile_parser.rb +++ b/ee/lib/remote_development/workspaces/reconcile/devfile_parser.rb @@ -6,7 +6,7 @@ module RemoteDevelopment module Workspaces module Reconcile class DevfileParser - def get_all(processed_devfile:, name:, namespace:, replicas:, domain_template:, labels:, annotations:) + def get_all(processed_devfile:, name:, namespace:, replicas:, domain_template:, labels:, annotations:, user:) workspace_resources_yaml = Devfile::Parser.get_all( processed_devfile, name, @@ -18,7 +18,8 @@ def get_all(processed_devfile:, name:, namespace:, replicas:, domain_template:, 'none' ) workspace_resources = YAML.load_stream(workspace_resources_yaml) - set_security_context(workspace_resources: workspace_resources) + workspace_resources = set_security_context(workspace_resources: workspace_resources) + set_git_configuration(workspace_resources: workspace_resources, user: user) end private @@ -63,6 +64,30 @@ def set_security_context(workspace_resources:) end workspace_resources end + + def set_git_configuration(workspace_resources:, user:) + workspace_resources.each do |workspace_resource| + next unless workspace_resource.fetch('kind') == 'Deployment' + + # Set git configuration for the `gl-cloner-injector-*` + pod_spec = workspace_resource.fetch('spec').fetch('template').fetch('spec') + pod_spec.fetch('initContainers').each do |init_container| + next unless init_container.fetch('name').starts_with?('gl-cloner-injector-') + + init_container.fetch('env').concat([ + { + 'name' => 'GIT_AUTHOR_NAME', + 'value' => user.name + }, + { + 'name' => 'GIT_AUTHOR_EMAIL', + 'value' => user.email + } + ]) + end + end + workspace_resources + end end end end diff --git a/ee/spec/features/remote_development/workspaces_spec.rb b/ee/spec/features/remote_development/workspaces_spec.rb index 876326a8ec46db3c82b0228b81de7354cc9cd8d9..54aa267235ee5240fc8837a42fe7317155d5d994 100644 --- a/ee/spec/features/remote_development/workspaces_spec.rb +++ b/ee/spec/features/remote_development/workspaces_spec.rb @@ -125,7 +125,9 @@ def simulate_first_poll(id:, name:, namespace:) workspace_namespace: namespace, agent_id: agent.id, owning_inventory: "#{name}-workspace-inventory", - started: true + started: true, + user_name: user.name, + user_email: user.email ) config_to_apply = info.fetch(:config_to_apply) @@ -145,7 +147,9 @@ def simulate_second_poll(id:, name:, namespace:) resource_version: resource_version, previous_actual_state: RemoteDevelopment::Workspaces::States::STARTING, current_actual_state: RemoteDevelopment::Workspaces::States::RUNNING, - workspace_exists: false + workspace_exists: false, + user_name: user.name, + user_email: user.email ) reconcile_post_response = simulate_agentk_reconcile_post(workspace_agent_infos: [workspace_agent_info]) diff --git a/ee/spec/fixtures/remote_development/example.processed-devfile.yaml b/ee/spec/fixtures/remote_development/example.processed-devfile.yaml index 817b960f0db1eb908b5ccdf22fc57c2c978bdaa0..ea814cef8e0b4e049d15f647d19659ada0b039e7 100644 --- a/ee/spec/fixtures/remote_development/example.processed-devfile.yaml +++ b/ee/spec/fixtures/remote_development/example.processed-devfile.yaml @@ -54,6 +54,9 @@ components: if [ ! -d '/projects/test-project' ]; then git clone --branch master http://localhost/test-group/test-project.git /projects/test-project; + cd /projects/test-project; + git config user.name "${GIT_AUTHOR_NAME}"; + git config user.email "${GIT_AUTHOR_EMAIL}"; fi command: - "/bin/sh" diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/actual_state_calculator_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/actual_state_calculator_spec.rb index ad3647ce7cb174b4d7d5090209dbfd755e925ade..b745e8b64e4597b352ed366df9127b0051c043b7 100644 --- a/ee/spec/lib/remote_development/workspaces/reconcile/actual_state_calculator_spec.rb +++ b/ee/spec/lib/remote_development/workspaces/reconcile/actual_state_calculator_spec.rb @@ -52,7 +52,9 @@ resource_version: 1, previous_actual_state: previous_actual_state, current_actual_state: current_actual_state, - workspace_exists: workspace_exists + workspace_exists: workspace_exists, + user_name: "does not matter", + user_email: "does@not.matter" ) workspace_agent_info.fetch('latest_k8s_deployment_info') end diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/agent_info_parser_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/agent_info_parser_spec.rb index b334559b499173bac05abf9bad73a96579775ce7..e46cf6bb3213c3588f5bb97d1ea868b1a895de14 100644 --- a/ee/spec/lib/remote_development/workspaces/reconcile/agent_info_parser_spec.rb +++ b/ee/spec/lib/remote_development/workspaces/reconcile/agent_info_parser_spec.rb @@ -5,6 +5,7 @@ RSpec.describe RemoteDevelopment::Workspaces::Reconcile::AgentInfoParser, feature_category: :remote_development do include_context 'with remote development shared fixtures' + let(:user) { create(:user) } let(:workspace) { create(:workspace) } let(:workspace_agent_info) do @@ -17,7 +18,9 @@ resource_version: '1', previous_actual_state: previous_actual_state, current_actual_state: current_actual_state, - workspace_exists: false + workspace_exists: false, + user_name: user.name, + user_email: user.email ) end diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/desired_config_generator_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/desired_config_generator_spec.rb index eed9e8de52bbd1b5a547dbb24b9ff1d71cf32a69..fb43302af62ec45a4c6d03655ad371a2df46513e 100644 --- a/ee/spec/lib/remote_development/workspaces/reconcile/desired_config_generator_spec.rb +++ b/ee/spec/lib/remote_development/workspaces/reconcile/desired_config_generator_spec.rb @@ -28,7 +28,9 @@ workspace_namespace: workspace.namespace, agent_id: workspace.agent.id, owning_inventory: owning_inventory, - started: started + started: started, + user_name: user.name, + user_email: user.email ) ) end diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/devfile_parser_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/devfile_parser_spec.rb index 0f7280206b226567a8df95d3877e7922f8c04f3c..bbd7ca91c22b2d069d1879ea733f271b0e61d215 100644 --- a/ee/spec/lib/remote_development/workspaces/reconcile/devfile_parser_spec.rb +++ b/ee/spec/lib/remote_development/workspaces/reconcile/devfile_parser_spec.rb @@ -22,7 +22,9 @@ agent_id: workspace.agent.id, owning_inventory: owning_inventory, started: true, - include_inventory: false + include_inventory: false, + user_name: user.name, + user_email: user.email ) ) end @@ -43,7 +45,8 @@ 'config.k8s.io/owning-inventory' => owning_inventory, 'workspaces.gitlab.com/host-template' => domain_template, 'workspaces.gitlab.com/id' => workspace.id - } + }, + user: user ) # noinspection RubyResolve diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_scenarios_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_scenarios_spec.rb index e2582e366725bc6a44419d46c4335a3455ef43e5..e38c368d0277b2158149e13348c0b5a3454ff851 100644 --- a/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_scenarios_spec.rb +++ b/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_scenarios_spec.rb @@ -10,6 +10,8 @@ RSpec.describe ::RemoteDevelopment::Workspaces::Reconcile::ReconcileProcessor, 'Partial Update Scenarios', feature_category: :remote_development do include_context 'with remote development shared fixtures' + let_it_be(:user) { create(:user) } + # See following documentation for details on all scenarios: # # https://gitlab.com/gitlab-org/remote-development/gitlab-remote-development-docs/-/blob/main/doc/workspace-updates.md @@ -204,7 +206,9 @@ resource_version: deployment_resource_version_from_agent, current_actual_state: current_actual_state, previous_actual_state: previous_actual_state, - workspace_exists: workspace_exists + workspace_exists: workspace_exists, + user_name: user.name, + user_email: user.email ) ] else diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_spec.rb index 3bc025852934f8cccc7fe6ccf12e889bb6e6df13..6b67d6ed5550d9abb0e1f558916de5f7b267706c 100644 --- a/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_spec.rb +++ b/ee/spec/lib/remote_development/workspaces/reconcile/reconcile_processor_spec.rb @@ -66,7 +66,9 @@ resource_version: deployment_resource_version_from_agent, previous_actual_state: previous_actual_state, current_actual_state: current_actual_state, - workspace_exists: workspace_exists + workspace_exists: workspace_exists, + user_name: user.name, + user_email: user.email ) end @@ -228,7 +230,9 @@ workspace_namespace: workspace.namespace, agent_id: workspace.agent.id, owning_inventory: owning_inventory, - started: expected_value_for_started + started: expected_value_for_started, + user_name: user.name, + user_email: user.email ) end @@ -371,7 +375,9 @@ resource_version: '42', previous_actual_state: RemoteDevelopment::Workspaces::States::STOPPING, current_actual_state: RemoteDevelopment::Workspaces::States::STOPPED, - workspace_exists: false + workspace_exists: false, + user_name: user.name, + user_email: user.email ) end @@ -412,7 +418,9 @@ workspace_namespace: unprovisioned_workspace.namespace, agent_id: unprovisioned_workspace.agent.id, owning_inventory: owning_inventory, - started: expected_value_for_started + started: expected_value_for_started, + user_name: user.name, + user_email: user.email ) end diff --git a/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb b/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb index 69204c448b12ce2c193c9abbd603000b113a18df..60a3ea938712b67305dd26935f713b2617a64739 100644 --- a/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb +++ b/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb @@ -16,6 +16,8 @@ def create_workspace_agent_info( current_actual_state:, # NOTE: workspace_exists is whether the workspace exists in the cluster at the time of the current_actual_state. workspace_exists:, + user_name:, + user_email:, dns_zone: 'workspaces.localdev.me' ) # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/409787 @@ -314,6 +316,9 @@ def create_workspace_agent_info( if [ ! -d '/projects/test-project' ]; then git clone --branch master #{root_url}test-group/test-project.git /projects/test-project; + cd /projects/test-project; + git config user.name "${GIT_AUTHOR_NAME}"; + git config user.email "${GIT_AUTHOR_EMAIL}"; fi command: ["/bin/sh", "-c"] env: @@ -321,6 +326,10 @@ def create_workspace_agent_info( value: "/projects" - name: PROJECT_SOURCE value: "/projects" + - name: GIT_AUTHOR_NAME + value: #{user_name} + - name: GIT_AUTHOR_EMAIL + value: #{user_email} image: alpine/git:2.36.3 imagePullPolicy: Always name: gl-cloner-injector-gl-cloner-injector-command-1 @@ -400,6 +409,7 @@ def create_workspace_rails_info( }.compact end + # rubocop:disable Metrics/ParameterLists def create_config_to_apply( workspace_id:, workspace_name:, @@ -407,6 +417,8 @@ def create_config_to_apply( agent_id:, owning_inventory:, started:, + user_name:, + user_email:, include_inventory: true, dns_zone: 'workspaces.localdev.me' ) @@ -492,6 +504,9 @@ def create_config_to_apply( if [ ! -d '/projects/test-project' ]; then git clone --branch master #{root_url}test-group/test-project.git /projects/test-project; + cd /projects/test-project; + git config user.name "${GIT_AUTHOR_NAME}"; + git config user.email "${GIT_AUTHOR_EMAIL}"; fi command: ["/bin/sh", "-c"] env: @@ -499,6 +514,10 @@ def create_config_to_apply( value: "/projects" - name: PROJECT_SOURCE value: "/projects" + - name: GIT_AUTHOR_NAME + value: #{user_name} + - name: GIT_AUTHOR_EMAIL + value: #{user_email} image: alpine/git:2.36.3 imagePullPolicy: Always name: gl-cloner-injector-gl-cloner-injector-command-1 @@ -606,6 +625,7 @@ def create_config_to_apply( YAML.dump(resource) end.join end + # rubocop:enable Metrics/ParameterLists def get_workspace_host_template(workspace_name, dns_zone) "\"{{.port}}-#{workspace_name}.#{dns_zone}\""