Skip to content

Dont mutate env vars outside the BuildEnv classes #8340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions readthedocs/doc_builder/environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ def __init__(
self.shell = shell
self.cwd = cwd or settings.RTD_DOCKER_WORKDIR
self.user = user or settings.RTD_DOCKER_USER
self.environment = environment.copy() if environment else {}
if 'PATH' in self.environment:
self._environment = environment.copy() if environment else {}
if 'PATH' in self._environment:
raise BuildEnvironmentError('\'PATH\' can\'t be set. Use bin_path')

self.build_env = build_env
Expand All @@ -132,7 +132,7 @@ def run(self):
log.info("Running: '%s' [%s]", self.get_command(), self.cwd)

self.start_time = datetime.utcnow()
environment = self.environment.copy()
environment = self._environment.copy()
if 'DJANGO_SETTINGS_MODULE' in environment:
del environment['DJANGO_SETTINGS_MODULE']
if 'PYTHONPATH' in environment:
Expand Down Expand Up @@ -302,7 +302,7 @@ def run(self):
exec_cmd = client.exec_create(
container=self.build_env.container_id,
cmd=self.get_wrapped_command(),
environment=self.environment,
environment=self._environment,
user=self.user,
workdir=self.cwd,
stdout=True,
Expand Down Expand Up @@ -384,7 +384,7 @@ class BaseEnvironment:
def __init__(self, project, environment=None):
# TODO: maybe we can remove this Project dependency also
self.project = project
self.environment = environment or {}
self._environment = environment or {}
self.commands = []

def record_command(self, command):
Expand Down Expand Up @@ -423,7 +423,7 @@ def run_command_class(
kwargs.update({'record_as_success': record_as_success})

# Remove PATH from env, and set it to bin_path if it isn't passed in
environment = self.environment.copy()
environment = self._environment.copy()
env_path = environment.pop('BIN_PATH', None)
if 'bin_path' not in kwargs and env_path:
kwargs['bin_path'] = env_path
Expand Down
15 changes: 11 additions & 4 deletions readthedocs/projects/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,13 @@ def validate_duplicate_reserved_versions(self, tags_data, branches_data):
RepositoryError.DUPLICATED_RESERVED_VERSIONS,
)

def get_vcs_env_vars(self):
"""Get environment variables to be included in the VCS setup step."""
env = self.get_rtd_env_vars()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see we're still passing them here 👍

# Don't prompt for username, this requires Git 2.3+
env['GIT_TERMINAL_PROMPT'] = '0'
return env

def get_rtd_env_vars(self):
"""Get bash environment variables specific to Read the Docs."""
env = {
Expand Down Expand Up @@ -370,7 +377,7 @@ def run(self, version_pk): # pylint: disable=arguments-differ
version=self.version,
record=False,
update_on_success=False,
environment=self.get_rtd_env_vars(),
environment=self.get_vcs_env_vars(),

This comment was marked as outdated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also like to see get_env_vars renamed to get_build_env_vars if we're doing this refactor, to keep things clear.

)
log.info(
'Running sync_repository_task: project=%s version=%s',
Expand Down Expand Up @@ -657,7 +664,7 @@ def run_setup(self, record=True):
build=self.build,
record=record,
update_on_success=False,
environment=self.get_rtd_env_vars(),
environment=self.get_vcs_env_vars(),
)
self.build_start_time = environment.start_time

Expand Down Expand Up @@ -734,7 +741,7 @@ def run_build(self, record):
:param record: whether or not record all the commands in the ``Build``
instance
"""
env_vars = self.get_env_vars()
env_vars = self.get_build_env_vars()

if settings.DOCKER_ENABLE:
env_cls = DockerBuildEnvironment
Expand Down Expand Up @@ -925,7 +932,7 @@ def setup_vcs(self, environment):
if commit:
self.build['commit'] = commit

def get_env_vars(self):
def get_build_env_vars(self):
"""Get bash environment variables used for all builder commands."""
env = self.get_rtd_env_vars()

Expand Down
6 changes: 2 additions & 4 deletions readthedocs/rtd_tests/tests/test_builds.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os
from unittest import mock

from allauth.socialaccount.models import SocialAccount
from django.contrib.auth.models import User
from django.test import TestCase
from django.utils import timezone
Expand All @@ -21,7 +20,6 @@
from readthedocs.doc_builder.environments import LocalBuildEnvironment
from readthedocs.doc_builder.exceptions import DuplicatedBuildError
from readthedocs.doc_builder.python_environments import Virtualenv
from readthedocs.oauth.models import RemoteRepository
from readthedocs.projects.models import EnvironmentVariable, Feature, Project
from readthedocs.projects.tasks import UpdateDocsTaskStep
from readthedocs.rtd_tests.tests.test_config_integration import create_load
Expand Down Expand Up @@ -363,7 +361,7 @@ def test_get_env_vars(self):
),
'TOKEN': 'a1b2c3',
}
self.assertEqual(task.get_env_vars(), env)
self.assertEqual(task.get_build_env_vars(), env)

# mock this object to make sure that we are in a conda env
task.config = mock.Mock(conda=True)
Expand All @@ -377,7 +375,7 @@ def test_get_env_vars(self):
'bin',
),
})
self.assertEqual(task.get_env_vars(), env)
self.assertEqual(task.get_build_env_vars(), env)


class BuildModelTests(TestCase):
Expand Down
2 changes: 1 addition & 1 deletion readthedocs/rtd_tests/tests/test_doc_building.py
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ def test_command_env(self):
env = {'FOOBAR': 'foobar', 'BIN_PATH': 'foobar'}
cmd = BuildCommand('echo', environment=env)
for key in list(env.keys()):
self.assertEqual(cmd.environment[key], env[key])
self.assertEqual(cmd._environment[key], env[key])

def test_result(self):
"""Test result of output using unix true/false commands."""
Expand Down
9 changes: 0 additions & 9 deletions readthedocs/vcs_support/backends/git.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Git-related utilities."""

import logging
import os
import re

import git
Expand Down Expand Up @@ -359,11 +358,3 @@ def ref_exists(self, ref):
except (BadName, ValueError):
return False
return False

@property
def env(self):
env = super().env
env['GIT_DIR'] = os.path.join(self.working_dir, '.git')
# Don't prompt for username, this requires Git 2.3+
env['GIT_TERMINAL_PROMPT'] = '0'
return env
7 changes: 0 additions & 7 deletions readthedocs/vcs_support/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ def __init__(
from readthedocs.doc_builder.environments import LocalBuildEnvironment
self.environment = environment or LocalBuildEnvironment(record=False)

# Update the env variables with the proper VCS env variables
self.environment.environment.update(self.env)

def check_working_dir(self):
if not os.path.exists(self.working_dir):
os.makedirs(self.working_dir)
Expand All @@ -84,10 +81,6 @@ def make_clean_working_dir(self):
shutil.rmtree(self.working_dir, ignore_errors=True)
self.check_working_dir()

@property
def env(self):
return {}

def update(self):
"""
Update a local copy of the repository in self.working_dir.
Expand Down