Skip to content

Inputs are wrong in post step when action is called through a nested composite action #442

@iaingalloway

Description

@iaingalloway

Description

When devcontainers/ci is called from within a composite action, images are built correctly but pushed under the wrong tags (or not at all). The push happens in the post step at main.ts#L255, which re-reads inputs via core.getInput('imageTag') and core.getInput('imageName'). At post time, those calls return incorrect values.

Root cause

This is a known GHA runner bug: when a node action with a post step is called through a composite action, the runner restores the wrong INPUT_* environment for the post step. Instead of the values the action itself received, it receives the input values of the nearest ancestor composite action.

  • actions/runner#3514 - Wrong environment passed to node post when called by composite called by composite action
  • actions/runner#2030 - Composite: Nested actions post steps have the wrong context

To reproduce

You can view an MVCE demonstrating this issue at: https://github.com/iaingalloway/devcontainers-ci-inputs-mcve

You can see an affected workflow run:

You can view an MCVE of the underlying issue in actions/runner at: https://github.com/iainlane/composite-action-inputs-mvce

Call devcontainers/ci from a composite action that itself receives imageName/imageTag as inputs:

.github/workflows/repro.yml:

name: Post hook sees wrong input

on:
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd

      - name: Log in to registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Call outer composite
        uses: ./.github/actions/outer-composite

.github/actions/outer-composite/action.yml:

# Outer composite action
name: Outer composite
description: Sets the value to bar and calls the inner composite

runs:
  using: composite
  steps:
    - name: Call inner composite
      uses: ./.github/actions/inner-composite
      with:
        image-tag: foo

.github/actions/inner-composite/action.yml:

name: Inner composite
description: Passes a value to the devcontainers/ci action
inputs:
  image-tag:
    description: Image tag to build and push
    required: true

runs:
  using: composite
  steps:
    - name: Build and push devcontainer image
      uses: devcontainers/ci@b63b30de439b47a52267f241112c5b453b673db5
      with:
        imageName: ghcr.io/${{ github.repository }}/devcontainer
        imageTag: ${{ inputs.image-tag }}
        push: always
        subFolder: src

./src/devcontainer.json:

{
  "image": "mcr.microsoft.com/devcontainers/base@sha256:e389149057371298eaeb72e736fc2c4dcb79974de222dd471d2e6d675d2f61c4"
}

Observed: post step attempts to push latest (by default, because INPUT_IMAGETAG is not set in the post context).

Expected: post step should push foo.

Workaround (for maintainers)

The fix used by github/codeql-action (codeql-action#2557) is to persist inputs in main using saveState, then read them back from STATE_* in the post step:

In main:

core.saveState('imageName', imageName);
core.saveState('imageTag', imageTag);
core.saveState('push', push);
core.saveState('platform', platform);

In post, replace core.getInput('imageName') / core.getInput('imageTag') / core.getInput('push') / core.getInput('platform') with:

core.getState('push')
core.getState('imageName')
core.getState('imageTag')
core.getState('platform')

This sidesteps the runner bug entirely since state is stored in STATE_* env vars which are not subject to the same mis-evaluation.

Happy to submit a PR with this change if it would be helpful!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions