diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 6df1377c..c9921fce 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: @@ -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,15 +243,36 @@ 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 }} - - name: "chore(health): check up on recent changes to the health score" - uses: slackapi/slack-health-score@d58a419f15cdaff97e9aa7f09f95772830ab66f7 # v0.1.1 + 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: + persist-credentials: false + ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.sha }} + + - 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: - 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 63532b20..54d5ec10 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -38,6 +38,9 @@ jobs: uses: teunmooij/github-versioned-release@3edf649c6e5e5e976d43f2584b15bdc8b4c8f0df # v1.2.1 with: template: javascript-action + include: | + dist/**/* + cli/**/* env: GITHUB_TOKEN: ${{ github.token }} diff --git a/cli/action.yml b/cli/action.yml new file mode 100644 index 00000000..3af30219 --- /dev/null +++ b/cli/action.yml @@ -0,0 +1,146 @@ +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-unix.outputs.ok || steps.slack-cli-windows.outputs.ok }} + response: + description: "The standard output from the CLI command." + 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-unix.outputs.time || steps.slack-cli-windows.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 "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Cache Slack CLI + if: steps.slack-cli-check.outputs.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 + 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 + 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 + if: >- + steps.slack-cli-check.outputs.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 + if: >- + steps.slack-cli-check.outputs.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 + if: runner.os != 'Windows' + id: slack-cli-unix + 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 | tee /dev/stderr) + 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 + + - name: Run Slack CLI command + if: runner.os == 'Windows' + id: slack-cli-windows + shell: pwsh + env: + SLACK_COMMAND: ${{ inputs.command }} + SLACK_TOKEN: ${{ inputs.token }} + run: | + $cliArgs = "$env:SLACK_COMMAND --skip-update" + if ($env:SLACK_TOKEN) { + $cliArgs = "$cliArgs --token $env:SLACK_TOKEN" + } + + $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 + + "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 + }