skaffold
skaffold copied to clipboard
skaffold pre-build hook can't create input
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
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.
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...
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
.
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 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 intarget/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.
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.
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