Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions .github/resources/.actions/cli-runner/action.yml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⭐ praise: We've discussed this setup and I think the separated action definition is a nice pattern to use for the CLI technique! Thanks for encouraging this!

👁️‍🗨️ thought: The exact calling syntax escapes me but for releases it'd be so interesting to find this pattern in calling workflows:

- uses: slackapi/slack-github-action/cli@v2
  with:
    command: version

Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: "Slack: Run a CLI command"
description: "Install the Slack CLI to run a command"

inputs:
command:
description: "Slack CLI command to run. Should not include the 'slack' prefix."
type: string
default: ""
required: true
verbose:
description: "Verbose flag"
type: boolean
default: false
required: false
cli-version:
description: "CLI Version"
type: string
default: "3.6.1"
required: false
app_id:
description: "App ID"
type: string
default: ""
required: false

Comment on lines +20 to +25
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
app_id:
description: "App ID"
type: string
default: ""
required: false

🪓 question: For now is this alright to remove? I believe it might conflict with a separate --app flag?

outputs:
ok:
description: "If the command completed without an error."
value: ${{ steps.run-slack-cli-command.outputs.ok || steps.run-slack-cli-command-windows.outputs.ok }}
exit_code:
description: "Exit code"
value: ${{ steps.run-slack-cli-command.outputs.exit_code || steps.run-slack-cli-command-windows.outputs.exit_code }}
command_executed:
description: "Command ran"
value: ${{ steps.run-slack-cli-command.outputs.command_executed || steps.run-slack-cli-command-windows.outputs.command_executed }}
output:
description: "Command output"
value: ${{ steps.run-slack-cli-command.outputs.output || steps.run-slack-cli-command-windows.outputs.output }}

runs:
using: composite
steps:
- name: Cache Slack CLI
id: cache-cli
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
${{ runner.os == 'Windows' && format('{0}/AppData/Local/slack-cli', env.USERPROFILE) || '~/.slack/bin' }}
key: slack-cli-${{ runner.os }}-${{ runner.arch }}-${{ inputs.cli-version }}

- name: Add Slack CLI to PATH (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: echo "$HOME/.slack/bin" >> "$GITHUB_PATH"

- name: Add Slack CLI to PATH (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\.slack\bin"
Comment on lines +51 to +59
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👾 question: Are these steps needed just if the cache was found? Unsure if the installation script has similar effects or if this could be skipped...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes seems like I would need to move the action to the root level so slack-github-action/cli/action.yml. Instead of having it under .github/resources/.actions


- name: Install Slack CLI (Linux/macOS)
if:
(runner.os == 'Linux' || runner.os == 'macOS') &&
(steps.cache-cli.outputs.cache-hit != 'true')
shell: bash
run: |
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s -- -v ${{ inputs.cli_version }}

- name: Install Slack CLI (Windows)
if:
runner.os == 'Windows' &&
(steps.cache-cli.outputs.cache-hit != 'true')
shell: pwsh
run: |
irm https://downloads.slack-edge.com/slack-cli/install-windows-dev.ps1 | iex -- -v ${{ inputs.cli_version }}

- name: Run Slack CLI Command (Linux/macOS)
if: runner.os != 'Windows'
id: run-slack-cli-command
shell: bash
env:
SLACK_SERVICE_TOKEN: $SLACK_SERVICE_TOKEN
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🪬 suggestion: We might prefer to use an explicit token input of this workflow instead of checking environment variables

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if I misunderstand, but wouldn't the user need to repeatedly put their token as an input? Or is it still saved in secrets so they don't need to regularly retrieve it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ewanek1 You're right that the token input would be more verbose... But I think this makes workflows more clear when different tokens are needed in separate steps! 👾

I'm curious if we can fallback to environment variables if a token isn't provided in inputs but the order of which token to use, if app and bot tokens are options, might be confusing for other techniques too.

Also, I also confirmed that a token provided by flag isn't saved to file by the CLI to avoid later unexpected happenings with a service token, so this might be similar to current behavior as well?

VERBOSE: ${{ inputs.verbose }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⌛ question: Is this used as a variable or can we also remove it?

Suggested change
VERBOSE: ${{ inputs.verbose }}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this I never used this and it can be removed 😄

run: |
cmd="slack --skip-update ${{ inputs.command }}"
if [ "${{ inputs.verbose }}" == "true" ]; then
cmd="$cmd --verbose"
fi
cmd="$cmd --skip-update"

output=$(eval $cmd 2>&1)
exit_code=$?

echo "Command output: $output"
echo "Exit code: $exit_code"

Comment on lines +94 to +96
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
echo "Command output: $output"
echo "Exit code: $exit_code"

🪓 thought: If these are duplicating outputs it might be alright to remove?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check if the exit code is necessary! I believe Actions resurfaces the error anyways.

echo "ok=$([ $exit_code -eq 0 ] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
echo "exit_code=$exit_code" >> $GITHUB_OUTPUT
echo "command_executed=slack ${{ inputs.command }} --skip-update" >> $GITHUB_OUTPUT

echo "output<<EOF" >> $GITHUB_OUTPUT
echo "$output" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Run Slack CLI Command (Windows)
if: runner.os == 'Windows'
id: run-slack-cli-command-windows
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍃 question: Do the outputs from this step also map to the outputs of the workflow? I notice a different id is used here and was not sure how these are mapping at this time...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an oversight thank you!!

shell: pwsh
env:
SLACK_SERVICE_TOKEN: $SLACK_SERVICE_TOKEN
VERBOSE: ${{ inputs.verbose }}
run: |
$cmd = "slack ${{ inputs.command }}"
if ("${{ inputs.verbose }}" -eq "true") { $cmd += " --verbose" }
$cmd += " --skip-update"

$output = & $cmd 2>&1
$exit_code = $LASTEXITCODE

Write-Host "Command output: $output"
Write-Host "Exit code: $exit_code"

"ok=$($exit_code -eq 0)" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"exit_code=$exit_code" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"command_executed=$cmd" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append

"output<<EOF" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
$output | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"EOF" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append

66 changes: 0 additions & 66 deletions .github/resources/.actions/slack-cli-runner/action.yml

This file was deleted.

161 changes: 161 additions & 0 deletions .github/workflows/cli-runner-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: Slack CLI Runner Tests

on:
pull_request:

jobs:
test-all:
runs-on: ubuntu-latest
steps:
- name: Checkout the current code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Run slack version
id: version
uses: ./.github/resources/.actions/cli-runner
with:
command: "version"
Comment on lines +13 to +17
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧪 suggestion: It might be interesting to run this test across multiple runners - ubuntu, mac, and windows?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

cli-version: "3.6.1"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Debug outputs
run: |
echo "output: '${{ steps.version.outputs.output }}'"
echo "ok: '${{ steps.version.outputs.ok }}'"
echo "command executed: '${{ steps.version.outputs.command_executed }}'"

- name: Verify CLI version
if: steps.version.outputs.ok != 'true'
run: |
echo "CLI version command failure"
echo "output: ${{ steps.version.outputs.output }}"
exit 1

- name: Empty command
id: empty-command
uses: ./.github/resources/.actions/cli-runner
with:
command: ""
cli-version: "3.6.1"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Command with whitespace
id: command-with-whitespace
uses: ./.github/resources/.actions/cli-runner
with:
command: " version"
cli-version: "3.6.1"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Long command with flags
id: long-command
uses: ./.github/resources/.actions/cli-runner
with:
command: 'doctor --help --experiment string'
cli-version: "3.6.1"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Ensure empty command works
if: steps.empty-command.outputs.ok != 'true'
run: |
echo "Empty command failure"
echo "ok: '${{ steps.empty-command.outputs.ok }}'"
echo "output: '${{ steps.empty-command.outputs.output }}'"
exit 1

- name: Ensure command with whitespace
if: steps.command-with-whitespace.outputs.ok != 'true'
run: |
echo "Command with whitespace failure"
echo "ok: '${{ steps.command-with-whitespace.outputs.ok }}'"
echo "output: '${{ steps.command-with-whitespace.outputs.output }}'"
exit 1

- name: Ensure long command works
if: steps.long-command.outputs.ok != 'true'
run: |
echo "Long command failure"
echo "ok: '${{ steps.long-command.outputs.ok }}'"
echo "output: '${{ steps.long-command.outputs.output }}'"
exit 1

- name: Run with verbose
id: with-verbose
uses: ./.github/resources/.actions/cli-runner
with:
command: "help"
cli-version: "3.6.1"
verbose: "true"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Ensure verbose flag worked
if: steps.with-verbose.outputs.ok != 'true'
run: |
echo "Verbose flag failure"
echo "ok: '${{ steps.with-verbose.outputs.ok }}'"
echo "output: '${{ steps.with-verbose.outputs.output }}'"
exit 1

- name: First run (install if missing)
id: no-cache
uses: ./.github/resources/.actions/cli-runner
with:
command: "version"
cli-version: "3.6.1"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Second run (cache hit)
id: cache-hit
uses: ./.github/resources/.actions/cli-runner
with:
command: "version"
cli-version: "3.6.1"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

- name: Ensure cache worked
if: github.run_attempt > 1 && steps.cache-hit.outputs.ok != 'true'
run: |
echo "cache failure"
exit 1

- name: Run with invalid command
id: invalid-command
continue-on-error: true
uses: ./.github/resources/.actions/cli-runner
with:
command: "invalid-command"
cli-version: "3.6.1"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Expect failure
if: steps.invalid-command.outputs.ok == 'true'
run: |
echo "Expected failure with invalid command"
echo "output: '${{ steps.invalid-command.outputs.output }}'"
echo "ok: '${{ steps.invalid-command.outputs.ok }}'"
exit 1

- name: Test specific version
id: specific-version
uses: ./.github/resources/.actions/cli-runner
with:
command: "version"
cli-version: "3.5.0"
env:
SLACK_SERVICE_TOKEN: ${{ secrets.SLACK_SERVICE_TOKEN }}

- name: Ensure specific version
if: ${{ !contains(steps.specific-version.outputs.output, '3.5.0') }}
run: |
echo "Specific version failure"
echo "output: '${{ steps.specific-version.outputs.output }}'"
exit 1
Loading
Loading