44from __future__ import division
55from __future__ import print_function
66from __future__ import unicode_literals
7- '''
7+
8+ """
89
910Extends FBCodeBuilder to produce Docker context directories.
1011
1516 that change the least often, and
1617 - Put the steps that you are debugging towards the very end.
1718
18- '''
19+ """
1920import logging
2021import os
2122import shutil
2223import tempfile
2324
2425from fbcode_builder import FBCodeBuilder
25- from shell_quoting import (
26- raw_shell , shell_comment , shell_join , ShellQuoted , path_join
27- )
26+ from shell_quoting import raw_shell , shell_comment , shell_join , ShellQuoted , path_join
2827from utils import recursively_flatten_list , run_command
2928
3029
3130class DockerFBCodeBuilder (FBCodeBuilder ):
32-
3331 def _user (self ):
34- return self .option (' user' , ' root' )
32+ return self .option (" user" , " root" )
3533
3634 def _change_user (self ):
37- return ShellQuoted (' USER {u}' ).format (u = self ._user ())
35+ return ShellQuoted (" USER {u}" ).format (u = self ._user ())
3836
3937 def setup (self ):
4038 # Please add RPM-based OSes here as appropriate.
@@ -63,17 +61,18 @@ def python_venv(self):
6361 # it is present when the resulting container is run add to PATH
6462 actions = []
6563 if self .option ("PYTHON_VENV" , "OFF" ) == "ON" :
66- actions = ShellQuoted ('ENV PATH={p}:$PATH' ).format (
67- p = path_join (self .option ('prefix' ), "venv" , "bin" ))
68- return (actions )
64+ actions = ShellQuoted ("ENV PATH={p}:$PATH" ).format (
65+ p = path_join (self .option ("prefix" ), "venv" , "bin" )
66+ )
67+ return actions
6968
7069 def step (self , name , actions ):
71- assert ' \n ' not in name , ' Name {0} would span > 1 line' .format (name )
72- b = ShellQuoted ('' )
73- return [ShellQuoted (' ### {0} ###' .format (name )), b ] + actions + [b ]
70+ assert " \n " not in name , " Name {0} would span > 1 line" .format (name )
71+ b = ShellQuoted ("" )
72+ return [ShellQuoted (" ### {0} ###" .format (name )), b ] + actions + [b ]
7473
7574 def run (self , shell_cmd ):
76- return ShellQuoted (' RUN {cmd}' ).format (cmd = shell_cmd )
75+ return ShellQuoted (" RUN {cmd}" ).format (cmd = shell_cmd )
7776
7877 def set_env (self , key , value ):
7978 return ShellQuoted ("ENV {key}={val}" ).format (key = key , val = value )
@@ -84,12 +83,12 @@ def workdir(self, dir):
8483 # by root:root -- the explicit `mkdir` works around the bug:
8584 # USER nobody
8685 # WORKDIR build
87- ShellQuoted (' USER root' ),
88- ShellQuoted (' RUN mkdir -p {d} && chown {u} {d}' ).format (
86+ ShellQuoted (" USER root" ),
87+ ShellQuoted (" RUN mkdir -p {d} && chown {u} {d}" ).format (
8988 d = dir , u = self ._user ()
9089 ),
9190 self ._change_user (),
92- ShellQuoted (' WORKDIR {dir}' ).format (dir = dir ),
91+ ShellQuoted (" WORKDIR {dir}" ).format (dir = dir ),
9392 ]
9493
9594 def comment (self , comment ):
@@ -99,60 +98,58 @@ def comment(self, comment):
9998
10099 def copy_local_repo (self , repo_dir , dest_name ):
101100 fd , archive_path = tempfile .mkstemp (
102- prefix = ' local_repo_{0}_' .format (dest_name ),
103- suffix = ' .tgz' ,
104- dir = os .path .abspath (self .option (' docker_context_dir' )),
101+ prefix = " local_repo_{0}_" .format (dest_name ),
102+ suffix = " .tgz" ,
103+ dir = os .path .abspath (self .option (" docker_context_dir" )),
105104 )
106105 os .close (fd )
107- run_command (' tar' , ' czf' , archive_path , '.' , cwd = repo_dir )
106+ run_command (" tar" , " czf" , archive_path , "." , cwd = repo_dir )
108107 return [
109- ShellQuoted (' ADD {archive} {dest_name}' ).format (
108+ ShellQuoted (" ADD {archive} {dest_name}" ).format (
110109 archive = os .path .basename (archive_path ), dest_name = dest_name
111110 ),
112111 # Docker permissions make very little sense... see also workdir()
113- ShellQuoted ('USER root' ),
114- ShellQuoted ('RUN chown -R {u} {d}' ).format (
115- d = dest_name , u = self ._user ()
116- ),
112+ ShellQuoted ("USER root" ),
113+ ShellQuoted ("RUN chown -R {u} {d}" ).format (d = dest_name , u = self ._user ()),
117114 self ._change_user (),
118115 ]
119116
120117 def _render_impl (self , steps ):
121- return raw_shell (shell_join (' \n ' , recursively_flatten_list (steps )))
118+ return raw_shell (shell_join (" \n " , recursively_flatten_list (steps )))
122119
123120 def debian_ccache_setup_steps (self ):
124- source_ccache_tgz = self .option (' ccache_tgz' , '' )
121+ source_ccache_tgz = self .option (" ccache_tgz" , "" )
125122 if not source_ccache_tgz :
126- logging .info (' Docker ccache not enabled' )
123+ logging .info (" Docker ccache not enabled" )
127124 return []
128125
129- dest_ccache_tgz = os .path .join (
130- self .option ('docker_context_dir' ), 'ccache.tgz'
131- )
126+ dest_ccache_tgz = os .path .join (self .option ("docker_context_dir" ), "ccache.tgz" )
132127
133128 try :
134129 try :
135130 os .link (source_ccache_tgz , dest_ccache_tgz )
136131 except OSError :
137132 logging .exception (
138- 'Hard-linking {s} to {d} failed, falling back to copy'
139- .format (s = source_ccache_tgz , d = dest_ccache_tgz )
133+ "Hard-linking {s} to {d} failed, falling back to copy" .format (
134+ s = source_ccache_tgz , d = dest_ccache_tgz
135+ )
140136 )
141137 shutil .copyfile (source_ccache_tgz , dest_ccache_tgz )
142138 except Exception :
143139 logging .exception (
144- 'Failed to copy or link {s} to {d}, aborting'
145- .format (s = source_ccache_tgz , d = dest_ccache_tgz )
140+ "Failed to copy or link {s} to {d}, aborting" .format (
141+ s = source_ccache_tgz , d = dest_ccache_tgz
142+ )
146143 )
147144 raise
148145
149146 return [
150147 # Separate layer so that in development we avoid re-downloads.
151- self .run (ShellQuoted (' apt-get install -yq ccache' )),
152- ShellQuoted (' ADD ccache.tgz /' ),
148+ self .run (ShellQuoted (" apt-get install -yq ccache" )),
149+ ShellQuoted (" ADD ccache.tgz /" ),
153150 ShellQuoted (
154151 # Set CCACHE_DIR before the `ccache` invocations below.
155- ' ENV CCACHE_DIR=/ccache '
152+ " ENV CCACHE_DIR=/ccache "
156153 # No clang support for now, so it's easiest to hardcode gcc.
157154 'CC="ccache gcc" CXX="ccache g++" '
158155 # Always log for ease of debugging. For real FB projects,
@@ -166,26 +163,28 @@ def debian_ccache_setup_steps(self):
166163 #
167164 # apt-get install sharutils
168165 # bzip2 -9 < /tmp/ccache.log | uuencode -m ccache.log.bz2
169- 'CCACHE_LOGFILE=/tmp/ccache.log'
166+ "CCACHE_LOGFILE=/tmp/ccache.log"
167+ ),
168+ self .run (
169+ ShellQuoted (
170+ # Future: Skipping this part made this Docker step instant,
171+ # saving ~1min of build time. It's unclear if it is the
172+ # chown or the du, but probably the chown -- since a large
173+ # part of the cost is incurred at image save time.
174+ #
175+ # ccache.tgz may be empty, or may have the wrong
176+ # permissions.
177+ "mkdir -p /ccache && time chown -R nobody /ccache && "
178+ "time du -sh /ccache && "
179+ # Reset stats so `docker_build_with_ccache.sh` can print
180+ # useful values at the end of the run.
181+ "echo === Prev run stats === && ccache -s && ccache -z && "
182+ # Record the current time to let travis_build.sh figure out
183+ # the number of bytes in the cache that are actually used --
184+ # this is crucial for tuning the maximum cache size.
185+ "date +%s > /FBCODE_BUILDER_CCACHE_START_TIME && "
186+ # The build running as `nobody` should be able to write here
187+ "chown nobody /tmp/ccache.log"
188+ )
170189 ),
171- self .run (ShellQuoted (
172- # Future: Skipping this part made this Docker step instant,
173- # saving ~1min of build time. It's unclear if it is the
174- # chown or the du, but probably the chown -- since a large
175- # part of the cost is incurred at image save time.
176- #
177- # ccache.tgz may be empty, or may have the wrong
178- # permissions.
179- 'mkdir -p /ccache && time chown -R nobody /ccache && '
180- 'time du -sh /ccache && '
181- # Reset stats so `docker_build_with_ccache.sh` can print
182- # useful values at the end of the run.
183- 'echo === Prev run stats === && ccache -s && ccache -z && '
184- # Record the current time to let travis_build.sh figure out
185- # the number of bytes in the cache that are actually used --
186- # this is crucial for tuning the maximum cache size.
187- 'date +%s > /FBCODE_BUILDER_CCACHE_START_TIME && '
188- # The build running as `nobody` should be able to write here
189- 'chown nobody /tmp/ccache.log'
190- )),
191190 ]
0 commit comments