From ae50e2ee7b301a5fd1a124d4f60818a9e049a74d Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 24 Feb 2026 20:33:07 -0800 Subject: [PATCH 01/18] feat: cli --- .github/workflows/integration.yml | 11 +++ .github/workflows/publish.yml | 4 +- action.yml | 137 +++++++++++++++++++++++++++++- 3 files changed, 148 insertions(+), 4 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 6df1377c..96919bc2 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -248,6 +248,17 @@ jobs: env: PAYLOAD_FILE_OUTPUT_TIME: ${{ steps.payload_file.outputs.time }} + - name: "integration(cli): run a slack cli version check" + id: cli-version + uses: ./ + with: + command: "version" + + - name: "integration(cli): confirm the cli command succeeded" + run: test "$CLI_OK" = "true" + env: + CLI_OK: ${{ steps.cli-version.outputs.ok }} + - name: "chore(health): check up on recent changes to the health score" uses: slackapi/slack-health-score@d58a419f15cdaff97e9aa7f09f95772830ab66f7 # v0.1.1 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 63532b20..9a70b6c9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,7 +37,9 @@ jobs: id: tag uses: teunmooij/github-versioned-release@3edf649c6e5e5e976d43f2584b15bdc8b4c8f0df # v1.2.1 with: - template: javascript-action + template: composite-action + include: | + dist/**/* env: GITHUB_TOKEN: ${{ github.token }} diff --git a/action.yml b/action.yml index 39c8b499..a863b45e 100644 --- a/action.yml +++ b/action.yml @@ -1,10 +1,13 @@ name: "Slack: Send to Slack" author: "slackapi" -description: "Send data to Slack to start a Slack workflow in Workflow Builder, call a Slack API method, or post a message into a channel" +description: "Send data to Slack to start a Slack workflow in Workflow Builder, call a Slack API method, post a message into a channel, or run a Slack CLI command" inputs: api: description: "A custom API URL to send Slack API method requests to." required: false + command: + description: "A Slack CLI command to run without the 'slack' prefix." + required: false errors: default: "false" description: "If the step exits with an error on errors or continues." @@ -34,6 +37,9 @@ inputs: token: description: "The authentication value used with the Slack API." required: false + version: + description: "The version of the Slack CLI to install." + required: false webhook: description: "A location for posting request payloads." required: false @@ -43,16 +49,141 @@ inputs: outputs: ok: description: "If the request completed without returning errors." + value: ${{ steps.slack-send.outputs.ok || steps.slack-cli.outputs.ok }} response: description: "A JSON stringified version of the Slack API response." + value: ${{ steps.slack-send.outputs.response || steps.slack-cli.outputs.response }} time: description: "The Unix epoch time that the step completed." + value: ${{ steps.slack-send.outputs.time || steps.slack-cli.outputs.time }} channel_id: description: "The channel ID returned with some of the Slack API methods." + value: ${{ steps.slack-send.outputs.channel_id }} thread_ts: description: "The timestamp of a parent Slack message with threaded replies." + value: ${{ steps.slack-send.outputs.thread_ts }} ts: description: "The timestamp of a Slack message or event in the response." + value: ${{ steps.slack-send.outputs.ts }} runs: - using: "node20" - main: "dist/index.js" + using: composite + steps: + - name: Validate inputs + if: inputs.command != '' && (inputs.method != '' || inputs.webhook != '') + shell: bash + run: | + echo "::error::The 'command' input cannot be combined with 'method' or 'webhook' inputs." + exit 1 + + - name: Send data to Slack + id: slack-send + if: inputs.command == '' + shell: bash + run: node "${{ github.action_path }}/dist/index.js" + env: + INPUT_API: ${{ inputs.api }} + INPUT_ERRORS: ${{ inputs.errors }} + INPUT_METHOD: ${{ inputs.method }} + INPUT_PAYLOAD: ${{ inputs.payload }} + INPUT_PAYLOAD-DELIMITER: ${{ inputs.payload-delimiter }} + INPUT_PAYLOAD-FILE-PATH: ${{ inputs.payload-file-path }} + INPUT_PAYLOAD-TEMPLATED: ${{ inputs.payload-templated }} + INPUT_PROXY: ${{ inputs.proxy }} + INPUT_RETRIES: ${{ inputs.retries }} + INPUT_TOKEN: ${{ inputs.token }} + INPUT_WEBHOOK: ${{ inputs.webhook }} + INPUT_WEBHOOK-TYPE: ${{ inputs.webhook-type }} + + - name: Check if Slack CLI already exists + id: slack-cli-check + if: inputs.command != '' + shell: bash + run: | + if command -v slack &> /dev/null; then + echo "cli-exists=true" >> "$GITHUB_OUTPUT" + else + echo "cli-exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Cache Slack CLI + if: inputs.command != '' && steps.slack-cli-check.outputs.cli-exists != 'true' + id: cache-cli + uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + with: + path: | + ${{ runner.os == 'Windows' && format('{0}\AppData\Local\slack-cli', env.USERPROFILE) || format('{0}/.slack/bin', env.HOME) }} + key: slack-cli-${{ runner.os }}-${{ runner.arch }}-${{ inputs.version }} + + - name: Add Slack CLI to PATH (Linux/macOS) + if: inputs.command != '' && steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os != 'Windows' + shell: bash + run: echo "$HOME/.slack/bin" >> "$GITHUB_PATH" + + - name: Add Slack CLI to PATH (Windows) + if: inputs.command != '' && steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os == 'Windows' + shell: pwsh + run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\.slack\bin" + + - name: Install Slack CLI (Linux/macOS) + if: >- + inputs.command != '' && + steps.slack-cli-check.outputs.cli-exists != 'true' && + steps.cache-cli.outputs.cache-hit != 'true' && + runner.os != 'Windows' + shell: bash + run: | + if [ -n "$SLACK_CLI_VERSION" ]; then + curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s -- -v "$SLACK_CLI_VERSION" + else + curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s + fi + env: + SLACK_CLI_VERSION: ${{ inputs.version }} + + - name: Install Slack CLI (Windows) + if: >- + inputs.command != '' && + steps.slack-cli-check.outputs.cli-exists != 'true' && + steps.cache-cli.outputs.cache-hit != 'true' && + runner.os == 'Windows' + shell: pwsh + run: | + if ($env:SLACK_CLI_VERSION) { + $installer = Join-Path $env:TEMP "install-slack-cli.ps1" + Invoke-WebRequest -Uri "https://downloads.slack-edge.com/slack-cli/install-windows-dev.ps1" -OutFile $installer + & $installer -v $env:SLACK_CLI_VERSION + } else { + irm https://downloads.slack-edge.com/slack-cli/install-windows-dev.ps1 | iex + } + env: + SLACK_CLI_VERSION: ${{ inputs.version }} + + - name: Run Slack CLI command + id: slack-cli + if: inputs.command != '' + shell: bash + env: + SLACK_COMMAND: ${{ inputs.command }} + SLACK_TOKEN: ${{ inputs.token }} + run: | + args="$SLACK_COMMAND --skip-update" + if [ -n "$SLACK_TOKEN" ]; then + args="$args --token $SLACK_TOKEN" + fi + + set +e + output=$(slack $args 2>&1) + exit_code=$? + set -e + + echo "ok=$([ $exit_code -eq 0 ] && echo 'true' || echo 'false')" >> "$GITHUB_OUTPUT" + echo "time=$(date +%s)" >> "$GITHUB_OUTPUT" + + echo "response<> "$GITHUB_OUTPUT" + echo "$output" >> "$GITHUB_OUTPUT" + echo "SLACKCLIEOF" >> "$GITHUB_OUTPUT" + + if [ $exit_code -ne 0 ]; then + echo "::error::Slack CLI command failed with exit code $exit_code" + exit $exit_code + fi From 165d9f6f9a358ea735c2494e10093560e5b0936d Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 24 Feb 2026 21:15:26 -0800 Subject: [PATCH 02/18] feat: cli --- .github/workflows/integration.yml | 35 ++++---- .github/workflows/publish.yml | 3 +- action.yml | 137 +----------------------------- cli/action.yml | 115 +++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 150 deletions(-) create mode 100644 cli/action.yml diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 96919bc2..8c14c3f9 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -248,21 +248,26 @@ jobs: env: PAYLOAD_FILE_OUTPUT_TIME: ${{ steps.payload_file.outputs.time }} - - name: "integration(cli): run a slack cli version check" - id: cli-version - uses: ./ + cli: + name: Run CLI tests + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + permissions: + contents: read + steps: + - name: "build: checkout the latest changes" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - command: "version" - - - name: "integration(cli): confirm the cli command succeeded" - run: test "$CLI_OK" = "true" - env: - CLI_OK: ${{ steps.cli-version.outputs.ok }} + persist-credentials: false + ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.sha }} - - name: "chore(health): check up on recent changes to the health score" - uses: slackapi/slack-health-score@d58a419f15cdaff97e9aa7f09f95772830ab66f7 # v0.1.1 + - name: "integration(cli): run a slack cli version check" + id: version + uses: ./cli with: - codecov_token: ${{ secrets.CODECOV_API_TOKEN }} - github_token: ${{ secrets.GITHUB_TOKEN }} - extension: js - include: src + command: "version" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9a70b6c9..54d5ec10 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,9 +37,10 @@ jobs: id: tag uses: teunmooij/github-versioned-release@3edf649c6e5e5e976d43f2584b15bdc8b4c8f0df # v1.2.1 with: - template: composite-action + template: javascript-action include: | dist/**/* + cli/**/* env: GITHUB_TOKEN: ${{ github.token }} diff --git a/action.yml b/action.yml index a863b45e..39c8b499 100644 --- a/action.yml +++ b/action.yml @@ -1,13 +1,10 @@ name: "Slack: Send to Slack" author: "slackapi" -description: "Send data to Slack to start a Slack workflow in Workflow Builder, call a Slack API method, post a message into a channel, or run a Slack CLI command" +description: "Send data to Slack to start a Slack workflow in Workflow Builder, call a Slack API method, or post a message into a channel" inputs: api: description: "A custom API URL to send Slack API method requests to." required: false - command: - description: "A Slack CLI command to run without the 'slack' prefix." - required: false errors: default: "false" description: "If the step exits with an error on errors or continues." @@ -37,9 +34,6 @@ inputs: token: description: "The authentication value used with the Slack API." required: false - version: - description: "The version of the Slack CLI to install." - required: false webhook: description: "A location for posting request payloads." required: false @@ -49,141 +43,16 @@ inputs: outputs: ok: description: "If the request completed without returning errors." - value: ${{ steps.slack-send.outputs.ok || steps.slack-cli.outputs.ok }} response: description: "A JSON stringified version of the Slack API response." - value: ${{ steps.slack-send.outputs.response || steps.slack-cli.outputs.response }} time: description: "The Unix epoch time that the step completed." - value: ${{ steps.slack-send.outputs.time || steps.slack-cli.outputs.time }} channel_id: description: "The channel ID returned with some of the Slack API methods." - value: ${{ steps.slack-send.outputs.channel_id }} thread_ts: description: "The timestamp of a parent Slack message with threaded replies." - value: ${{ steps.slack-send.outputs.thread_ts }} ts: description: "The timestamp of a Slack message or event in the response." - value: ${{ steps.slack-send.outputs.ts }} runs: - using: composite - steps: - - name: Validate inputs - if: inputs.command != '' && (inputs.method != '' || inputs.webhook != '') - shell: bash - run: | - echo "::error::The 'command' input cannot be combined with 'method' or 'webhook' inputs." - exit 1 - - - name: Send data to Slack - id: slack-send - if: inputs.command == '' - shell: bash - run: node "${{ github.action_path }}/dist/index.js" - env: - INPUT_API: ${{ inputs.api }} - INPUT_ERRORS: ${{ inputs.errors }} - INPUT_METHOD: ${{ inputs.method }} - INPUT_PAYLOAD: ${{ inputs.payload }} - INPUT_PAYLOAD-DELIMITER: ${{ inputs.payload-delimiter }} - INPUT_PAYLOAD-FILE-PATH: ${{ inputs.payload-file-path }} - INPUT_PAYLOAD-TEMPLATED: ${{ inputs.payload-templated }} - INPUT_PROXY: ${{ inputs.proxy }} - INPUT_RETRIES: ${{ inputs.retries }} - INPUT_TOKEN: ${{ inputs.token }} - INPUT_WEBHOOK: ${{ inputs.webhook }} - INPUT_WEBHOOK-TYPE: ${{ inputs.webhook-type }} - - - name: Check if Slack CLI already exists - id: slack-cli-check - if: inputs.command != '' - shell: bash - run: | - if command -v slack &> /dev/null; then - echo "cli-exists=true" >> "$GITHUB_OUTPUT" - else - echo "cli-exists=false" >> "$GITHUB_OUTPUT" - fi - - - name: Cache Slack CLI - if: inputs.command != '' && steps.slack-cli-check.outputs.cli-exists != 'true' - id: cache-cli - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 - with: - path: | - ${{ runner.os == 'Windows' && format('{0}\AppData\Local\slack-cli', env.USERPROFILE) || format('{0}/.slack/bin', env.HOME) }} - key: slack-cli-${{ runner.os }}-${{ runner.arch }}-${{ inputs.version }} - - - name: Add Slack CLI to PATH (Linux/macOS) - if: inputs.command != '' && steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os != 'Windows' - shell: bash - run: echo "$HOME/.slack/bin" >> "$GITHUB_PATH" - - - name: Add Slack CLI to PATH (Windows) - if: inputs.command != '' && steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os == 'Windows' - shell: pwsh - run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\.slack\bin" - - - name: Install Slack CLI (Linux/macOS) - if: >- - inputs.command != '' && - steps.slack-cli-check.outputs.cli-exists != 'true' && - steps.cache-cli.outputs.cache-hit != 'true' && - runner.os != 'Windows' - shell: bash - run: | - if [ -n "$SLACK_CLI_VERSION" ]; then - curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s -- -v "$SLACK_CLI_VERSION" - else - curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s - fi - env: - SLACK_CLI_VERSION: ${{ inputs.version }} - - - name: Install Slack CLI (Windows) - if: >- - inputs.command != '' && - steps.slack-cli-check.outputs.cli-exists != 'true' && - steps.cache-cli.outputs.cache-hit != 'true' && - runner.os == 'Windows' - shell: pwsh - run: | - if ($env:SLACK_CLI_VERSION) { - $installer = Join-Path $env:TEMP "install-slack-cli.ps1" - Invoke-WebRequest -Uri "https://downloads.slack-edge.com/slack-cli/install-windows-dev.ps1" -OutFile $installer - & $installer -v $env:SLACK_CLI_VERSION - } else { - irm https://downloads.slack-edge.com/slack-cli/install-windows-dev.ps1 | iex - } - env: - SLACK_CLI_VERSION: ${{ inputs.version }} - - - name: Run Slack CLI command - id: slack-cli - if: inputs.command != '' - shell: bash - env: - SLACK_COMMAND: ${{ inputs.command }} - SLACK_TOKEN: ${{ inputs.token }} - run: | - args="$SLACK_COMMAND --skip-update" - if [ -n "$SLACK_TOKEN" ]; then - args="$args --token $SLACK_TOKEN" - fi - - set +e - output=$(slack $args 2>&1) - exit_code=$? - set -e - - echo "ok=$([ $exit_code -eq 0 ] && echo 'true' || echo 'false')" >> "$GITHUB_OUTPUT" - echo "time=$(date +%s)" >> "$GITHUB_OUTPUT" - - echo "response<> "$GITHUB_OUTPUT" - echo "$output" >> "$GITHUB_OUTPUT" - echo "SLACKCLIEOF" >> "$GITHUB_OUTPUT" - - if [ $exit_code -ne 0 ]; then - echo "::error::Slack CLI command failed with exit code $exit_code" - exit $exit_code - fi + using: "node20" + main: "dist/index.js" diff --git a/cli/action.yml b/cli/action.yml new file mode 100644 index 00000000..78923f28 --- /dev/null +++ b/cli/action.yml @@ -0,0 +1,115 @@ +name: "Slack: Run CLI Command" +author: "slackapi" +description: "Install the Slack CLI and run a command in a GitHub Actions workflow" +inputs: + command: + description: "A Slack CLI command to run without the 'slack' prefix." + required: true + token: + description: "A service token passed as the '--token' flag to the CLI command." + required: false + version: + description: "The version of the Slack CLI to install. Defaults to the latest." + required: false +outputs: + ok: + description: "If the command completed with a '0' exit code." + value: ${{ steps.slack-cli.outputs.ok }} + response: + description: "The standard output from the CLI command." + value: ${{ steps.slack-cli.outputs.response }} + time: + description: "The Unix epoch time that the step completed." + value: ${{ steps.slack-cli.outputs.time }} +runs: + using: composite + steps: + - name: Check if Slack CLI already exists + id: slack-cli-check + shell: bash + run: | + if command -v slack &> /dev/null; then + echo "cli-exists=true" >> "$GITHUB_OUTPUT" + else + echo "cli-exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Cache Slack CLI + if: steps.slack-cli-check.outputs.cli-exists != 'true' + id: cache-cli + uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + with: + path: | + ${{ runner.os == 'Windows' && format('{0}\AppData\Local\slack-cli', env.USERPROFILE) || format('{0}/.slack/bin', env.HOME) }} + key: slack-cli-${{ runner.os }}-${{ runner.arch }}-${{ inputs.version }} + + - name: Add Slack CLI to PATH (Linux/macOS) + if: steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os != 'Windows' + shell: bash + run: echo "$HOME/.slack/bin" >> "$GITHUB_PATH" # zizmor: ignore[github-env] + + - name: Add Slack CLI to PATH (Windows) + if: steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os == 'Windows' + shell: pwsh + run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\.slack\bin" # zizmor: ignore[github-env] + + - name: Install Slack CLI (Linux/macOS) + if: >- + steps.slack-cli-check.outputs.cli-exists != 'true' && + steps.cache-cli.outputs.cache-hit != 'true' && + runner.os != 'Windows' + shell: bash + run: | + if [ -n "$SLACK_CLI_VERSION" ]; then + curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s -- -v "$SLACK_CLI_VERSION" + else + curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s + fi + env: + SLACK_CLI_VERSION: ${{ inputs.version }} + + - name: Install Slack CLI (Windows) + if: >- + steps.slack-cli-check.outputs.cli-exists != 'true' && + steps.cache-cli.outputs.cache-hit != 'true' && + runner.os == 'Windows' + shell: pwsh + run: | + if ($env:SLACK_CLI_VERSION) { + $installer = Join-Path $env:TEMP "install-slack-cli.ps1" + Invoke-WebRequest -Uri "https://downloads.slack-edge.com/slack-cli/install-windows-dev.ps1" -OutFile $installer + & $installer -v $env:SLACK_CLI_VERSION + } else { + irm https://downloads.slack-edge.com/slack-cli/install-windows-dev.ps1 | iex + } + env: + SLACK_CLI_VERSION: ${{ inputs.version }} + + - name: Run Slack CLI command + id: slack-cli + shell: bash + env: + SLACK_COMMAND: ${{ inputs.command }} + SLACK_TOKEN: ${{ inputs.token }} + run: | + args="$SLACK_COMMAND --skip-update" + if [ -n "$SLACK_TOKEN" ]; then + args="$args --token $SLACK_TOKEN" + fi + + set +e + output=$(slack $args 2>&1) + exit_code=$? + set -e + + echo "ok=$([ $exit_code -eq 0 ] && echo 'true' || echo 'false')" >> "$GITHUB_OUTPUT" + echo "time=$(date +%s)" >> "$GITHUB_OUTPUT" + + echo "response<> "$GITHUB_OUTPUT" + echo "$output" >> "$GITHUB_OUTPUT" + echo "SLACKCLIEOF" >> "$GITHUB_OUTPUT" + + if [ $exit_code -ne 0 ]; then + echo "::error::Slack CLI command failed with exit code $exit_code" + exit $exit_code + fi From 2d8c99663449093476d1c2225893353573ee2b22 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 24 Feb 2026 21:26:57 -0800 Subject: [PATCH 03/18] fix: echo output --- .github/workflows/integration.yml | 1 - cli/action.yml | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 8c14c3f9..59ce223f 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -267,7 +267,6 @@ jobs: ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.sha }} - name: "integration(cli): run a slack cli version check" - id: version uses: ./cli with: command: "version" diff --git a/cli/action.yml b/cli/action.yml index 78923f28..b7b8c90b 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -102,6 +102,8 @@ runs: exit_code=$? set -e + echo "$output" + echo "ok=$([ $exit_code -eq 0 ] && echo 'true' || echo 'false')" >> "$GITHUB_OUTPUT" echo "time=$(date +%s)" >> "$GITHUB_OUTPUT" From 077f882c0cfcf4ff0be63dd372e2094f52dcdf84 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 24 Feb 2026 22:59:33 -0800 Subject: [PATCH 04/18] ci: use development build Co-Authored-By: Claude --- .github/workflows/integration.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 59ce223f..12dc238e 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -270,3 +270,4 @@ jobs: uses: ./cli with: command: "version" + version: "3.13.0-fix-windows-ci-feature" From 35b81020892a15f73b1955877369f3448b148dd7 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 00:06:33 -0800 Subject: [PATCH 05/18] fix: add to windows path --- cli/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/action.yml b/cli/action.yml index b7b8c90b..f2a3bda8 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -51,7 +51,7 @@ runs: - name: Add Slack CLI to PATH (Windows) if: steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os == 'Windows' shell: pwsh - run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\.slack\bin" # zizmor: ignore[github-env] + run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\AppData\Local\slack-cli\bin" # zizmor: ignore[github-env] - name: Install Slack CLI (Linux/macOS) if: >- From 5d5197b887302bbfac81382bc782d8d56ce4a039 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 00:17:18 -0800 Subject: [PATCH 06/18] ci: remove feature build cli version --- .github/workflows/integration.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 12dc238e..59ce223f 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -270,4 +270,3 @@ jobs: uses: ./cli with: command: "version" - version: "3.13.0-fix-windows-ci-feature" From 613ab73d8ed70e37d8127130c00973234494f7a5 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 00:38:52 -0800 Subject: [PATCH 07/18] test: verbose version --- .github/workflows/integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 59ce223f..5f78ee8f 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -269,4 +269,4 @@ jobs: - name: "integration(cli): run a slack cli version check" uses: ./cli with: - command: "version" + command: "version --verbose" From 47ed37c31d6a91d4a1c8e94da90cde57bf73a020 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 00:42:25 -0800 Subject: [PATCH 08/18] fix: run windows build in powershell --- cli/action.yml | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/cli/action.yml b/cli/action.yml index f2a3bda8..d7bbbc58 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -14,13 +14,13 @@ inputs: outputs: ok: description: "If the command completed with a '0' exit code." - value: ${{ steps.slack-cli.outputs.ok }} + value: ${{ steps.slack-cli-unix.outputs.ok || steps.slack-cli-windows.outputs.ok }} response: description: "The standard output from the CLI command." - value: ${{ steps.slack-cli.outputs.response }} + value: ${{ steps.slack-cli-unix.outputs.response || steps.slack-cli-windows.outputs.response }} time: description: "The Unix epoch time that the step completed." - value: ${{ steps.slack-cli.outputs.time }} + value: ${{ steps.slack-cli-unix.outputs.time || steps.slack-cli-windows.outputs.time }} runs: using: composite steps: @@ -85,8 +85,9 @@ runs: env: SLACK_CLI_VERSION: ${{ inputs.version }} - - name: Run Slack CLI command - id: slack-cli + - name: Run Slack CLI command (Linux/macOS) + if: runner.os != 'Windows' + id: slack-cli-unix shell: bash env: SLACK_COMMAND: ${{ inputs.command }} @@ -115,3 +116,33 @@ runs: echo "::error::Slack CLI command failed with exit code $exit_code" exit $exit_code fi + + - name: Run Slack CLI command (Windows) + if: runner.os == 'Windows' + id: slack-cli-windows + shell: pwsh + env: + SLACK_COMMAND: ${{ inputs.command }} + SLACK_TOKEN: ${{ inputs.token }} + run: | + $args = "$env:SLACK_COMMAND --skip-update" + if ($env:SLACK_TOKEN) { + $args = "$args --token $env:SLACK_TOKEN" + } + + $output = slack $args.Split(' ') 2>&1 | Out-String + $exit_code = $LASTEXITCODE + + Write-Output $output + + "ok=$( if ($exit_code -eq 0) { 'true' } else { 'false' } )" >> $env:GITHUB_OUTPUT + "time=$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())" >> $env:GITHUB_OUTPUT + + "response<> $env:GITHUB_OUTPUT + $output >> $env:GITHUB_OUTPUT + "SLACKCLIEOF" >> $env:GITHUB_OUTPUT + + if ($exit_code -ne 0) { + Write-Output "::error::Slack CLI command failed with exit code $exit_code" + exit $exit_code + } From 4e7d5d377b55c7aa7272522082cfb91e9b6d1a4d Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 01:07:43 -0800 Subject: [PATCH 09/18] ci: dev --- .github/workflows/integration.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 5f78ee8f..cdf7920b 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -270,3 +270,4 @@ jobs: uses: ./cli with: command: "version --verbose" + version: "3.13.0-fix-windows-ci-feature" From f50140b89fe6a3c061ef78412153e3dd193cad13 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 01:11:50 -0800 Subject: [PATCH 10/18] ci: debug --- cli/action.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cli/action.yml b/cli/action.yml index d7bbbc58..63bc1e9d 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -125,11 +125,20 @@ runs: SLACK_COMMAND: ${{ inputs.command }} SLACK_TOKEN: ${{ inputs.token }} run: | + Write-Output "DEBUG: PATH entries:" + $env:PATH -split ';' | Where-Object { $_ -match 'slack' } | ForEach-Object { Write-Output " $_" } + Write-Output "DEBUG: Looking for slack binary..." + Get-Command slack -ErrorAction SilentlyContinue | Format-List + $slackDir = "$env:USERPROFILE\AppData\Local\slack-cli\bin" + Write-Output "DEBUG: Contents of ${slackDir}:" + if (Test-Path $slackDir) { Get-ChildItem $slackDir } else { Write-Output " Directory not found!" } + $args = "$env:SLACK_COMMAND --skip-update" if ($env:SLACK_TOKEN) { $args = "$args --token $env:SLACK_TOKEN" } + Write-Output "DEBUG: Running: slack $args" $output = slack $args.Split(' ') 2>&1 | Out-String $exit_code = $LASTEXITCODE From b48e5cf48525a4e1530a36e2bfac1413c5483974 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 01:15:47 -0800 Subject: [PATCH 11/18] ci: tee output --- cli/action.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/action.yml b/cli/action.yml index 63bc1e9d..203d9b46 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -99,7 +99,7 @@ runs: fi set +e - output=$(slack $args 2>&1) + output=$(slack $args 2>&1 | tee /dev/stderr) exit_code=$? set -e @@ -139,10 +139,10 @@ runs: } Write-Output "DEBUG: Running: slack $args" - $output = slack $args.Split(' ') 2>&1 | Out-String + $outputFile = New-TemporaryFile + slack $args.Split(' ') 2>&1 | Tee-Object -FilePath $outputFile.FullName $exit_code = $LASTEXITCODE - - Write-Output $output + $output = Get-Content $outputFile.FullName -Raw "ok=$( if ($exit_code -eq 0) { 'true' } else { 'false' } )" >> $env:GITHUB_OUTPUT "time=$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())" >> $env:GITHUB_OUTPUT From 32371dd83173f4567b5bec892274fdc4388134ad Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 01:33:28 -0800 Subject: [PATCH 12/18] test: write empty credentials for windows tests for io speed --- cli/action.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cli/action.yml b/cli/action.yml index 203d9b46..eca93846 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -133,6 +133,17 @@ runs: Write-Output "DEBUG: Contents of ${slackDir}:" if (Test-Path $slackDir) { Get-ChildItem $slackDir } else { Write-Output " Directory not found!" } + # Pre-create credentials file to avoid write/read race + $slackConfigDir = "$env:USERPROFILE\.slack" + if (-not (Test-Path $slackConfigDir)) { New-Item -ItemType Directory -Path $slackConfigDir -Force | Out-Null } + $credsPath = "$slackConfigDir\credentials.json" + if (-not (Test-Path $credsPath)) { + Set-Content -Path $credsPath -Value "{}`n" + Write-Output "DEBUG: Pre-created empty credentials.json" + } else { + Write-Output "DEBUG: credentials.json already exists" + } + $args = "$env:SLACK_COMMAND --skip-update" if ($env:SLACK_TOKEN) { $args = "$args --token $env:SLACK_TOKEN" From 059f8f3bb0a0420369740f42c7cb2994086803e3 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 01:47:01 -0800 Subject: [PATCH 13/18] test: attempt to create all windows files or quit --- cli/action.yml | 74 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/cli/action.yml b/cli/action.yml index eca93846..1baf1291 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -133,26 +133,78 @@ runs: Write-Output "DEBUG: Contents of ${slackDir}:" if (Test-Path $slackDir) { Get-ChildItem $slackDir } else { Write-Output " Directory not found!" } - # Pre-create credentials file to avoid write/read race + # Pre-create all .slack filesystem structures to eliminate lazy creation as a suspect $slackConfigDir = "$env:USERPROFILE\.slack" if (-not (Test-Path $slackConfigDir)) { New-Item -ItemType Directory -Path $slackConfigDir -Force | Out-Null } + $credsPath = "$slackConfigDir\credentials.json" - if (-not (Test-Path $credsPath)) { - Set-Content -Path $credsPath -Value "{}`n" - Write-Output "DEBUG: Pre-created empty credentials.json" - } else { - Write-Output "DEBUG: credentials.json already exists" + if (-not (Test-Path $credsPath)) { Set-Content -Path $credsPath -Value "{}`n" } + + $configPath = "$slackConfigDir\config.json" + if (-not (Test-Path $configPath)) { Set-Content -Path $configPath -Value "{}`n" } + + $logsDir = "$slackConfigDir\logs" + if (-not (Test-Path $logsDir)) { New-Item -ItemType Directory -Path $logsDir -Force | Out-Null } + + $configSubDir = "$slackConfigDir\config" + if (-not (Test-Path $configSubDir)) { New-Item -ItemType Directory -Path $configSubDir -Force | Out-Null } + + # Permission diagnostics + Write-Output "DEBUG: .slack directory contents:" + Get-ChildItem -Path $slackConfigDir -Recurse | ForEach-Object { Write-Output " $($_.FullName) [$(if($_.PSIsContainer){'dir'}else{$_.Length.ToString() + 'b'})]" } + + Write-Output "DEBUG: Testing file read/write access..." + try { + $content = Get-Content $credsPath -Raw + Write-Output " credentials.json readable: '$content'" + } catch { + Write-Output " ERROR reading credentials.json: $_" + } + + try { + $testFile = "$slackConfigDir\test-write.tmp" + Set-Content -Path $testFile -Value "test" + Remove-Item $testFile + Write-Output " .slack directory writable: OK" + } catch { + Write-Output " ERROR writing to .slack directory: $_" } - $args = "$env:SLACK_COMMAND --skip-update" + $cliArgs = "$env:SLACK_COMMAND --skip-update" if ($env:SLACK_TOKEN) { - $args = "$args --token $env:SLACK_TOKEN" + $cliArgs = "$cliArgs --token $env:SLACK_TOKEN" } - Write-Output "DEBUG: Running: slack $args" + Write-Output "DEBUG: Running: slack $cliArgs" $outputFile = New-TemporaryFile - slack $args.Split(' ') 2>&1 | Tee-Object -FilePath $outputFile.FullName - $exit_code = $LASTEXITCODE + $errFile = "$($outputFile.FullName).err" + + $process = Start-Process -FilePath "slack" -ArgumentList $cliArgs.Split(' ') -NoNewWindow -PassThru -RedirectStandardOutput $outputFile.FullName -RedirectStandardError $errFile + $exited = $process.WaitForExit(60000) # 60 second timeout + + if (-not $exited) { + Write-Output "ERROR: slack CLI hung for 60s, dumping diagnostics..." + Write-Output "DEBUG: Process ID: $($process.Id)" + Write-Output "DEBUG: Process threads:" + try { + Get-Process -Id $process.Id | Select-Object -ExpandProperty Threads | Format-Table Id, ThreadState, WaitReason -AutoSize + } catch { + Write-Output " Could not get thread info: $_" + } + Write-Output "DEBUG: stdout so far:" + Get-Content $outputFile.FullName + Write-Output "DEBUG: stderr so far:" + Get-Content $errFile + Stop-Process -Id $process.Id -Force + $exit_code = 1 + } else { + $exit_code = $process.ExitCode + Write-Output "DEBUG: CLI completed with exit code $exit_code" + Get-Content $outputFile.FullName + $errContent = Get-Content $errFile -Raw + if ($errContent) { Write-Output "DEBUG: stderr: $errContent" } + } + $output = Get-Content $outputFile.FullName -Raw "ok=$( if ($exit_code -eq 0) { 'true' } else { 'false' } )" >> $env:GITHUB_OUTPUT From eaed8dbeae75e744ac26fe6e1b3430956e9ae221 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 01:56:04 -0800 Subject: [PATCH 14/18] build: use .net api for better diagnostics --- cli/action.yml | 62 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/cli/action.yml b/cli/action.yml index 1baf1291..72c0903f 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -175,37 +175,63 @@ runs: $cliArgs = "$cliArgs --token $env:SLACK_TOKEN" } - Write-Output "DEBUG: Running: slack $cliArgs" - $outputFile = New-TemporaryFile - $errFile = "$($outputFile.FullName).err" + $slackExe = (Get-Command slack).Source + Write-Output "DEBUG: Starting at $(Get-Date -Format 'HH:mm:ss.fff'): $slackExe $cliArgs" - $process = Start-Process -FilePath "slack" -ArgumentList $cliArgs.Split(' ') -NoNewWindow -PassThru -RedirectStandardOutput $outputFile.FullName -RedirectStandardError $errFile - $exited = $process.WaitForExit(60000) # 60 second timeout + # Use .NET Process API directly for reliable timeout + output capture + $psi = [System.Diagnostics.ProcessStartInfo]::new($slackExe, $cliArgs) + $psi.UseShellExecute = $false + $psi.RedirectStandardOutput = $true + $psi.RedirectStandardError = $true + $psi.CreateNoWindow = $true + + $proc = [System.Diagnostics.Process]::new() + $proc.StartInfo = $psi + + try { + $proc.Start() | Out-Null + Write-Output "DEBUG: Process started with PID $($proc.Id)" + } catch { + Write-Output "ERROR: Failed to start process: $_" + Write-Output $_.ScriptStackTrace + exit 1 + } + + # Read stdout/stderr asynchronously to avoid pipe buffer deadlock + $stdoutTask = $proc.StandardOutput.ReadToEndAsync() + $stderrTask = $proc.StandardError.ReadToEndAsync() + + $exited = $proc.WaitForExit(60000) # 60 second timeout if (-not $exited) { Write-Output "ERROR: slack CLI hung for 60s, dumping diagnostics..." - Write-Output "DEBUG: Process ID: $($process.Id)" + Write-Output "DEBUG: Process ID: $($proc.Id)" Write-Output "DEBUG: Process threads:" try { - Get-Process -Id $process.Id | Select-Object -ExpandProperty Threads | Format-Table Id, ThreadState, WaitReason -AutoSize + Get-Process -Id $proc.Id | Select-Object -ExpandProperty Threads | Format-Table Id, ThreadState, WaitReason -AutoSize } catch { Write-Output " Could not get thread info: $_" } - Write-Output "DEBUG: stdout so far:" - Get-Content $outputFile.FullName - Write-Output "DEBUG: stderr so far:" - Get-Content $errFile - Stop-Process -Id $process.Id -Force + $proc.Kill() + $proc.WaitForExit(5000) + # After kill, async reads will complete with whatever was buffered + [void]$stdoutTask.Wait(5000) + [void]$stderrTask.Wait(5000) + Write-Output "DEBUG: stdout captured:" + Write-Output $stdoutTask.Result + Write-Output "DEBUG: stderr captured:" + Write-Output $stderrTask.Result $exit_code = 1 } else { - $exit_code = $process.ExitCode - Write-Output "DEBUG: CLI completed with exit code $exit_code" - Get-Content $outputFile.FullName - $errContent = Get-Content $errFile -Raw - if ($errContent) { Write-Output "DEBUG: stderr: $errContent" } + [void]$stdoutTask.Wait(5000) + [void]$stderrTask.Wait(5000) + $exit_code = $proc.ExitCode + Write-Output "DEBUG: CLI completed at $(Get-Date -Format 'HH:mm:ss.fff') with exit code $exit_code" + Write-Output $stdoutTask.Result + if ($stderrTask.Result) { Write-Output "DEBUG: stderr: $($stderrTask.Result)" } } - $output = Get-Content $outputFile.FullName -Raw + $output = if ($stdoutTask.IsCompleted) { $stdoutTask.Result } else { "" } "ok=$( if ($exit_code -eq 0) { 'true' } else { 'false' } )" >> $env:GITHUB_OUTPUT "time=$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())" >> $env:GITHUB_OUTPUT From 65f25ff9189b226449bf9d5970d705ac8b7333e0 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 02:31:22 -0800 Subject: [PATCH 15/18] test: remove debug from windows --- .github/workflows/integration.yml | 2 +- cli/action.yml | 106 ++---------------------------- 2 files changed, 5 insertions(+), 103 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index cdf7920b..8550a692 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -12,7 +12,7 @@ on: jobs: integration: - name: Run integration tests + name: Run API tests runs-on: ubuntu-latest environment: staging permissions: diff --git a/cli/action.yml b/cli/action.yml index 72c0903f..0df62818 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -125,113 +125,15 @@ runs: SLACK_COMMAND: ${{ inputs.command }} SLACK_TOKEN: ${{ inputs.token }} run: | - Write-Output "DEBUG: PATH entries:" - $env:PATH -split ';' | Where-Object { $_ -match 'slack' } | ForEach-Object { Write-Output " $_" } - Write-Output "DEBUG: Looking for slack binary..." - Get-Command slack -ErrorAction SilentlyContinue | Format-List - $slackDir = "$env:USERPROFILE\AppData\Local\slack-cli\bin" - Write-Output "DEBUG: Contents of ${slackDir}:" - if (Test-Path $slackDir) { Get-ChildItem $slackDir } else { Write-Output " Directory not found!" } - - # Pre-create all .slack filesystem structures to eliminate lazy creation as a suspect - $slackConfigDir = "$env:USERPROFILE\.slack" - if (-not (Test-Path $slackConfigDir)) { New-Item -ItemType Directory -Path $slackConfigDir -Force | Out-Null } - - $credsPath = "$slackConfigDir\credentials.json" - if (-not (Test-Path $credsPath)) { Set-Content -Path $credsPath -Value "{}`n" } - - $configPath = "$slackConfigDir\config.json" - if (-not (Test-Path $configPath)) { Set-Content -Path $configPath -Value "{}`n" } - - $logsDir = "$slackConfigDir\logs" - if (-not (Test-Path $logsDir)) { New-Item -ItemType Directory -Path $logsDir -Force | Out-Null } - - $configSubDir = "$slackConfigDir\config" - if (-not (Test-Path $configSubDir)) { New-Item -ItemType Directory -Path $configSubDir -Force | Out-Null } - - # Permission diagnostics - Write-Output "DEBUG: .slack directory contents:" - Get-ChildItem -Path $slackConfigDir -Recurse | ForEach-Object { Write-Output " $($_.FullName) [$(if($_.PSIsContainer){'dir'}else{$_.Length.ToString() + 'b'})]" } - - Write-Output "DEBUG: Testing file read/write access..." - try { - $content = Get-Content $credsPath -Raw - Write-Output " credentials.json readable: '$content'" - } catch { - Write-Output " ERROR reading credentials.json: $_" - } - - try { - $testFile = "$slackConfigDir\test-write.tmp" - Set-Content -Path $testFile -Value "test" - Remove-Item $testFile - Write-Output " .slack directory writable: OK" - } catch { - Write-Output " ERROR writing to .slack directory: $_" - } - $cliArgs = "$env:SLACK_COMMAND --skip-update" if ($env:SLACK_TOKEN) { $cliArgs = "$cliArgs --token $env:SLACK_TOKEN" } - $slackExe = (Get-Command slack).Source - Write-Output "DEBUG: Starting at $(Get-Date -Format 'HH:mm:ss.fff'): $slackExe $cliArgs" - - # Use .NET Process API directly for reliable timeout + output capture - $psi = [System.Diagnostics.ProcessStartInfo]::new($slackExe, $cliArgs) - $psi.UseShellExecute = $false - $psi.RedirectStandardOutput = $true - $psi.RedirectStandardError = $true - $psi.CreateNoWindow = $true - - $proc = [System.Diagnostics.Process]::new() - $proc.StartInfo = $psi - - try { - $proc.Start() | Out-Null - Write-Output "DEBUG: Process started with PID $($proc.Id)" - } catch { - Write-Output "ERROR: Failed to start process: $_" - Write-Output $_.ScriptStackTrace - exit 1 - } - - # Read stdout/stderr asynchronously to avoid pipe buffer deadlock - $stdoutTask = $proc.StandardOutput.ReadToEndAsync() - $stderrTask = $proc.StandardError.ReadToEndAsync() - - $exited = $proc.WaitForExit(60000) # 60 second timeout - - if (-not $exited) { - Write-Output "ERROR: slack CLI hung for 60s, dumping diagnostics..." - Write-Output "DEBUG: Process ID: $($proc.Id)" - Write-Output "DEBUG: Process threads:" - try { - Get-Process -Id $proc.Id | Select-Object -ExpandProperty Threads | Format-Table Id, ThreadState, WaitReason -AutoSize - } catch { - Write-Output " Could not get thread info: $_" - } - $proc.Kill() - $proc.WaitForExit(5000) - # After kill, async reads will complete with whatever was buffered - [void]$stdoutTask.Wait(5000) - [void]$stderrTask.Wait(5000) - Write-Output "DEBUG: stdout captured:" - Write-Output $stdoutTask.Result - Write-Output "DEBUG: stderr captured:" - Write-Output $stderrTask.Result - $exit_code = 1 - } else { - [void]$stdoutTask.Wait(5000) - [void]$stderrTask.Wait(5000) - $exit_code = $proc.ExitCode - Write-Output "DEBUG: CLI completed at $(Get-Date -Format 'HH:mm:ss.fff') with exit code $exit_code" - Write-Output $stdoutTask.Result - if ($stderrTask.Result) { Write-Output "DEBUG: stderr: $($stderrTask.Result)" } - } - - $output = if ($stdoutTask.IsCompleted) { $stdoutTask.Result } else { "" } + $outputFile = New-TemporaryFile + slack $cliArgs.Split(' ') 2>&1 | Tee-Object -FilePath $outputFile.FullName + $exit_code = $LASTEXITCODE + $output = Get-Content $outputFile.FullName -Raw "ok=$( if ($exit_code -eq 0) { 'true' } else { 'false' } )" >> $env:GITHUB_OUTPUT "time=$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())" >> $env:GITHUB_OUTPUT From 4b307de92c182de9ee477e9ae2ee5aa1a3927f74 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 02:39:15 -0800 Subject: [PATCH 16/18] chore: remove verbose flag option --- .github/workflows/integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 8550a692..b379692e 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -269,5 +269,5 @@ jobs: - name: "integration(cli): run a slack cli version check" uses: ./cli with: - command: "version --verbose" + command: "version" version: "3.13.0-fix-windows-ci-feature" From 2d3baa15eb140727dc59ce9315d2c52549cafde2 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 02:46:19 -0800 Subject: [PATCH 17/18] fix: remove duplicate output for unix --- cli/action.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/cli/action.yml b/cli/action.yml index 0df62818..dc4f1a5b 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -103,8 +103,6 @@ runs: exit_code=$? set -e - echo "$output" - echo "ok=$([ $exit_code -eq 0 ] && echo 'true' || echo 'false')" >> "$GITHUB_OUTPUT" echo "time=$(date +%s)" >> "$GITHUB_OUTPUT" From c6baa4b18ba10ed94a2cbb30716aa46aae59b45e Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 25 Feb 2026 03:06:39 -0800 Subject: [PATCH 18/18] test: improve checks of existing cache or path --- .github/workflows/integration.yml | 45 +++++++++++++++++-------------- cli/action.yml | 26 +++++++++--------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index b379692e..c9921fce 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -68,7 +68,7 @@ jobs: env: INPUT_REF: ${{ inputs.ref }} - - name: "integration(wfb): send a payload to workflow builder via webhook trigger" + - name: "test(wfb): send a payload to workflow builder via webhook trigger" id: wfb uses: ./ with: @@ -82,12 +82,12 @@ jobs: repo_name: ${{ github.event.repository.full_name }} status: ${{ job.status }} - - name: "integration(wfb): confirm a payload was sent" + - name: "test(wfb): confirm a payload was sent" run: test -n "$WFB_OUTPUT_TIME" env: WFB_OUTPUT_TIME: ${{ steps.wfb.outputs.time }} - - name: "integration(botToken): post a message to channel" + - name: "test(api): post a message to channel" id: message uses: ./ with: @@ -98,12 +98,12 @@ jobs: channel: ${{ secrets.SLACK_CHANNEL_ID }} text: ":checkered_flag: Action happens at " - - name: "integration(method): confirm a message was posted" + - name: "test(api): confirm a message was posted" run: test -n "$MESSAGE_OUTPUT_TS" env: MESSAGE_OUTPUT_TS: ${{ steps.message.outputs.ts }} - - name: "integration(method): post a message with blocks" + - name: "test(api): post a message with blocks" id: blocks uses: ./ with: @@ -120,12 +120,12 @@ jobs: short: true value: "Processing" - - name: "integration(method): confirm the blocks were posted" + - name: "test(api): confirm the blocks were posted" run: test -n "$BLOCKS_OUTPUT_TS" env: BLOCKS_OUTPUT_TS: ${{ steps.blocks.outputs.ts }} - - name: "integration(method): post a threaded message" + - name: "test(api): post a threaded message" id: timer uses: ./ with: @@ -137,15 +137,15 @@ jobs: text: "Started at `${{ steps.blocks.outputs.time }}`" thread_ts: "${{ steps.blocks.outputs.ts }}" - - name: "integration(incoming): confirm the thread started" + - name: "test(api): confirm the thread started" run: test -n "$TIMER_OUTPUT_TIME" env: TIMER_OUTPUT_TIME: ${{ steps.timer.outputs.time }} - - name: "integration(method): wait to mock event processing" + - name: "test(api): wait to mock event processing" run: sleep 3 - - name: "integration(method): update the original message" + - name: "test(api): update the original message" id: finished uses: ./ with: @@ -163,7 +163,7 @@ jobs: short: true value: "Completed" - - name: "integration(method): post another threaded message" + - name: "test(api): post another threaded message" id: done uses: ./ with: @@ -175,7 +175,7 @@ jobs: text: "Finished at `${{ steps.finished.outputs.time }}`" thread_ts: "${{ steps.timer.outputs.thread_ts }}" - - name: "integration(method): post a file into a channel" + - name: "test(api): post a file into a channel" id: file uses: ./ with: @@ -188,7 +188,7 @@ jobs: file: .github/workflows/integration.yml filename: integration.yml - - name: "integration(method): react to the completed update message" + - name: "test(api): react to the completed update message" uses: ./ with: errors: true @@ -199,12 +199,12 @@ jobs: timestamp: ${{ steps.blocks.outputs.ts }} name: "tada" - - name: "integration(method): confirm the thread ended" + - name: "test(api): confirm the thread ended" run: test -n "$DONE_OUTPUT_TIME" env: DONE_OUTPUT_TIME: ${{ steps.done.outputs.time }} - - name: "integration(incoming): post a message via incoming webhook" + - name: "test(incoming): post a message via incoming webhook" id: incoming uses: ./ with: @@ -220,17 +220,17 @@ jobs: text: ":link: A message was received via incoming webhook" emoji: true - - name: "integration(incoming): confirm a webhook was posted" + - name: "test(incoming): confirm a webhook was posted" run: test -n "$INCOMING_WEBHOOK_OUTPUT_TIME" env: INCOMING_WEBHOOK_OUTPUT_TIME: ${{ steps.incoming.outputs.time }} - - name: "integration(incoming): reveal contents of the github payload" + - name: "test(incoming): reveal contents of the github payload" run: echo "$JSON" env: JSON: ${{ toJSON(github) }} - - name: "integration(incoming): post a message via payload file" + - name: "test(incoming): post a message via payload file" id: payload_file uses: ./ with: @@ -243,7 +243,7 @@ jobs: JOB_STATUS: ${{ job.status }} ATTACHMENT_COLOR: ${{ (job.status == 'success' && 'good') || (job.status == 'failure' && 'danger') || 'warning' }} - - name: "integration(incoming): confirm a payload file was posted" + - name: "test(incoming): confirm a payload file was posted" run: test -n "$PAYLOAD_FILE_OUTPUT_TIME" env: PAYLOAD_FILE_OUTPUT_TIME: ${{ steps.payload_file.outputs.time }} @@ -266,8 +266,13 @@ jobs: persist-credentials: false ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.sha }} - - name: "integration(cli): run a slack cli version check" + - name: "test(cli): run a slack cli version check" uses: ./cli with: command: "version" version: "3.13.0-fix-windows-ci-feature" + + - name: "test(cli): run a slack cli version check again" + uses: ./cli + with: + command: "version" diff --git a/cli/action.yml b/cli/action.yml index dc4f1a5b..3af30219 100644 --- a/cli/action.yml +++ b/cli/action.yml @@ -29,13 +29,13 @@ runs: shell: bash run: | if command -v slack &> /dev/null; then - echo "cli-exists=true" >> "$GITHUB_OUTPUT" + echo "exists=true" >> "$GITHUB_OUTPUT" else - echo "cli-exists=false" >> "$GITHUB_OUTPUT" + echo "exists=false" >> "$GITHUB_OUTPUT" fi - name: Cache Slack CLI - if: steps.slack-cli-check.outputs.cli-exists != 'true' + if: steps.slack-cli-check.outputs.exists != 'true' id: cache-cli uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: @@ -43,19 +43,19 @@ runs: ${{ runner.os == 'Windows' && format('{0}\AppData\Local\slack-cli', env.USERPROFILE) || format('{0}/.slack/bin', env.HOME) }} key: slack-cli-${{ runner.os }}-${{ runner.arch }}-${{ inputs.version }} - - name: Add Slack CLI to PATH (Linux/macOS) - if: steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os != 'Windows' + - name: Add Slack CLI to PATH + if: steps.slack-cli-check.outputs.exists != 'true' && runner.os != 'Windows' shell: bash run: echo "$HOME/.slack/bin" >> "$GITHUB_PATH" # zizmor: ignore[github-env] - - name: Add Slack CLI to PATH (Windows) - if: steps.slack-cli-check.outputs.cli-exists != 'true' && runner.os == 'Windows' + - name: Add Slack CLI to PATH + if: steps.slack-cli-check.outputs.exists != 'true' && runner.os == 'Windows' shell: pwsh run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\AppData\Local\slack-cli\bin" # zizmor: ignore[github-env] - - name: Install Slack CLI (Linux/macOS) + - name: Install Slack CLI if: >- - steps.slack-cli-check.outputs.cli-exists != 'true' && + steps.slack-cli-check.outputs.exists != 'true' && steps.cache-cli.outputs.cache-hit != 'true' && runner.os != 'Windows' shell: bash @@ -68,9 +68,9 @@ runs: env: SLACK_CLI_VERSION: ${{ inputs.version }} - - name: Install Slack CLI (Windows) + - name: Install Slack CLI if: >- - steps.slack-cli-check.outputs.cli-exists != 'true' && + steps.slack-cli-check.outputs.exists != 'true' && steps.cache-cli.outputs.cache-hit != 'true' && runner.os == 'Windows' shell: pwsh @@ -85,7 +85,7 @@ runs: env: SLACK_CLI_VERSION: ${{ inputs.version }} - - name: Run Slack CLI command (Linux/macOS) + - name: Run Slack CLI command if: runner.os != 'Windows' id: slack-cli-unix shell: bash @@ -115,7 +115,7 @@ runs: exit $exit_code fi - - name: Run Slack CLI command (Windows) + - name: Run Slack CLI command if: runner.os == 'Windows' id: slack-cli-windows shell: pwsh