act icon indicating copy to clipboard operation
act copied to clipboard

Issue accessing outputs of a skipped job - works on GH CI

Open mgoerens opened this issue 5 months ago • 0 comments

Bug report info

act version:            0.2.67
GOOS:                   linux
GOARCH:                 amd64
NumCPU:                 12
Docker host:            DOCKER_HOST environment variable is not set
Sockets found:
	/var/run/docker.sock
Config files:           
	/home/mgoerens/.actrc:
		-P ubuntu-latest=catthehacker/ubuntu:act-latest
		-P ubuntu-22.04=catthehacker/ubuntu:act-22.04
		-P ubuntu-20.04=catthehacker/ubuntu:act-20.04
		-P ubuntu-18.04=catthehacker/ubuntu:act-18.04
Build info:
	Go version:            go1.21.13
	Module path:           github.com/nektos/act
	Main version:          (devel)
	Main path:             github.com/nektos/act
	Main checksum:         
	Build settings:
		-buildmode:           exe
		-compiler:            gc
		-ldflags:             -s -w -X main.version=0.2.67 -X main.commit=f75a2d8b38cc3b929ab652c0994d6d33f6584ed9 -X main.date=2024-09-10T18:17:24Z -X main.builtBy=goreleaser
		CGO_ENABLED:          0
		GOARCH:               amd64
		GOOS:                 linux
		GOAMD64:              v1
		vcs:                  git
		vcs.revision:         f75a2d8b38cc3b929ab652c0994d6d33f6584ed9
		vcs.time:             2024-09-10T18:17:07Z
		vcs.modified:         false
Docker Engine:
	Engine version:        24.0.5
	Engine runtime:        runc
	Cgroup version:        2
	Cgroup driver:         systemd
	Storage driver:        btrfs
	Registry URI:          https://index.docker.io/v1/
	OS:                    Fedora Linux 40 (Workstation Edition)
	OS type:               linux
	OS version:            40
	OS arch:               x86_64
	OS kernel:             6.10.9-200.fc40.x86_64
	OS CPU:                12
	OS memory:             31844 MB
	Security options:
		name=seccomp,profile=builtin
		name=selinux
		name=cgroupns

Command used with act

act push

Describe issue

Tested on GitHub CI, works as expected, but not locally using latest act.

I have configured three jobs that runs sequentially. The third (and last) job always run, but requires outputs from the second job. I want to configure default values in case the second job is skipped due to an error in the first job.

See the workflow file.

I expect following output in job three (and that's what I get in GitHub CI):

Second job result: skipped
Step outcome: skipped
Step output: default value

Instead the result of job two is empty, and the outputs from the job two (that is skipped due to the first one failing) are weirdly evaluated to a non empty string and bash complains of a bad substitution (see relevant log output)

Link to GitHub repository

No response

Workflow content

name: whatever
on: ['push']

jobs:
  one:
    name: "First"
    runs-on: ubuntu-22.04

    steps:
      - run: exit 1 # Fail first job

  
  two:
    name: "Second"
    runs-on: ubuntu-22.04
    needs: [one] # Second job is skipped

    outputs:
      step-outcome: ${{ steps.two-step.outcome }}
      step-output: ${{ steps.two-step.outputs.two-step }}

    steps:
      - id: two-step
        run: echo "two-step=Test-output" | tee -a $GITHUB_OUTPUT

  three:
    name: "Third"
    runs-on: ubuntu-22.04
    needs: [two, one]
  
    if: ${{ always() }}

    steps:
      - run: |
          # job result is empty, should be "skipped"
          echo "Second job result: " ${{ needs.two.result }}
          # Printing the step outcome fails, even when using default (using && true to continue to next command)
          echo "Step outcome: " ${{ needs.two.outputs.step-outcome || 'skipped' }} && true
          # Printing the step output also fails, even when using default
          echo "Step output: " ${{ needs.two.outputs.step-output || 'default value' }}

Relevant log output

[CI/Third ] [DEBUG] expression '# job result is empty, should be "skipped"
echo "Second job result: " ${{ needs.two.result }}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " ${{ needs.two.outputs.step-outcome || 'skipped' }} && true
# Printing the step output also fails, even when using default
echo "Step output: " ${{ needs.two.outputs.step-output || 'default value' }}
' rewritten to 'format('# job result is empty, should be "skipped"
echo "Second job result: " {0}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " {1} && true
# Printing the step output also fails, even when using default
echo "Step output: " {2}
', needs.two.result, needs.two.outputs.step-outcome || 'skipped', needs.two.outputs.step-output || 'default value')'
[CI/Third ] [DEBUG] evaluating expression 'format('# job result is empty, should be "skipped"
echo "Second job result: " {0}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " {1} && true
# Printing the step output also fails, even when using default
echo "Step output: " {2}
', needs.two.result, needs.two.outputs.step-outcome || 'skipped', needs.two.outputs.step-output || 'default value')'
[CI/Third ] [DEBUG] expression 'format('# job result is empty, should be "skipped"
echo "Second job result: " {0}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " {1} && true
# Printing the step output also fails, even when using default
echo "Step output: " {2}
', needs.two.result, needs.two.outputs.step-outcome || 'skipped', needs.two.outputs.step-output || 'default value')' evaluated to '%!t(string=# job result is empty, should be "skipped"
echo "Second job result: " skipped
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " ${{ steps.two-step.outcome }} && true
# Printing the step output also fails, even when using default
echo "Step output: " ${{ steps.two-step.outputs.two-step }}
)'
[CI/Third ] [DEBUG] Wrote command 

# job result is empty, should be "skipped"
echo "Second job result: " skipped
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " ${{ steps.two-step.outcome }} && true
# Printing the step output also fails, even when using default
echo "Step output: " ${{ steps.two-step.outputs.two-step }}


 to 'workflow/0'
[CI/Third ] [DEBUG] Writing entry to tarball workflow/0 len:366
[CI/Third ] [DEBUG] Extracting content to '/var/run/act'
[CI/Third ]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/0] user= workdir=
[CI/Third ] [DEBUG] Exec command '[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/0]'
[CI/Third ] [DEBUG] Working directory '/home/mgoerens/dev/github.com/mgoerens/development'
| Second job result:  skipped
| /var/run/act/workflow/0: line 5: ${{ steps.two-step.outcome }}: bad substitution
[CI/Third ]   ❌  Failure - Main # job result is empty, should be "skipped"
echo "Second job result: " skipped
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " ${{ steps.two-step.outcome }} && true
# Printing the step output also fails, even when using default
echo "Step output: " ${{ steps.two-step.outputs.two-step }}
[CI/Third ] exitcode '1': failure
[CI/Third ] [DEBUG] expression '# job result is empty, should be "skipped"
echo "Second job result: " ${{ needs.two.result }}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " ${{ needs.two.outputs.step-outcome || 'skipped' }} && true
# Printing the step output also fails, even when using default
echo "Step output: " ${{ needs.two.outputs.step-output || 'default value' }}
' rewritten to 'format('# job result is empty, should be "skipped"
echo "Second job result: " {0}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " {1} && true
# Printing the step output also fails, even when using default
echo "Step output: " {2}
', needs.two.result, needs.two.outputs.step-outcome || 'skipped', needs.two.outputs.step-output || 'default value')'
[CI/Third ] [DEBUG] evaluating expression 'format('# job result is empty, should be "skipped"
echo "Second job result: " {0}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " {1} && true
# Printing the step output also fails, even when using default
echo "Step output: " {2}
', needs.two.result, needs.two.outputs.step-outcome || 'skipped', needs.two.outputs.step-output || 'default value')'
[CI/Third ] [DEBUG] expression 'format('# job result is empty, should be "skipped"
echo "Second job result: " {0}
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " {1} && true
# Printing the step output also fails, even when using default
echo "Step output: " {2}
', needs.two.result, needs.two.outputs.step-outcome || 'skipped', needs.two.outputs.step-output || 'default value')' evaluated to '%!t(string=# job result is empty, should be "skipped"
echo "Second job result: " skipped
# Printing the step outcome fails, even when using default (using && true to continue to next command)
echo "Step outcome: " ${{ steps.two-step.outcome }} && true
# Printing the step output also fails, even when using default
echo "Step output: " ${{ steps.two-step.outputs.two-step }}
)'
[CI/Third ] 🏁  Job failed
[CI/Third ] [DEBUG] Loading revision from git directory
[CI/Third ] [DEBUG] Found revision: 278e8683b8c8fdefa42999cefccee8a11817f96c
[CI/Third ] [DEBUG] HEAD points to '278e8683b8c8fdefa42999cefccee8a11817f96c'
[CI/Third ] [DEBUG] using github ref: refs/heads/main
[CI/Third ] [DEBUG] Found revision: 278e8683b8c8fdefa42999cefccee8a11817f96c

Additional information

No response

mgoerens avatar Sep 20 '24 16:09 mgoerens