4
4
from __future__ import division
5
5
from __future__ import print_function
6
6
from __future__ import unicode_literals
7
- '''
7
+
8
+ """
8
9
9
10
Extends FBCodeBuilder to produce Docker context directories.
10
11
15
16
that change the least often, and
16
17
- Put the steps that you are debugging towards the very end.
17
18
18
- '''
19
+ """
19
20
import logging
20
21
import os
21
22
import shutil
22
23
import tempfile
23
24
24
25
from 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
28
27
from utils import recursively_flatten_list , run_command
29
28
30
29
31
30
class DockerFBCodeBuilder (FBCodeBuilder ):
32
-
33
31
def _user (self ):
34
- return self .option (' user' , ' root' )
32
+ return self .option (" user" , " root" )
35
33
36
34
def _change_user (self ):
37
- return ShellQuoted (' USER {u}' ).format (u = self ._user ())
35
+ return ShellQuoted (" USER {u}" ).format (u = self ._user ())
38
36
39
37
def setup (self ):
40
38
# Please add RPM-based OSes here as appropriate.
@@ -63,17 +61,18 @@ def python_venv(self):
63
61
# it is present when the resulting container is run add to PATH
64
62
actions = []
65
63
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
69
68
70
69
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 ]
74
73
75
74
def run (self , shell_cmd ):
76
- return ShellQuoted (' RUN {cmd}' ).format (cmd = shell_cmd )
75
+ return ShellQuoted (" RUN {cmd}" ).format (cmd = shell_cmd )
77
76
78
77
def set_env (self , key , value ):
79
78
return ShellQuoted ("ENV {key}={val}" ).format (key = key , val = value )
@@ -84,12 +83,12 @@ def workdir(self, dir):
84
83
# by root:root -- the explicit `mkdir` works around the bug:
85
84
# USER nobody
86
85
# 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 (
89
88
d = dir , u = self ._user ()
90
89
),
91
90
self ._change_user (),
92
- ShellQuoted (' WORKDIR {dir}' ).format (dir = dir ),
91
+ ShellQuoted (" WORKDIR {dir}" ).format (dir = dir ),
93
92
]
94
93
95
94
def comment (self , comment ):
@@ -99,60 +98,58 @@ def comment(self, comment):
99
98
100
99
def copy_local_repo (self , repo_dir , dest_name ):
101
100
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" )),
105
104
)
106
105
os .close (fd )
107
- run_command (' tar' , ' czf' , archive_path , '.' , cwd = repo_dir )
106
+ run_command (" tar" , " czf" , archive_path , "." , cwd = repo_dir )
108
107
return [
109
- ShellQuoted (' ADD {archive} {dest_name}' ).format (
108
+ ShellQuoted (" ADD {archive} {dest_name}" ).format (
110
109
archive = os .path .basename (archive_path ), dest_name = dest_name
111
110
),
112
111
# 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 ()),
117
114
self ._change_user (),
118
115
]
119
116
120
117
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 )))
122
119
123
120
def debian_ccache_setup_steps (self ):
124
- source_ccache_tgz = self .option (' ccache_tgz' , '' )
121
+ source_ccache_tgz = self .option (" ccache_tgz" , "" )
125
122
if not source_ccache_tgz :
126
- logging .info (' Docker ccache not enabled' )
123
+ logging .info (" Docker ccache not enabled" )
127
124
return []
128
125
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" )
132
127
133
128
try :
134
129
try :
135
130
os .link (source_ccache_tgz , dest_ccache_tgz )
136
131
except OSError :
137
132
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
+ )
140
136
)
141
137
shutil .copyfile (source_ccache_tgz , dest_ccache_tgz )
142
138
except Exception :
143
139
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
+ )
146
143
)
147
144
raise
148
145
149
146
return [
150
147
# 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 /" ),
153
150
ShellQuoted (
154
151
# Set CCACHE_DIR before the `ccache` invocations below.
155
- ' ENV CCACHE_DIR=/ccache '
152
+ " ENV CCACHE_DIR=/ccache "
156
153
# No clang support for now, so it's easiest to hardcode gcc.
157
154
'CC="ccache gcc" CXX="ccache g++" '
158
155
# Always log for ease of debugging. For real FB projects,
@@ -166,26 +163,28 @@ def debian_ccache_setup_steps(self):
166
163
#
167
164
# apt-get install sharutils
168
165
# 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
+ )
170
189
),
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
- )),
191
190
]
0 commit comments