skaffold icon indicating copy to clipboard operation
skaffold copied to clipboard

skaffold pre-build hook can't create input

Open kjurka opened this issue 2 years ago • 6 comments

Expected behavior

My understanding of the before-build hook was that it should be able to create the inputs used for the build.

Actual behavior

Dependency checking happens before the before-build hook is run and fails as it can't find the data that hasn't been created yet.

Information

  • skaffold v1.35.2
  • Operating system: Ubuntu 18.04
  • Contents of skaffold.yaml:
apiVersion: skaffold/v2beta22
kind: Config
build:
  artifacts:
  - image: makedataimage
    hooks:
      before:
      - command: ["./makedata.sh"]

makedata.sh

#!/bin/bash

echo "XX" > data

Dockerfile

FROM busybox

COPY ./data .

Steps to reproduce the behavior

skaffold build

Generating tags...
 - makedataimage -> makedataimage:latest
Some taggers failed. Rerun with -vdebug for errors.
Checking cache...
 - makedataimage: Error checking cache.
getting hash for artifact "makedataimage": getting dependencies for "makedataimage": file pattern [./data] must match at least one file

kjurka avatar Mar 22 '22 16:03 kjurka

aah. The current design does not support the use case you are using. This looks like a legit case where a pre-hook generates files needed in the build.

tejal29 avatar Mar 22 '22 20:03 tejal29

OK, that's kind of odd because the design doc explicitly states copying in a file (same as generating it) as a use case. https://github.com/GoogleContainerTools/skaffold/blob/main/docs/design_proposals/lifecycle-hooks.md

I guess I'm not sure what you can do with a before build hook then as you can't rely on it to modify the inputs to the docker container. If the cache check happens without running the before build hook, and then you modify the contents in the before-build hook, you won't have checked the cache correctly...

kjurka avatar Mar 22 '22 22:03 kjurka

Ran into the same problem when trying to use a custom builder:

apiVersion: skaffold/v2beta27
kind: Config
build:
  artifacts:
  - image: my-quarkus-project
    custom: 
      buildCommand: ./skaffold_build.sh --profile dev
      dependencies:
        paths:
          - target/classes/**/*
          - skaffold_build.sh
          - skaffold_dev_rebuild_trigger.txt
        ignore:
          - .git/index.lock
    hooks:
      before:
        - command: [ "./bin/skaffold_dev.sh" ]
    #local files synced to pods instead of triggering an image build when modified. If no files are listed, sync all the files and infer the destination.
    sync:
      manual: 	#manual sync rules indicating the source and destination.
        - src: 'target/classes/**/*' 	# a glob pattern to match local paths against. Directories should be delimited by / on all platforms.
          dest: 'dev/app' 	#destination path in the container where the files should be synced to.
          strip: 'target/classes/'

The command ./bin/skaffold_dev.sh in the before-build hook is expected to create target/classes/**/* listed in the dependencies (among other things).

However, running skaffold dev will not run the before-build hook because the dependencies are validated before the before-build hook gets a chance to execute:

Listing files to watch...
 - my-quarkus-project
listing files: pattern "target/classes/**/*" did not match any file

The before-build hook does run if I create a dummy directory and file first:

mkdir -p target/classes/dummy
touch target/classes/dummy/dummy.txt

So, as a workaround for now, I need to figure out how to set a .gitignore for the build output directory that ignores everything but target/classes/dummy/dummy.txt to avoid needing to document the extra steps for the dummy file (or a needless wrapper script for skaffold dev that does the same).

Oh, and yes, also need to figure out how to recreate the dummy directory and file after the user runs ./mvnw clean.

joes avatar May 13 '22 07:05 joes

Scrap everything I said, having the empty file in place initially does not help in my case. This will only lead to an endless rebuild loop in skaffold dev for some reason. Possibly due to how the manual sync and dependencies interact with the pre build hook.

Possibly the skaffold dev computes the initial state using whatever was in target/classes/**/* before the before-build hook was run. When the before-build hook is then run the classes are actually created but this then perhaps leads to a rebuild due to changes being detected (first only target/classes/dummy/dummy.txt -> more classes after before-build) and somehow this leads to an infinite rebuild loop.

Maybe if I can restrict the pre-build from running only once for the very first build...

joes avatar May 13 '22 08:05 joes

Scrap everything I said, having the empty file in place initially does not help in my case. This will only lead to an endless rebuild loop in skaffold dev for some reason. Possibly due to how the manual sync and dependencies interact with the pre build hook.

Possibly the skaffold dev computes the initial state using whatever was in target/classes/**/* before the before-build hook was run. When the before-build hook is then run the classes are actually created but this then perhaps leads to a rebuild due to changes being detected (first only target/classes/dummy/dummy.txt -> more classes after before-build) and somehow this leads to an infinite rebuild loop.

Maybe if I can restrict the pre-build from running only once for the very first build...

Scrap the above...

I am back to the initial conclusion, having the empty directory with the dummy file actually does actually work out. There was simply an error in the before-build hook that was causing the endless loop.

joes avatar May 13 '22 08:05 joes

This also left me stumped. I thought that before calculating any dependencies it would run the pre-build hooks. Apparently that was wrong. The only real solution right now seems to use a custom build command that does this.

Blackclaws avatar Aug 25 '22 10:08 Blackclaws

I agree that the pre-built hook, as the name implies, should be executed before any steps (including the dependencies calculation) otherwise they have very small usability. We also have to create empty folders/files or use custom builder for quite regular normal docker build which kind of defeats the purpose of having those hooks

GolubevV avatar Jan 28 '23 12:01 GolubevV