Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Golang a first class language #2651

Merged
merged 1 commit into from Jan 13, 2023

Conversation

taoufik07
Copy link
Contributor

@taoufik07 taoufik07 commented Dec 23, 2022

Following #2672
Closes #2649

@taoufik07 taoufik07 force-pushed the golang_playground branch 13 times, most recently from d251ed6 to 9d155c4 Compare December 29, 2022 03:42
@taoufik07 taoufik07 marked this pull request as ready for review December 29, 2022 03:45
Comment on lines 285 to 289


def test_get_remote_url(tmpdir):
git.init_repo(str(tmpdir), remote='dne')
assert git.get_remote_url(tmpdir) == 'dne'
Copy link
Member

Choose a reason for hiding this comment

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

if this function is dead it should just be removed -- originally this was building a GOPATH-like directory -- if that's not needed any more then there's a bunch of stuff that can be cleaned up I think ?

Copy link
Contributor Author

@taoufik07 taoufik07 Dec 30, 2022

Choose a reason for hiding this comment

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

Only get_remote_url is left I think. Done!

Comment on lines 59 to 69
def _get_arch() -> str: # pragma: no cover
arch = platform.machine().lower()
if arch in ('x86_64',):
return 'amd64'
if arch in ('i386',):
return '386'
if arch in ('armv6l', 'armv7l'):
return 'armv6l'
if arch in ('arm64', 'aarch64', 'armv8'):
return 'arm64'
return arch
Copy link
Member

Choose a reason for hiding this comment

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

this can just be a dict

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done... I think

Comment on lines 42 to 73
if language_version == 'system':
return (
('PATH', (os.path.join(venv, 'bin'), os.pathsep, Var('PATH'))),
)
Copy link
Member

Choose a reason for hiding this comment

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

this is potentially going to install stuff outside of pre-commit's management isn't it?

Copy link
Contributor Author

@taoufik07 taoufik07 Dec 30, 2022

Choose a reason for hiding this comment

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

No, since I've set a GOPATH later in the code for system which now I think can be moved to here I've moved here.

if helpers.exe_exists('go'):
return 'system'
else:
return '1.19.4' # C.DEFAULT
Copy link
Member

Choose a reason for hiding this comment

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

this doesn't seem right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was wondering if:

  • I should return directly a default version X.Y.Z?
  • or I should return C.DEFAULT and translate it somewhere in the code to a default version X.Y.Z?

Copy link
Member

Choose a reason for hiding this comment

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

yeah this should just be 'default' -- we absolutely cannot have a specific version hardcoded because I do not want to deal with spammy PRs bumping it all the time

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah this should just be 'default' -- we absolutely cannot have a specific version hardcoded because I do not want to deal with spammy PRs bumping it all the time

and translate it somewhere in the code to a default version X.Y.Z? (this won't shoo spammy PRs, and I don't think Go provides an alias for stable or latest version)

Copy link
Member

Choose a reason for hiding this comment

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

yeah I can't accept that -- you'll have to figure some way to determine the latest available version

Copy link
Contributor Author

@taoufik07 taoufik07 Dec 30, 2022

Choose a reason for hiding this comment

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

Looks good now? -- The only way I could think of is to fetch the list of versions

Comment on lines 94 to 98
shutil.unpack_archive(
tmp_file.name,
dest,
format='zip' if sys.platform == 'win32' else 'gztar',
)
Copy link
Member

Choose a reason for hiding this comment

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

hmm I thought the whole point of unpack_archive was that it's automatic?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's what I thought at first, but when not provided, the format is only inferred using the filename extension.

Copy link
Member

Choose a reason for hiding this comment

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

should be easy to preserve the original extension right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only way I can think of is to add it as a suffix to the named temp file (basically move the whole ternary there)

Copy link
Member

Choose a reason for hiding this comment

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

the url has the extension, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've suffixed the whole name, might be useful for someone someday inspecting the temp dir :D

@taoufik07 taoufik07 force-pushed the golang_playground branch 2 times, most recently from d128ccd to 37edd59 Compare December 30, 2022 15:48
@taoufik07
Copy link
Contributor Author

@asottile Could you please approve me running workflows? Congrats on the migration btw 🎉

@asottile
Copy link
Member

asottile commented Jan 1, 2023

if we don't need to build special GOPATH directories any more -- can you split that out to a separate PR so this is more straightforward?

@taoufik07 taoufik07 force-pushed the golang_playground branch 2 times, most recently from a1b4a06 to efe2ca1 Compare January 2, 2023 21:16
@taoufik07 taoufik07 force-pushed the golang_playground branch 3 times, most recently from df6239b to ecd44ab Compare January 3, 2023 02:44
Comment on lines 45 to 83
return (
('GOROOT', os.path.join(venv, '.go')),
(
'PATH', (
os.path.join(venv, 'bin'), os.pathsep,
os.path.join(venv, '.go', 'bin'), os.pathsep, Var('PATH'),
),
),
)
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this is needed at all? the extra go installation is only needed during build right?

Copy link
Contributor Author

@taoufik07 taoufik07 Jan 5, 2023

Choose a reason for hiding this comment

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

All I can think of are some builtin commands that are useful to hookify (😆) and require access to a Go instance e.g. gofmt, go generate, go mod ... , go vet.

The question now is; do we want to give each an independent env? or expect/require the user to have a system installation? what if he uses a language version manager -- will it be cumbersome to activate?

If no to independent env, then we can yeet it.

Copy link
Member

Choose a reason for hiding this comment

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

I've been thinking about this a bit -- and it probably benefits pre-commit to store languages separate from the environments maybe? that way they can all be shared instead of having N copies of go -- I'm not sure what it would look like yet (probably another entry in the store database?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had the same thought when I started working on this PR. It will mainly benefit the end user, thus pre-commit, especially when dealing with e.g. large sized languages in this case Go. Speaking of which, Go is a good candidate in this case, as it offers a simple way of achieving what we're looking for. I'm not sure if other languages offer the same experience -- I think that we can leverage virtualenv and rbenv for python and ruby -- if it's too complex or not worth it, we can have both structures coexist, maybe.

As a start, I think a very simple solution would be to pass a computed path to a language dir, install the language there, and make available a helper function that returns the language binary, this won't require a new database entry, but again this is a very simple solution based on my little knowledge of the tool internals.

Copy link
Member

Choose a reason for hiding this comment

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

yeah I think I'll design something separate from this -- I'm imaginging any "first class" language will support this (so ruby, js, rust, and now go) -- and any second class language (python) will continue doing nothing. I'll need to think of the right api for this though (and hopefully something that makes it ~easy for pre-commit.ci to use as well)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh! python is a second class language, I forgot that, knowing that I've read it in the CONTRIBUTING docs

gopath = env_dir
env = dict(os.environ, GOPATH=gopath)
env.pop('GOBIN', None)
with in_env(prefix, version):
Copy link
Member

Choose a reason for hiding this comment

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

I had factored this out in your other patch -- this shouldn't be needed here I think

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mainly because both hook install and run steps have shared env vars since I kept go accessible.

I've refactored it now after fixing #2677.

Comment on lines 1 to 5
module golang-hello-world

go 1.18

require github.com/BurntSushi/toml v1.1.0
Copy link
Member

Choose a reason for hiding this comment

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

you can probably take the existing local go test and set language_version -- that'd be simpler than a whole separate repo

Copy link
Contributor Author

@taoufik07 taoufik07 Jan 8, 2023

Choose a reason for hiding this comment

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

done, now we only have one repo!

Comment on lines 383 to 408
def test_golang_hook(tempdir_factory, store):
@pytest.fixture
def _golang_lru_cache_clear():
golang.get_default_version.cache_clear()
yield
golang.get_default_version.cache_clear()
Copy link
Member

Choose a reason for hiding this comment

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

this shouldn't be needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have added two tests, where I test default version resolving to system and to fetching latest version, so I needed to clear the get_default_version cache. Probably might be a stretch since we're already testing get_default_version, let me know if you think I should get rid of the tests.

Copy link
Member

Choose a reason for hiding this comment

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

you can set the language version directly for these tests -- you can pass in both default and system

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done!

@taoufik07 taoufik07 force-pushed the golang_playground branch 3 times, most recently from ca2ec9d to dac33b0 Compare January 8, 2023 17:25
)


def _get_arch() -> str: # pragma: no cover
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this needs no cover any more

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

if version != C.DEFAULT:
return version
resp = urllib.request.urlopen('https://go.dev/dl/?mode=json')
return json.loads(resp.read())[0]['version'].lstrip('go')
Copy link
Member

Choose a reason for hiding this comment

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

json.load(resp) is ~slightly more efficient -- lstrip isn't quite right here -- you probably want removeprefix but that's new in python 3.9

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 77 to 78
os_name = platform.system().lower()
ext = 'zip' if os_name == 'windows' else 'tar.gz'
Copy link
Member

Choose a reason for hiding this comment

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

the rest of the checks in the codebase use sys.platform -- just to be consistent let's do that here as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

try:
url = _get_url(version)
resp = urllib.request.urlopen(url)
except urllib.error.HTTPError as exec: # pragma: no cover
Copy link
Member

Choose a reason for hiding this comment

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

exec is a bit of a weird name here -- if it's short for exception idk where the second e comes from 😆 -- I would call it just e or exc personally

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Muscle memory typo probably 😅 -- done!

raise
else:
with tempfile.NamedTemporaryFile(
delete=False,
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is right? this leaves the archive around after

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On windows, we can't open the named temp file a second time without first closing it, hence the delete=False. I've delegated the cleanup to the OS.

Copy link
Member

Choose a reason for hiding this comment

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

the store database has the same problem -- check out what's done there.

some people are ok delegating temp cleanup to the OS, I am not :P

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Today I learned that Windows doesn't automatically cleanup the temp dir. I've made a little context manager to perform the cleanup.

with envcontext(get_env_patch(envdir)):
def in_env(
prefix: Prefix,
language_version: str,
Copy link
Member

Choose a reason for hiding this comment

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

in a WIP branch I've standardized this function and with the name version: str (it'll also fit on one line) -- if you could do that here that'll save me a semantic conflict :D

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done!

if sys.platform == 'cygwin': # pragma: no cover
gopath = cmd_output('cygpath', '-w', env_dir)[1].strip()
else:
gopath = env_dir
gopath = os.path.join(env_dir)
Copy link
Member

Choose a reason for hiding this comment

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

os.path.join isn't doing anything here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 136 to 140
env['PATH'] = (
os.path.join(env_dir, '.go', 'bin') +
os.pathsep + os.environ['PATH']
)
Copy link
Member

Choose a reason for hiding this comment

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

I would do env['PATH'] = os.pathsep.join((os.path.join(env_dir, '.go', 'bin'), os.environ['PATH']))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done!

Comment on lines 44 to 45
resp = urllib.request.urlopen(golang._get_url(version))
assert resp.code == 200
Copy link
Member

Choose a reason for hiding this comment

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

this is going to be pretty slow -- not sure it improves the test -- maybe just assert that it looks like a version?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 383 to 408
def test_golang_hook(tempdir_factory, store):
@pytest.fixture
def _golang_lru_cache_clear():
golang.get_default_version.cache_clear()
yield
golang.get_default_version.cache_clear()
Copy link
Member

Choose a reason for hiding this comment

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

you can set the language version directly for these tests -- you can pass in both default and system

@taoufik07 taoufik07 force-pushed the golang_playground branch 2 times, most recently from 916cec3 to 523f2ae Compare January 9, 2023 00:01
Comment on lines 86 to 102
@contextlib.contextmanager
def _named_temp_file(
delete: bool = True, **kwargs: Any,
) -> Generator[tempfile._TemporaryFileWrapper[Any], None, None]:
"""On Windows, we can't open a named temp file a second time,
while it's still open.
- https://github.com/python/cpython/issues/58451
"""
f = tempfile.NamedTemporaryFile(**kwargs, delete=False)
try:
yield f
finally: # pragma: no cover
try:
if delete:
os.unlink(f.name)
except OSError:
pass
Copy link
Member

Choose a reason for hiding this comment

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

there's a different pattern in pre_commit/store.py -- also we shouldn't no cover here -- that should be reserved for things which aren't testable

Copy link
Member

Choose a reason for hiding this comment

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

also I don't think this is necessary -- you can seek(0) on the original temporary file without having to close and reopen it

Copy link
Contributor Author

@taoufik07 taoufik07 Jan 10, 2023

Choose a reason for hiding this comment

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

I'll give it a look -- the no cover was necessary due to a coverage bug on the finally and if delete nedbat/coveragepy#867

I'm not sure if seek(0) will do the trick -- shutil.unpack_archive only accepts the filename.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should be good now

Comment on lines 143 to 48
gopath = env_dir
if sys.platform == 'cygwin': # pragma: no cover
gopath = cmd_output('cygpath', '-w', env_dir)[1].strip()
else:
gopath = env_dir
Copy link
Member

Choose a reason for hiding this comment

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

the original code was better

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

def _test_hook_repo(
def _try_hook_repo(
Copy link
Member

Choose a reason for hiding this comment

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

this should just use the original function

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 419 to 434
def test_golang_default_to_version_hook(tempdir_factory, store):
with mock.patch.object(helpers, 'exe_exists') as exe_exists_mck:
with mock.patch.object(golang, '_infer_go_version') as _infer_go_mck:
exe_exists_mck.return_value = False
_infer_go_mck.return_value = '1.18.4'
_test_hook_repo(
tempdir_factory, store, 'golang_hooks_repo',
'golang-hook', [], b'hello world from go1.18.4\n',
config_kwargs={
'hooks': [{
'id': 'golang-hook',
'language_version': 'default',
}],
},
)
_infer_go_mck.assert_called_once_with(C.DEFAULT)
Copy link
Member

Choose a reason for hiding this comment

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

I don't think the mocks are useful here? can't this just make an assertion based on the real execution and output? this test is just a reimplementation of the implementation so it's not actually testing anything (same for the mock above as well)

Copy link
Contributor Author

@taoufik07 taoufik07 Jan 10, 2023

Choose a reason for hiding this comment

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

I think I'll remove the test as I'm not convinced by it -- I wanted to test that the program fetches a go version and run it, when no version is passed and no system binary is available -- having test_golang_versionned_hook and testing the helper functions is enough I think

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@taoufik07 taoufik07 force-pushed the golang_playground branch 2 times, most recently from 97af889 to d8841b5 Compare January 10, 2023 14:52
@asottile
Copy link
Member

I got rid of unpack_archive -- it's way simpler without it

Copy link
Member

@asottile asottile left a comment

Choose a reason for hiding this comment

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

@asottile asottile merged commit 87ab767 into pre-commit:main Jan 13, 2023
@taoufik07 taoufik07 deleted the golang_playground branch January 15, 2023 16:43
jaypikay pushed a commit to jaypikay/doxy that referenced this pull request Apr 27, 2023
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [pre-commit](https://github.com/pre-commit/pre-commit) | dev-dependencies | major | `^2.21.0` -> `^3.0.0` |

---

### Release Notes

<details>
<summary>pre-commit/pre-commit</summary>

### [`v3.2.2`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;322---2023-04-03)

[Compare Source](pre-commit/pre-commit@v3.2.1...v3.2.2)

\==================

##### Fixes

-   Fix support for swift >= 5.8.
    -   [#&#8203;2836](pre-commit/pre-commit#2836) PR by [@&#8203;edelabar](https://github.com/edelabar).
    -   [#&#8203;2835](pre-commit/pre-commit#2835) issue by [@&#8203;kgrobelny-intive](https://github.com/kgrobelny-intive).

### [`v3.2.1`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;321---2023-03-25)

[Compare Source](pre-commit/pre-commit@v3.2.0...v3.2.1)

\==================

##### Fixes

-   Fix `language_version` for `language: rust` without global `rustup`.
    -   [#&#8203;2823](pre-commit/pre-commit#2823) issue by [@&#8203;daschuer](https://github.com/daschuer).
    -   [#&#8203;2827](pre-commit/pre-commit#2827) PR by [@&#8203;asottile](https://github.com/asottile).

### [`v3.2.0`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;320---2023-03-17)

[Compare Source](pre-commit/pre-commit@v3.1.1...v3.2.0)

\==================

##### Features

-   Allow `pre-commit`, `pre-push`, and `pre-merge-commit` as `stages`.
    -   [#&#8203;2732](pre-commit/pre-commit#2732) issue by [@&#8203;asottile](https://github.com/asottile).
    -   [#&#8203;2808](pre-commit/pre-commit#2808) PR by [@&#8203;asottile](https://github.com/asottile).
-   Add `pre-rebase` hook support.
    -   [#&#8203;2582](pre-commit/pre-commit#2582) issue by [@&#8203;BrutalSimplicity](https://github.com/BrutalSimplicity).
    -   [#&#8203;2725](pre-commit/pre-commit#2725) PR by [@&#8203;mgaligniana](https://github.com/mgaligniana).

##### Fixes

-   Remove bulky cargo cache from `language: rust` installs.
    -   [#&#8203;2820](pre-commit/pre-commit#2820) PR by [@&#8203;asottile](https://github.com/asottile).

### [`v3.1.1`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;311---2023-02-27)

[Compare Source](pre-commit/pre-commit@v3.1.0...v3.1.1)

\==================

##### Fixes

-   Fix `rust` with `language_version` and a non-writable host `RUSTUP_HOME`.
    -   [pre-commit-ci/issues#&#8203;173](pre-commit-ci/issues#173) by [@&#8203;Swiftb0y](https://github.com/Swiftb0y).
    -   [#&#8203;2788](pre-commit/pre-commit#2788) by [@&#8203;asottile](https://github.com/asottile).

### [`v3.1.0`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;310---2023-02-22)

[Compare Source](pre-commit/pre-commit@v3.0.4...v3.1.0)

\==================

##### Fixes

-   Fix `dotnet` for `.sln`-based hooks for dotnet>=7.0.200.
    -   [#&#8203;2763](pre-commit/pre-commit#2763) PR by [@&#8203;m-rsha](https://github.com/m-rsha).
-   Prevent stashing when `diff` fails to execute.
    -   [#&#8203;2774](pre-commit/pre-commit#2774) PR by [@&#8203;asottile](https://github.com/asottile).
    -   [#&#8203;2773](pre-commit/pre-commit#2773) issue by [@&#8203;strubbly](https://github.com/strubbly).
-   Dependencies are no longer sorted in repository key.
    -   [#&#8203;2776](pre-commit/pre-commit#2776) PR by [@&#8203;asottile](https://github.com/asottile).

##### Updating

-   Deprecate `language: python_venv`.  Use `language: python` instead.
    -   [#&#8203;2746](pre-commit/pre-commit#2746) PR by [@&#8203;asottile](https://github.com/asottile).
    -   [#&#8203;2734](pre-commit/pre-commit#2734) issue by [@&#8203;asottile](https://github.com/asottile).

### [`v3.0.4`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;304---2023-02-03)

[Compare Source](pre-commit/pre-commit@v3.0.3...v3.0.4)

\==================

##### Fixes

-   Fix hook diff detection for files affected by `--textconv`.
    -   [#&#8203;2743](pre-commit/pre-commit#2743) PR by [@&#8203;adamchainz](https://github.com/adamchainz).
    -   [#&#8203;2743](pre-commit/pre-commit#2743) issue by [@&#8203;adamchainz](https://github.com/adamchainz).

### [`v3.0.3`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;303---2023-02-01)

[Compare Source](pre-commit/pre-commit@v3.0.2...v3.0.3)

\==================

##### Fixes

-   Revert "Prevent local `Gemfile` from interfering with hook execution.".
    -   [#&#8203;2739](pre-commit/pre-commit#2739) issue by [@&#8203;Roguelazer](https://github.com/Roguelazer).
    -   [#&#8203;2740](pre-commit/pre-commit#2740) PR by [@&#8203;asottile](https://github.com/asottile).

### [`v3.0.2`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;302---2023-01-29)

[Compare Source](pre-commit/pre-commit@v3.0.1...v3.0.2)

\==================

##### Fixes

-   Prevent local `Gemfile` from interfering with hook execution.
    -   [#&#8203;2727](pre-commit/pre-commit#2727) PR by [@&#8203;asottile](https://github.com/asottile).
-   Fix `language: r`, `repo: local` hooks
    -   [pre-commit-ci/issues#&#8203;107](pre-commit-ci/issues#107) by [@&#8203;lorenzwalthert](https://github.com/lorenzwalthert).
    -   [#&#8203;2728](pre-commit/pre-commit#2728) PR by [@&#8203;asottile](https://github.com/asottile).

### [`v3.0.1`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;301---2023-01-26)

[Compare Source](pre-commit/pre-commit@v3.0.0...v3.0.1)

\==================

##### Fixes

-   Ensure coursier hooks are available offline after install.
    -   [#&#8203;2723](pre-commit/pre-commit#2723) PR by [@&#8203;asottile](https://github.com/asottile).

### [`v3.0.0`](https://github.com/pre-commit/pre-commit/blob/HEAD/CHANGELOG.md#&#8203;300---2023-01-23)

[Compare Source](pre-commit/pre-commit@v2.21.0...v3.0.0)

\==================

##### Features

-   Make `language: golang` bootstrap `go` if not present.
    -   [#&#8203;2651](pre-commit/pre-commit#2651) PR by [@&#8203;taoufik07](https://github.com/taoufik07).
    -   [#&#8203;2649](pre-commit/pre-commit#2649) issue by [@&#8203;taoufik07](https://github.com/taoufik07).
-   `language: coursier` now supports `additional_dependencies` and `repo: local`
    -   [#&#8203;2702](pre-commit/pre-commit#2702) PR by [@&#8203;asottile](https://github.com/asottile).
-   Upgrade `ruby-build` to `20221225`.
    -   [#&#8203;2718](pre-commit/pre-commit#2718) PR by [@&#8203;jalessio](https://github.com/jalessio).

##### Fixes

-   Improve error message for invalid yaml for `pre-commit autoupdate`.
    -   [#&#8203;2686](pre-commit/pre-commit#2686) PR by [@&#8203;asottile](https://github.com/asottile).
    -   [#&#8203;2685](pre-commit/pre-commit#2685) issue by [@&#8203;CarstenGrohmann](https://github.com/CarstenGrohmann).
-   `repo: local` no longer provisions an empty `git` repo.
    -   [#&#8203;2699](pre-commit/pre-commit#2699) PR by [@&#8203;asottile](https://github.com/asottile).

##### Updating

-   Drop support for python<3.8
    -   [#&#8203;2655](pre-commit/pre-commit#2655) PR by [@&#8203;asottile](https://github.com/asottile).
-   Drop support for top-level list, use `pre-commit migrate-config` to update.
    -   [#&#8203;2656](pre-commit/pre-commit#2656) PR by [@&#8203;asottile](https://github.com/asottile).
-   Drop support for `sha` to specify revision, use `pre-commit migrate-config`
    to update.
    -   [#&#8203;2657](pre-commit/pre-commit#2657) PR by [@&#8203;asottile](https://github.com/asottile).
-   Remove `pre-commit-validate-config` and `pre-commit-validate-manifest`, use
    `pre-commit validate-config` and `pre-commit validate-manifest` instead.
    -   [#&#8203;2658](pre-commit/pre-commit#2658) PR by [@&#8203;asottile](https://github.com/asottile).
-   `language: golang` hooks must use `go.mod` to specify dependencies
    -   [#&#8203;2672](pre-commit/pre-commit#2672) PR by [@&#8203;taoufik07](https://github.com/taoufik07).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS42MS4wIiwidXBkYXRlZEluVmVyIjoiMzUuNjEuMCJ9-->

Co-authored-by: Renovate Bot <renovate@localhost.localdomain>
Reviewed-on: https://git.goatpr0n.de/public/doxy/pulls/2
Co-authored-by: renovate <renovate@noreply.localhost>
Co-committed-by: renovate <renovate@noreply.localhost>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Make Go a first class language
2 participants