Add hint of progress to the output of `docker build`
| ... | ... |
@@ -233,6 +233,7 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri |
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
var shortImgID string |
| 236 |
+ total := len(b.dockerfile.Children) |
|
| 236 | 237 |
for i, n := range b.dockerfile.Children {
|
| 237 | 238 |
select {
|
| 238 | 239 |
case <-b.clientCtx.Done(): |
| ... | ... |
@@ -242,7 +243,7 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri |
| 242 | 242 |
default: |
| 243 | 243 |
// Not cancelled yet, keep going... |
| 244 | 244 |
} |
| 245 |
- if err := b.dispatch(i, n); err != nil {
|
|
| 245 |
+ if err := b.dispatch(i, total, n); err != nil {
|
|
| 246 | 246 |
if b.options.ForceRemove {
|
| 247 | 247 |
b.clearTmp() |
| 248 | 248 |
} |
| ... | ... |
@@ -320,8 +321,9 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con |
| 320 | 320 |
b.Stderr = ioutil.Discard |
| 321 | 321 |
b.disableCommit = true |
| 322 | 322 |
|
| 323 |
+ total := len(ast.Children) |
|
| 323 | 324 |
for i, n := range ast.Children {
|
| 324 |
- if err := b.dispatch(i, n); err != nil {
|
|
| 325 |
+ if err := b.dispatch(i, total, n); err != nil {
|
|
| 325 | 326 |
return nil, err |
| 326 | 327 |
} |
| 327 | 328 |
} |
| ... | ... |
@@ -93,7 +93,7 @@ func init() {
|
| 93 | 93 |
// such as `RUN` in ONBUILD RUN foo. There is special case logic in here to |
| 94 | 94 |
// deal with that, at least until it becomes more of a general concern with new |
| 95 | 95 |
// features. |
| 96 |
-func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
|
|
| 96 |
+func (b *Builder) dispatch(stepN int, stepTotal int, ast *parser.Node) error {
|
|
| 97 | 97 |
cmd := ast.Value |
| 98 | 98 |
upperCasedCmd := strings.ToUpper(cmd) |
| 99 | 99 |
|
| ... | ... |
@@ -107,7 +107,7 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
|
| 107 | 107 |
original := ast.Original |
| 108 | 108 |
flags := ast.Flags |
| 109 | 109 |
strList := []string{}
|
| 110 |
- msg := fmt.Sprintf("Step %d : %s", stepN+1, upperCasedCmd)
|
|
| 110 |
+ msg := fmt.Sprintf("Step %d/%d : %s", stepN+1, stepTotal, upperCasedCmd)
|
|
| 111 | 111 |
|
| 112 | 112 |
if len(ast.Flags) > 0 {
|
| 113 | 113 |
msg += " " + strings.Join(ast.Flags, " ") |
| ... | ... |
@@ -184,7 +184,7 @@ func executeTestCase(t *testing.T, testCase dispatchTestCase) {
|
| 184 | 184 |
|
| 185 | 185 |
b := &Builder{runConfig: config, options: options, Stdout: ioutil.Discard, context: context}
|
| 186 | 186 |
|
| 187 |
- err = b.dispatch(0, n.Children[0]) |
|
| 187 |
+ err = b.dispatch(0, len(n.Children), n.Children[0]) |
|
| 188 | 188 |
|
| 189 | 189 |
if err == nil {
|
| 190 | 190 |
t.Fatalf("No error when executing test %s", testCase.name)
|
| ... | ... |
@@ -434,6 +434,7 @@ func (b *Builder) processImageFrom(img builder.Image) error {
|
| 434 | 434 |
return err |
| 435 | 435 |
} |
| 436 | 436 |
|
| 437 |
+ total := len(ast.Children) |
|
| 437 | 438 |
for i, n := range ast.Children {
|
| 438 | 439 |
switch strings.ToUpper(n.Value) {
|
| 439 | 440 |
case "ONBUILD": |
| ... | ... |
@@ -442,7 +443,7 @@ func (b *Builder) processImageFrom(img builder.Image) error {
|
| 442 | 442 |
return fmt.Errorf("%s isn't allowed as an ONBUILD trigger", n.Value)
|
| 443 | 443 |
} |
| 444 | 444 |
|
| 445 |
- if err := b.dispatch(i, n); err != nil {
|
|
| 445 |
+ if err := b.dispatch(i, total, n); err != nil {
|
|
| 446 | 446 |
return err |
| 447 | 447 |
} |
| 448 | 448 |
} |
| ... | ... |
@@ -5417,7 +5417,7 @@ func (s *DockerSuite) TestBuildNoDupOutput(c *check.C) {
|
| 5417 | 5417 |
c.Fatalf("Build should have worked: %q", err)
|
| 5418 | 5418 |
} |
| 5419 | 5419 |
|
| 5420 |
- exp := "\nStep 2 : RUN env\n" |
|
| 5420 |
+ exp := "\nStep 2/2 : RUN env\n" |
|
| 5421 | 5421 |
if !strings.Contains(out, exp) {
|
| 5422 | 5422 |
c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
|
| 5423 | 5423 |
} |
| ... | ... |
@@ -5434,7 +5434,7 @@ func (s *DockerSuite) TestBuildStartsFromOne(c *check.C) {
|
| 5434 | 5434 |
c.Fatalf("Build should have worked: %q", err)
|
| 5435 | 5435 |
} |
| 5436 | 5436 |
|
| 5437 |
- exp := "\nStep 1 : FROM busybox\n" |
|
| 5437 |
+ exp := "\nStep 1/1 : FROM busybox\n" |
|
| 5438 | 5438 |
if !strings.Contains(out, exp) {
|
| 5439 | 5439 |
c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
|
| 5440 | 5440 |
} |
| ... | ... |
@@ -6981,3 +6981,16 @@ func (s *DockerSuite) TestBuildCmdShellArgsEscaped(c *check.C) {
|
| 6981 | 6981 |
c.Fatalf("CMD was not escaped Config.Cmd: got %v", res)
|
| 6982 | 6982 |
} |
| 6983 | 6983 |
} |
| 6984 |
+ |
|
| 6985 |
+// Test case for #24912. |
|
| 6986 |
+func (s *DockerSuite) TestBuildStepsWithProgress(c *check.C) {
|
|
| 6987 |
+ name := "testbuildstepswithprogress" |
|
| 6988 |
+ |
|
| 6989 |
+ totalRun := 5 |
|
| 6990 |
+ _, out, err := buildImageWithOut(name, "FROM busybox\n"+strings.Repeat("RUN echo foo\n", totalRun), true)
|
|
| 6991 |
+ c.Assert(err, checker.IsNil) |
|
| 6992 |
+ c.Assert(out, checker.Contains, fmt.Sprintf("Step 1/%d : FROM busybox", 1+totalRun))
|
|
| 6993 |
+ for i := 2; i <= 1+totalRun; i++ {
|
|
| 6994 |
+ c.Assert(out, checker.Contains, fmt.Sprintf("Step %d/%d : RUN echo foo", i, 1+totalRun))
|
|
| 6995 |
+ } |
|
| 6996 |
+} |