From d9632bf8b4b6ffe04f5a79134717835f7b8841bb Mon Sep 17 00:00:00 2001 From: eliran-mic Date: Thu, 30 Apr 2026 21:45:01 +0300 Subject: [PATCH] Fix input contract: user-provided context/dockerfile override service_name resolution The resolve step always emitted resolved_context=code (even with no service_name or as a safety-net on early exit), which made the build step's `steps.skyhook_config.outputs.resolved_context || inputs.context` chain ignore inputs.context entirely. Changes: - Drop default values from `context` and `dockerfile` inputs so empty means "not provided" (defaults still effective via build-step fallback). - Gate the resolve step on service_name being set AND at least one of context/dockerfile being unset. - Only emit resolved_context/resolved_dockerfile when actually resolved from skyhook.yaml (no `code` safety-net on early exit). - Flip build step precedence to `inputs.X || resolved_X || default` so user-provided inputs win over service_name-derived values. - Update step summary to reflect the same precedence and tag the source. Co-Authored-By: Claude Opus 4.7 (1M context) --- action.yml | 85 +++++++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/action.yml b/action.yml index c7c75a1..2741e4b 100644 --- a/action.yml +++ b/action.yml @@ -43,13 +43,11 @@ inputs: # Build inputs (pass-through to docker/build-push-action) context: - description: 'Build context' + description: 'Build context. If set, overrides any value derived from service_name. Defaults to "." when neither is provided.' required: false - default: '.' dockerfile: - description: 'Path to Dockerfile (relative to context or absolute)' + description: 'Path to Dockerfile (relative to context or absolute). If set, overrides any value derived from service_name. Defaults to "Dockerfile" when neither is provided.' required: false - default: 'Dockerfile' platforms: description: 'Comma-separated platforms' required: false @@ -196,74 +194,59 @@ runs: - name: Resolve build config from .skyhook/skyhook.yaml id: skyhook_config + if: ${{ inputs.service_name != '' && (inputs.context == '' || inputs.dockerfile == '') }} shell: bash working-directory: code run: | set -euo pipefail - # Use the input if it exists; - if [[ -n "${{ inputs.service_name }}" ]]; then - SERVICE_NAME="${{ inputs.service_name }}" - fi + SERVICE_NAME="${{ inputs.service_name }}" - # If no service_name provided, skip config resolution - if [[ -z "$SERVICE_NAME" ]]; then - echo "No service_name provided, skipping config resolution" - echo "resolved_context=code" >> "$GITHUB_OUTPUT" - exit 0 - fi - # Find the config file - CONFIG_FILE="" - if [[ -f ".skyhook/skyhook.yaml" ]]; then - CONFIG_FILE=".skyhook/skyhook.yaml" - fi - - if [[ -z "$CONFIG_FILE" ]]; then + if [[ ! -f ".skyhook/skyhook.yaml" ]]; then echo "::warning::service_name '$SERVICE_NAME' provided but .skyhook/skyhook.yaml not found. Falling back to input parameters." - echo "resolved_context=code" >> "$GITHUB_OUTPUT" exit 0 fi - + CONFIG_FILE=".skyhook/skyhook.yaml" echo "Found config file: $CONFIG_FILE" # Check if service exists SERVICE_EXISTS=$(yq ".services[] | select(.name == \"$SERVICE_NAME\") | .name" "$CONFIG_FILE") if [[ -z "$SERVICE_EXISTS" ]]; then echo "::warning::Service '$SERVICE_NAME' not found in $CONFIG_FILE. Falling back to input parameters." - echo "resolved_context=code" >> "$GITHUB_OUTPUT" exit 0 fi echo "Found service '$SERVICE_NAME' in config" # Extract build config using yq - # Context: only use buildTool.docker.contextPath if explicitly set, otherwise empty (defaults to repo root) CONTEXT_PATH=$(yq ".services[] | select(.name == \"$SERVICE_NAME\") | .buildTool.docker.contextPath // \"\"" "$CONFIG_FILE") DOCKERFILE_PATH=$(yq ".services[] | select(.name == \"$SERVICE_NAME\") | .buildTool.docker.dockerfilePath // \"\"" "$CONFIG_FILE") - # Normalize outputs to repo root (this step runs in working-directory: code) + # Paths in skyhook.yaml are relative to repo root; this step runs in working-directory: code REPO_PREFIX="code" - # Context: if contextPath is set use code/{contextPath}, else use code - if [[ -n "$CONTEXT_PATH" ]]; then - RESOLVED_CONTEXT="$REPO_PREFIX/$CONTEXT_PATH" - - # If dockerfile is not set, default to {context}/Dockerfile - if [[ -z "$DOCKERFILE_PATH" ]]; then - DOCKERFILE_PATH="${CONTEXT_PATH}/Dockerfile" - echo "Defaulting dockerfile to: $REPO_PREFIX/$DOCKERFILE_PATH" + # Only emit resolved_context if user did not provide inputs.context + if [[ -z "${{ inputs.context }}" ]]; then + if [[ -n "$CONTEXT_PATH" ]]; then + RESOLVED_CONTEXT="$REPO_PREFIX/$CONTEXT_PATH" + else + RESOLVED_CONTEXT="$REPO_PREFIX" fi - else - RESOLVED_CONTEXT="$REPO_PREFIX" + echo "Using context from config: $RESOLVED_CONTEXT" + echo "resolved_context=$RESOLVED_CONTEXT" >> "$GITHUB_OUTPUT" fi - echo "Using context: $RESOLVED_CONTEXT" - echo "resolved_context=$RESOLVED_CONTEXT" >> "$GITHUB_OUTPUT" - if [[ -n "$DOCKERFILE_PATH" ]]; then - FULL_DOCKERFILE_PATH="$REPO_PREFIX/$DOCKERFILE_PATH" - echo "Using dockerfile from config: $FULL_DOCKERFILE_PATH" - echo "resolved_dockerfile=$FULL_DOCKERFILE_PATH" >> "$GITHUB_OUTPUT" + # Only emit resolved_dockerfile if user did not provide inputs.dockerfile + if [[ -z "${{ inputs.dockerfile }}" ]]; then + if [[ -z "$DOCKERFILE_PATH" && -n "$CONTEXT_PATH" ]]; then + DOCKERFILE_PATH="${CONTEXT_PATH}/Dockerfile" + fi + if [[ -n "$DOCKERFILE_PATH" ]]; then + FULL_DOCKERFILE_PATH="$REPO_PREFIX/$DOCKERFILE_PATH" + echo "Using dockerfile from config: $FULL_DOCKERFILE_PATH" + echo "resolved_dockerfile=$FULL_DOCKERFILE_PATH" >> "$GITHUB_OUTPUT" + fi fi echo "config_file=$CONFIG_FILE" >> "$GITHUB_OUTPUT" @@ -362,8 +345,8 @@ runs: id: build uses: docker/build-push-action@v6 with: - context: ${{ steps.skyhook_config.outputs.resolved_context || inputs.context }} - file: ${{ steps.skyhook_config.outputs.resolved_dockerfile || inputs.dockerfile }} + context: ${{ inputs.context || steps.skyhook_config.outputs.resolved_context || '.' }} + file: ${{ inputs.dockerfile || steps.skyhook_config.outputs.resolved_dockerfile || 'Dockerfile' }} platforms: ${{ inputs.platforms }} build-args: ${{ inputs.build_args }} labels: ${{ steps.meta.outputs.labels }} @@ -414,9 +397,9 @@ runs: fi echo "### ⚙️ Build Configuration" >> $GITHUB_STEP_SUMMARY - # Determine effective values and sources - EFFECTIVE_CONTEXT="${{ steps.skyhook_config.outputs.resolved_context || inputs.context }}" - EFFECTIVE_DOCKERFILE="${{ steps.skyhook_config.outputs.resolved_dockerfile || inputs.dockerfile }}" + # Determine effective values and sources (input wins over config, fallback to default) + EFFECTIVE_CONTEXT="${{ inputs.context || steps.skyhook_config.outputs.resolved_context || '.' }}" + EFFECTIVE_DOCKERFILE="${{ inputs.dockerfile || steps.skyhook_config.outputs.resolved_dockerfile || 'Dockerfile' }}" if [[ -n "${{ steps.skyhook_config.outputs.config_file }}" ]]; then echo "> 📄 Config source: \`${{ steps.skyhook_config.outputs.config_file }}\` (service: \`${{ steps.skyhook_config.outputs.service_name }}\`)" >> $GITHUB_STEP_SUMMARY @@ -424,12 +407,16 @@ runs: fi CONTEXT_SOURCE="" - if [[ -n "${{ steps.skyhook_config.outputs.resolved_context }}" ]]; then + if [[ -n "${{ inputs.context }}" ]]; then + CONTEXT_SOURCE=" _(from input)_" + elif [[ -n "${{ steps.skyhook_config.outputs.resolved_context }}" ]]; then CONTEXT_SOURCE=" _(from config)_" fi DOCKERFILE_SOURCE="" - if [[ -n "${{ steps.skyhook_config.outputs.resolved_dockerfile }}" ]]; then + if [[ -n "${{ inputs.dockerfile }}" ]]; then + DOCKERFILE_SOURCE=" _(from input)_" + elif [[ -n "${{ steps.skyhook_config.outputs.resolved_dockerfile }}" ]]; then DOCKERFILE_SOURCE=" _(from config)_" fi