Skip to content

Commit fb269f1

Browse files
authored
fix: venv usage (#314)
* use combo of --project and --directory * conditionally show uv debug output dependent on ACTIONS_STEP_DEBUG env var or `inputs.verbosity` * rewrote most steps at this point * conditionally add ~/.local/bin to PATH (temporarily) * document required tools for each platform * remove warning in README
1 parent d7155ea commit fb269f1

File tree

2 files changed

+190
-58
lines changed

2 files changed

+190
-58
lines changed

README.md

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,6 @@ to collect feedback provided in the form of
3333
workflow [`step-summary`][step-summary], and Pull Request reviews (with
3434
[`tidy-review`][tidy-review] or [`format-review`][format-review]).
3535

36-
> [!WARNING]
37-
> We only support Linux runners using a Debian-based Linux OS (like Ubuntu and many others).
38-
>
39-
> MacOS and Windows runners are supported as well.
40-
4136
## Usage
4237

4338
Create a new GitHub Actions workflow in your project, e.g. at [.github/workflows/cpp-linter.yml](https://github.com/cpp-linter/cpp-linter-action/blob/main/.github/workflows/cpp-linter.yml)
@@ -158,8 +153,57 @@ Example
158153

159154
To provide feedback (requesting a feature or reporting a bug) please post to [issues](https://github.com/cpp-linter/cpp-linter-action/issues).
160155

156+
## Required tools installed
157+
158+
As of v2.16.0, this action uses
159+
160+
- [nushell] for cross-platform compatible scripting
161+
- [uv] for driving a Python virtual environment
162+
163+
This action installs [nushell] and [uv] automatically.
164+
Only [nushell] is added to the PATH environment variable.
165+
[uv], and any standalone Python distribution it downloads, are not added to the PATH environment variable.
166+
167+
### On Linux runners
168+
169+
We only support Linux runners using a Debian-based Linux OS (like Ubuntu and many others).
170+
This is because we first try to use the `apt` package manager to install clang tools.
171+
172+
Linux workflows that use a specific [`container`][gh-container-syntax] should ensure that
173+
the following are installed:
174+
175+
- GLIBC (v2.32 or later)
176+
- `wget` or `curl`
177+
- `lsb-release` (required by LLVM-provided install script)
178+
- `software-properties-common` (required by LLVM-provided install script)
179+
- `gnupg` (required by LLVM-provided install script)
180+
181+
```shell
182+
apt-get update
183+
apt-get install -y libc6 wget lsb-release software-properties-common gnupg
184+
```
185+
186+
Otherwise, [nushell] and/or the LLVM-provided bash script will fail to run.
187+
188+
### On macOS runners
189+
190+
The specified `version` of `clang-format` and `clang-tidy` is installed via Homebrew.
191+
Failing that, we attempt to use static binaries that we built ourselves;
192+
see [cpp-linter/clang-tools-pip] and [cpp-linter/clang-tools-static-binaries] projects for more detail.
193+
194+
### On Windows runners
195+
196+
For Windows runners, we only use clang tools built as static binaries.
197+
See [cpp-linter/clang-tools-pip] and [cpp-linter/clang-tools-static-binaries] projects for more detail.
198+
161199
## License
162200

163201
The scripts and documentation in this project are released under the [MIT License](https://github.com/cpp-linter/cpp-linter-action/blob/main/LICENSE)
164202

203+
[nushell]: https://www.nushell.sh/
204+
[uv]: https://docs.astral.sh/uv/
205+
[cpp-linter/clang-tools-pip]: https://github.com/cpp-linter/clang-tools-pip
206+
[cpp-linter/clang-tools-static-binaries]: https://github.com/cpp-linter/clang-tools-static-binaries
207+
[gh-container-syntax]: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idcontainer
208+
165209
<!--README-end-->

action.yml

Lines changed: 141 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,13 @@ inputs:
217217
required: false
218218
default: 0
219219
cache-enable:
220-
description: enable caching of cpp-linter dependencies
220+
description: |-
221+
Controls the caching of cpp-linter dependencies.
222+
The installed `clang-format` and `clang-tidy` tools are not cached.
223+
224+
By default, this is enabled.
225+
Any cached assets are kept within the path to this action's source
226+
(not in the runner's workspace or temp directory).
221227
required: false
222228
default: true
223229
outputs:
@@ -233,21 +239,6 @@ outputs:
233239
runs:
234240
using: "composite"
235241
steps:
236-
- name: Install Linux clang dependencies
237-
if: runner.os == 'Linux'
238-
shell: bash
239-
run: |
240-
sudo apt-get update
241-
# First try installing from default Ubuntu repositories before trying LLVM script
242-
if ! sudo apt-get install -y clang-format-${{ inputs.version }} clang-tidy-${{ inputs.version }}; then
243-
# This LLVM script will add the relevant LLVM PPA: https://apt.llvm.org/
244-
wget https://apt.llvm.org/llvm.sh -O ${GITHUB_ACTION_PATH%/}/llvm_install.sh
245-
chmod +x ${GITHUB_ACTION_PATH%/}/llvm_install.sh
246-
if sudo ${GITHUB_ACTION_PATH%/}/llvm_install.sh ${{ inputs.version }}; then
247-
sudo apt-get install -y clang-format-${{ inputs.version }} clang-tidy-${{ inputs.version }}
248-
fi
249-
fi
250-
251242
- name: Setup nu shell
252243
# I'm done writing everything twice (in bash and powershell)
253244
# With nu shell, we use the same shell/script for all platforms
@@ -279,75 +270,172 @@ runs:
279270
path: ${{ runner.temp }}/cpp-linter-action-cache
280271
key: cpp-linter-action_${{ runner.os }}_${{ steps.compute-cache-key.outputs.key }}
281272

273+
- name: Install Linux clang dependencies
274+
if: runner.os == 'Linux'
275+
shell: nu {0}
276+
run: |
277+
let action_path = $env.GITHUB_ACTION_PATH | path expand
278+
let apt_install_args = [
279+
install -y clang-format-${{ inputs.version }} clang-tidy-${{ inputs.version }}
280+
]
281+
let has_sudo = not ((which 'sudo') | is-empty)
282+
283+
# First try installing from default Ubuntu repositories before trying LLVM script
284+
let are_tools_present = (
285+
if $has_sudo {
286+
^sudo apt-get update
287+
^sudo apt-get ...$apt_install_args
288+
} else {
289+
^apt-get update
290+
^apt-get ...$apt_install_args
291+
}
292+
) | complete | $in.exit_code == 0
293+
if (not $are_tools_present) {
294+
# This LLVM script will add the relevant LLVM PPA: https://apt.llvm.org/
295+
(
296+
http get --raw --redirect-mode follow https://apt.llvm.org/llvm.sh
297+
| save $"($action_path)/llvm_install.sh"
298+
)
299+
^chmod +x $"($action_path)/llvm_install.sh"
300+
301+
let llvm_installer_result = (
302+
if $has_sudo {
303+
^sudo $"($action_path)/llvm_install.sh" ${{ inputs.version }}
304+
} else {
305+
^bash $"($action_path)/llvm_install.sh" ${{ inputs.version }}
306+
}
307+
) | complete
308+
print $llvm_installer_result
309+
310+
if ($llvm_installer_result.exit_code == 0) {
311+
let result = (
312+
if $has_sudo {
313+
^sudo apt-get ...$apt_install_args
314+
} else {
315+
^apt-get ...$apt_install_args
316+
}
317+
) | complete
318+
print $result
319+
}
320+
}
321+
282322
- name: Install MacOS clang dependencies
283323
if: runner.os == 'macOS'
284-
shell: bash
285-
continue-on-error: true
286-
run: |
287-
brew install llvm@${{ inputs.version }}
288-
ln -s "$(brew --prefix llvm@${{ inputs.version }})/bin/clang-format" "/usr/local/bin/clang-format-${{ inputs.version }}"
289-
ln -s "$(brew --prefix llvm@${{ inputs.version }})/bin/clang-tidy" "/usr/local/bin/clang-tidy-${{ inputs.version }}"
324+
shell: nu {0}
325+
run: |-
326+
let brew_install_arg = 'llvm@${{ inputs.version }}'
327+
let result = (^brew install $brew_install_arg) | complete
328+
print $result
329+
if ($result.exit_code == 0) {
330+
let brew_prefix = ^brew --prefix $brew_install_arg
331+
^ln -s $"($brew_prefix)/bin/clang-format" "/usr/local/bin/clang-format-${{ inputs.version }}"
332+
^ln -s $"($brew_prefix)/bin/clang-tidy" "/usr/local/bin/clang-tidy-${{ inputs.version }}"
333+
}
290334
291335
- name: Setup cpp-linter dependencies
292336
shell: nu {0}
293337
env:
294338
UV_NO_MODIFY_PATH: 1
295-
UV_VERSION: '0.8.9'
339+
UV_VERSION: '0.8.11'
296340
run: |-
297341
let action_path = $env.GITHUB_ACTION_PATH | path expand
298342
$env.UV_INSTALL_DIR = $action_path | path join 'bin'
299-
$env.UV_PROJECT_ENVIRONMENT = $action_path | path join '.venv'
300343
301344
$env.UV_CACHE_DIR = $env.RUNNER_TEMP | path join 'cpp-linter-action-cache'
302345
if (not ($env.UV_CACHE_DIR | path exists)) {
303-
mkdir $env.UV_CACHE_DIR
346+
mkdir $env.UV_CACHE_DIR
304347
}
305348
306349
print $"\n(ansi purple)Installing uv version ($env.UV_VERSION)(ansi reset)"
307-
if ((sys host | get 'name') == 'Windows') {
308-
^powershell -ExecutionPolicy ByPass -c $"irm https://astral.sh/uv/($env.UV_VERSION)/install.ps1 | iex"
350+
let is_windows = (sys host | get 'name') == 'Windows'
351+
let uv_installer_url = if $is_windows {
352+
$"https://astral.sh/uv/($env.UV_VERSION)/install.ps1"
353+
} else {
354+
$"https://astral.sh/uv/($env.UV_VERSION)/install.sh"
355+
}
356+
let installer = http get --raw --redirect-mode follow $uv_installer_url
357+
if $is_windows {
358+
^powershell -ExecutionPolicy ByPass $installer
309359
} else {
310-
^curl -LsSf $"https://astral.sh/uv/($env.UV_VERSION)/install.sh" | sh
360+
$installer | ^sh
311361
}
312362
363+
let gh_action_debug = $env | get --optional 'ACTIONS_STEP_DEBUG'
364+
let action_verbosity = '${{ inputs.verbosity }}' == 'debug'
365+
let verbosity = (
366+
$action_verbosity
367+
or ($gh_action_debug == true)
368+
or ($gh_action_debug == 'true')
369+
)
370+
313371
print $"\n(ansi purple)Installing workflow dependencies(ansi reset)"
314-
^$'($env.UV_INSTALL_DIR)/uv' sync --directory $action_path --group action
372+
mut uv_args = [sync --project $action_path --group action]
373+
if $verbosity {
374+
$uv_args = $uv_args | append '-v'
375+
}
376+
^$'($env.UV_INSTALL_DIR)/uv' ...$uv_args
315377
316378
print $"\n(ansi purple)Ensuring clang-format and clang-tidy ${{ inputs.version }} are present(ansi reset)"
317-
^$'($env.UV_INSTALL_DIR)/uv' run clang-tools -i ${{ inputs.version }} -b
379+
let cmd = [clang-tools -i ${{ inputs.version }} -b]
380+
$uv_args = [run --no-sync --project $action_path --directory (pwd)]
381+
if $verbosity {
382+
$uv_args = $uv_args | append '-v'
383+
}
384+
^$'($env.UV_INSTALL_DIR)/uv' ...$uv_args ...$cmd
318385
319386
- name: Run cpp-linter
320387
id: cpp-linter
321388
shell: nu {0}
322389
run: |-
323390
let action_path = $env.GITHUB_ACTION_PATH | path expand
324391
$env.UV_INSTALL_DIR = $action_path | path join 'bin'
325-
$env.UV_PROJECT_ENVIRONMENT = $action_path | path join '.venv'
326392
$env.UV_CACHE_DIR = $env.RUNNER_TEMP | path join 'cpp-linter-action-cache'
327393
328394
let args = [
329-
--style="${{ inputs.style }}"
330-
--extensions=${{ inputs.extensions }}
331-
--tidy-checks="${{ inputs.tidy-checks }}"
332-
--repo-root=${{ inputs.repo-root }}
333-
--version=${{ inputs.version }}
334-
--verbosity=${{ inputs.verbosity }}
335-
--lines-changed-only=${{ inputs.lines-changed-only }}
336-
--files-changed-only=${{ inputs.files-changed-only }}
337-
--thread-comments=${{ inputs.thread-comments }}
338-
--no-lgtm=${{ inputs.no-lgtm }}
339-
--step-summary=${{ inputs.step-summary }}
340-
--ignore="${{ inputs.ignore }}"
341-
--ignore-tidy="${{ inputs.ignore-tidy }}"
342-
--ignore-format="${{ inputs.ignore-format }}"
343-
--database=${{ inputs.database }}
344-
--file-annotations=${{ inputs.file-annotations }}
345-
--extra-arg="${{ inputs.extra-args }}"
346-
--tidy-review="${{ inputs.tidy-review }}"
347-
--format-review="${{ inputs.format-review }}"
348-
--passive-reviews="${{ inputs.passive-reviews }}"
349-
--jobs=${{ inputs.jobs }}
395+
--style="${{ inputs.style }}"
396+
--extensions=${{ inputs.extensions }}
397+
--tidy-checks="${{ inputs.tidy-checks }}"
398+
--repo-root=${{ inputs.repo-root }}
399+
--version=${{ inputs.version }}
400+
--verbosity=${{ inputs.verbosity }}
401+
--lines-changed-only=${{ inputs.lines-changed-only }}
402+
--files-changed-only=${{ inputs.files-changed-only }}
403+
--thread-comments=${{ inputs.thread-comments }}
404+
--no-lgtm=${{ inputs.no-lgtm }}
405+
--step-summary=${{ inputs.step-summary }}
406+
--ignore="${{ inputs.ignore }}"
407+
--ignore-tidy="${{ inputs.ignore-tidy }}"
408+
--ignore-format="${{ inputs.ignore-format }}"
409+
--database=${{ inputs.database }}
410+
--file-annotations=${{ inputs.file-annotations }}
411+
--extra-arg="${{ inputs.extra-args }}"
412+
--tidy-review="${{ inputs.tidy-review }}"
413+
--format-review="${{ inputs.format-review }}"
414+
--passive-reviews="${{ inputs.passive-reviews }}"
415+
--jobs=${{ inputs.jobs }}
350416
]
417+
mut uv_args = [run --no-sync --project $action_path --directory (pwd)]
418+
419+
let gh_action_debug = $env | get --optional 'ACTIONS_STEP_DEBUG'
420+
let action_verbosity = '${{ inputs.verbosity }}' == 'debug'
421+
let verbosity = (
422+
$action_verbosity
423+
or ($gh_action_debug == true)
424+
or ($gh_action_debug == 'true')
425+
)
426+
if $verbosity {
427+
$uv_args = $uv_args | append '-v'
428+
}
429+
430+
let local_bin = '~/.local/bin' | path expand
431+
if (
432+
('${{ runner.os }}' == 'Linux')
433+
and ($local_bin | path exists)
434+
and (not ($env.PATH | any {$in == $local_bin}))
435+
) {
436+
# add ~/.local/bin to PATH (temporarily)
437+
$env.PATH = $env.PATH | append $local_bin
438+
}
351439
352440
print $"\n(ansi purple)Running cpp-linter(ansi reset)"
353-
^$'($env.UV_INSTALL_DIR)/uv' run cpp-linter ...$args
441+
^$'($env.UV_INSTALL_DIR)/uv' ...$uv_args cpp-linter ...$args

0 commit comments

Comments
 (0)