Repository: nektos/act (language: go)

Issue:
Boolean inputs in reusable workflows are not proper booleans
### Bug report info

```plain text
act version:            0.2.61
GOOS:                   linux
GOARCH:                 amd64
NumCPU:                 16
Docker host:            DOCKER_HOST environment variable is not set
Sockets found:
        /var/run/docker.sock
Config files:
Build info:
        Go version:            go1.20.14
        Module path:           github.com/nektos/act
        Main version:          (devel)
        Main path:             github.com/nektos/act
        Main checksum:
        Build settings:
                -buildmode:           exe
                -compiler:            gc
                -trimpath:            true
                CGO_ENABLED:          0
                GOARCH:               amd64
                GOOS:                 linux
                GOAMD64:              v1
                vcs:                  git
                vcs.revision:         e8856f0fb00fcdd16eef2325b845f55f5d346f51
                vcs.time:             2023-08-21T16:17:06Z
                vcs.modified:         true
Docker Engine:
        Engine version:        25.0.3
        Engine runtime:        runc
        Cgroup version:        1
        Cgroup driver:         cgroupfs
        Storage driver:        overlay2
        Registry URI:          https://index.docker.io/v1/
        OS:                    Docker Desktop
        OS type:               linux
        OS version:
        OS arch:               x86_64
        OS kernel:             5.15.146.1-microsoft-standard-WSL2
        OS CPU:                16
        OS memory:             32100 MB
        Security options:
                name=seccomp,profile=unconfined
```


### Command used with act

```sh
act -W .github/workflows/act-test-caller.yml
```


### Describe issue

In GitHub Actions, `boolean` type inputs inside a `workflow_call` are real booleans, and you can use them as such. When a workflow is called with those in Act, they are converted to strings when they shouldn't be.

The output from my example below will be `This should not run` because `false` gets cast to `'false'` which actually ends up being truthy.

### Link to GitHub repository

_No response_

### Workflow content

```yml
# Calling workflow:
---
on:
  workflow_dispatch:

jobs:
  test:
    uses: ./.github/workflows/act-test-called.yml

# Reusable workflow:
---
on:
  workflow_call:
    inputs:
      test:
        type: boolean
        default: false

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - if: ${{ !inputs.test }}
        run: |
          echo "This should run"
      
      - if: ${{ inputs.test }}
        run: |
          echo "This should not run"
```


### Relevant log output

```sh
[test/act-test-called.yml/test] ⭐ Run Main echo "This should not run"
[test/act-test-called.yml/test]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/1] user= workdir=
| This should not run
[test/act-test-called.yml/test]   ✅  Success - Main echo "This should not run"

# Relevant line from debug output
[test/act-test-called.yml/test] [DEBUG] evaluating expression '${{ !inputs.test }}'
[test/act-test-called.yml/test] [DEBUG] expression '${{ !inputs.test }}' evaluated to 'false'
[test/act-test-called.yml/test] [DEBUG] Skipping step 'echo "This should run"
' due to '${{ !inputs.test }}'
...
[test/act-test-called.yml/test] [DEBUG] evaluating expression '${{ inputs.test }}'
[test/act-test-called.yml/test] [DEBUG] expression '${{ inputs.test }}' evaluated to '%!t(string=false)'
[test/act-test-called.yml/test] ⭐ Run Main echo "This should not run"
```


### Additional information

_No response_


Discussion / hints:

Fix patch:
diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go
index 7fbecd6c537..b8a39f19143 100644
--- a/pkg/model/workflow.go
+++ b/pkg/model/workflow.go
@@ -116,10 +116,10 @@ func (w *Workflow) WorkflowDispatchConfig() *WorkflowDispatch {
 }
 
 type WorkflowCallInput struct {
-	Description string `yaml:"description"`
-	Required    bool   `yaml:"required"`
-	Default     string `yaml:"default"`
-	Type        string `yaml:"type"`
+	Description string    `yaml:"description"`
+	Required    bool      `yaml:"required"`
+	Default     yaml.Node `yaml:"default"`
+	Type        string    `yaml:"type"`
 }
 
 type WorkflowCallOutput struct {
diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go
index 2e3152b0993..dca35380d60 100644
--- a/pkg/runner/expression.go
+++ b/pkg/runner/expression.go
@@ -512,7 +512,7 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
 			for k, v := range config.Inputs {
 				value := nestedMapLookup(ghc.Event, "inputs", k)
 				if value == nil {
-					value = v.Default
+					v.Default.Decode(&value)
 				}
 				if v.Type == "boolean" {
 					inputs[k] = value == "true"
@@ -531,21 +531,24 @@ func setupWorkflowInputs(ctx context.Context, inputs *map[string]interface{}, rc
 
 		for name, input := range config.Inputs {
 			value := rc.caller.runContext.Run.Job().With[name]
+
 			if value != nil {
-				if str, ok := value.(string); ok {
+				node := yaml.Node{}
+				_ = node.Encode(value)
+				if rc.caller.runContext.ExprEval != nil {
 					// evaluate using the calling RunContext (outside)
-					value = rc.caller.runContext.ExprEval.Interpolate(ctx, str)
+					_ = rc.caller.runContext.ExprEval.EvaluateYamlNode(ctx, &node)
 				}
+				_ = node.Decode(&value)
 			}
 
 			if value == nil && config != nil && config.Inputs != nil {
-				value = input.Default
+				def := input.Default
 				if rc.ExprEval != nil {
-					if str, ok := value.(string); ok {
-						// evaluate using the called RunContext (inside)
-						value = rc.ExprEval.Interpolate(ctx, str)
-					}
+					// evaluate using the called RunContext (inside)
+					_ = rc.ExprEval.EvaluateYamlNode(ctx, &def)
 				}
+				_ = def.Decode(&value)
 			}
 
 			(*inputs)[name] = value


Test patch:
diff --git a/pkg/runner/testdata/.github/workflows/local-reusable-workflow.yml b/pkg/runner/testdata/.github/workflows/local-reusable-workflow.yml
index d32dc5b8ea4..2befe5f35f6 100644
--- a/pkg/runner/testdata/.github/workflows/local-reusable-workflow.yml
+++ b/pkg/runner/testdata/.github/workflows/local-reusable-workflow.yml
@@ -45,23 +45,23 @@ jobs:
 
     - name: test required bool
       run: |
-        echo inputs.bool_required=${{ inputs.bool_required }}
-        [[ "${{ inputs.bool_required }}" = "true" ]] || exit 1
+        echo inputs.bool_required=${{ tojson(inputs.bool_required) }}
+        [[ "${{ tojson(inputs.bool_required) }}" = "true" ]] || exit 1
 
     - name: test optional bool
       run: |
-        echo inputs.bool_optional=${{ inputs.bool_optional }}
-        [[ "${{ inputs.bool_optional }}" = "true" ]] || exit 1
+        echo inputs.bool_optional=${{ tojson(inputs.bool_optional) }}
+        [[ "${{ tojson(inputs.bool_optional) }}" = "true" ]] || exit 1
 
     - name: test required number
       run: |
-        echo inputs.number_required=${{ inputs.number_required }}
-        [[ "${{ inputs.number_required == 1 }}" = "true" ]] || exit 1
+        echo inputs.number_required=${{ tojson(inputs.number_required) }}
+        [[ "${{ tojson(inputs.number_required) == '1' }}" = "true" ]] || exit 1
 
     - name: test optional number
       run: |
-        echo inputs.number_optional=${{ inputs.number_optional }}
-        [[ "${{ inputs.number_optional == 1 }}" = "true" ]] || exit 1
+        echo inputs.number_optional=${{ tojson(inputs.number_optional) }}
+        [[ "${{ tojson(inputs.number_optional) == '1' }}" = "true" ]] || exit 1
 
     - name: test secret
       run: |