diff --git a/.github/actions/setup-python-env/action.yml b/.github/actions/setup-python-env/action.yml
new file mode 100644
index 00000000..3f05ad82
--- /dev/null
+++ b/.github/actions/setup-python-env/action.yml
@@ -0,0 +1,20 @@
+name: Setup Python env
+description: Install Python & Hatch
+inputs:
+    python-version:
+      description: 'Version of Python to Install'
+      required: true
+      default: '3.9'
+runs:
+  using: "composite"
+  steps:
+  - name: "Set up Python ${{ inputs.python-version }}"
+    uses: actions/setup-python@v4
+    with:
+      python-version: "${{ inputs.python-version }}"
+
+  - name: Install Hatch
+    shell: bash
+    run: |
+      python -m pip install --user --upgrade pip
+      python -m pip install hatch
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 368ad408..aa8bdd91 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,9 +7,9 @@ on:
         type: choice
         description: Choose where to publish (test/prod)
         options:
-        - prod
-        - test
-        default: prod
+          - PypiProd
+          - PypiTest
+        default: PypiTest
 
 permissions: read-all
 
@@ -39,15 +39,11 @@ jobs:
         with:
           persist-credentials: false
 
-      - name: Set up Python 3.11
-        uses: actions/setup-python@v4
+      - name: "Set up Python & Hatch - 3.11"
+        uses: ./.github/actions/setup-python-env
         with:
           python-version: "3.11"
 
-      - name: Install hatch
-        run: python -m pip install hatch
-        shell: bash
-
       - name: Build artifacts
         run: hatch build
         shell: bash
@@ -58,3 +54,5 @@ jobs:
 
       - name: Publish artifacts to PyPI
         uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          repository-url: https://test.pypi.org/legacy/
diff --git a/Makefile b/Makefile
index 298b696d..dad020b0 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ lint:
 
 .PHONY: proto_types
 proto_types:  ## generates google protobuf python file from types.proto
-	protoc -I=./dbt/common/events --python_out=./dbt/common/events ./dbt/common/events/types.proto
+	protoc -I=./dbt_common/events --python_out=./dbt_common/events ./dbt_common/events/types.proto
 
 .PHONY: help
 help: ## Show this help message.
diff --git a/dbt_common/events/types_pb2.py b/dbt_common/events/types_pb2.py
index 3d7a33e3..babf7158 100644
--- a/dbt_common/events/types_pb2.py
+++ b/dbt_common/events/types_pb2.py
@@ -6,7 +6,6 @@
 from google.protobuf import descriptor_pool as _descriptor_pool
 from google.protobuf import symbol_database as _symbol_database
 from google.protobuf.internal import builder as _builder
-
 # @@protoc_insertion_point(imports)
 
 _sym_db = _symbol_database.Default()
@@ -15,58 +14,56 @@
 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
 
 
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
-    b'\n\x0btypes.proto\x12\x0bproto_types\x1a\x1fgoogle/protobuf/timestamp.proto"\x91\x02\n\tEventInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\x12\x0b\n\x03msg\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\t\x12\x15\n\rinvocation_id\x18\x05 \x01(\t\x12\x0b\n\x03pid\x18\x06 \x01(\x05\x12\x0e\n\x06thread\x18\x07 \x01(\t\x12&\n\x02ts\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x05\x65xtra\x18\t \x03(\x0b\x32!.proto_types.EventInfo.ExtraEntry\x12\x10\n\x08\x63\x61tegory\x18\n \x01(\t\x1a,\n\nExtraEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"6\n\x0eGenericMessage\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo"1\n\x11RetryExternalCall\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\x05\x12\x0b\n\x03max\x18\x02 \x01(\x05"j\n\x14RetryExternalCallMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12,\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1e.proto_types.RetryExternalCall"#\n\x14RecordRetryException\x12\x0b\n\x03\x65xc\x18\x01 \x01(\t"p\n\x17RecordRetryExceptionMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12/\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32!.proto_types.RecordRetryException"@\n\x13SystemCouldNotWrite\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x0b\n\x03\x65xc\x18\x03 \x01(\t"n\n\x16SystemCouldNotWriteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12.\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32 .proto_types.SystemCouldNotWrite"!\n\x12SystemExecutingCmd\x12\x0b\n\x03\x63md\x18\x01 \x03(\t"l\n\x15SystemExecutingCmdMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12-\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1f.proto_types.SystemExecutingCmd"\x1c\n\x0cSystemStdOut\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t"`\n\x0fSystemStdOutMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdOut"\x1c\n\x0cSystemStdErr\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t"`\n\x0fSystemStdErrMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdErr",\n\x16SystemReportReturnCode\x12\x12\n\nreturncode\x18\x01 \x01(\x05"t\n\x19SystemReportReturnCodeMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x31\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32#.proto_types.SystemReportReturnCode"\x19\n\nFormatting\x12\x0b\n\x03msg\x18\x01 \x01(\t"\\\n\rFormattingMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12%\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x17.proto_types.Formatting"\x13\n\x04Note\x12\x0b\n\x03msg\x18\x01 \x01(\t"P\n\x07NoteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x1f\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x11.proto_types.Noteb\x06proto3'
-)
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0btypes.proto\x12\x0bproto_types\x1a\x1fgoogle/protobuf/timestamp.proto\"\x91\x02\n\tEventInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\x12\x0b\n\x03msg\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\t\x12\x15\n\rinvocation_id\x18\x05 \x01(\t\x12\x0b\n\x03pid\x18\x06 \x01(\x05\x12\x0e\n\x06thread\x18\x07 \x01(\t\x12&\n\x02ts\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x05\x65xtra\x18\t \x03(\x0b\x32!.proto_types.EventInfo.ExtraEntry\x12\x10\n\x08\x63\x61tegory\x18\n \x01(\t\x1a,\n\nExtraEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"6\n\x0eGenericMessage\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\"1\n\x11RetryExternalCall\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\x05\x12\x0b\n\x03max\x18\x02 \x01(\x05\"j\n\x14RetryExternalCallMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12,\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1e.proto_types.RetryExternalCall\"#\n\x14RecordRetryException\x12\x0b\n\x03\x65xc\x18\x01 \x01(\t\"p\n\x17RecordRetryExceptionMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12/\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32!.proto_types.RecordRetryException\"@\n\x13SystemCouldNotWrite\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x0b\n\x03\x65xc\x18\x03 \x01(\t\"n\n\x16SystemCouldNotWriteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12.\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32 .proto_types.SystemCouldNotWrite\"!\n\x12SystemExecutingCmd\x12\x0b\n\x03\x63md\x18\x01 \x03(\t\"l\n\x15SystemExecutingCmdMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12-\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1f.proto_types.SystemExecutingCmd\"\x1c\n\x0cSystemStdOut\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t\"`\n\x0fSystemStdOutMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdOut\"\x1c\n\x0cSystemStdErr\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t\"`\n\x0fSystemStdErrMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdErr\",\n\x16SystemReportReturnCode\x12\x12\n\nreturncode\x18\x01 \x01(\x05\"t\n\x19SystemReportReturnCodeMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x31\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32#.proto_types.SystemReportReturnCode\"\x19\n\nFormatting\x12\x0b\n\x03msg\x18\x01 \x01(\t\"\\\n\rFormattingMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12%\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x17.proto_types.Formatting\"\x13\n\x04Note\x12\x0b\n\x03msg\x18\x01 \x01(\t\"P\n\x07NoteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x1f\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x11.proto_types.Noteb\x06proto3')
 
 _globals = globals()
 _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
-_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "types_pb2", _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'types_pb2', _globals)
 if _descriptor._USE_C_DESCRIPTORS == False:
 
-    DESCRIPTOR._options = None
-    _EVENTINFO_EXTRAENTRY._options = None
-    _EVENTINFO_EXTRAENTRY._serialized_options = b"8\001"
-    _globals["_EVENTINFO"]._serialized_start = 62
-    _globals["_EVENTINFO"]._serialized_end = 335
-    _globals["_EVENTINFO_EXTRAENTRY"]._serialized_start = 291
-    _globals["_EVENTINFO_EXTRAENTRY"]._serialized_end = 335
-    _globals["_GENERICMESSAGE"]._serialized_start = 337
-    _globals["_GENERICMESSAGE"]._serialized_end = 391
-    _globals["_RETRYEXTERNALCALL"]._serialized_start = 393
-    _globals["_RETRYEXTERNALCALL"]._serialized_end = 442
-    _globals["_RETRYEXTERNALCALLMSG"]._serialized_start = 444
-    _globals["_RETRYEXTERNALCALLMSG"]._serialized_end = 550
-    _globals["_RECORDRETRYEXCEPTION"]._serialized_start = 552
-    _globals["_RECORDRETRYEXCEPTION"]._serialized_end = 587
-    _globals["_RECORDRETRYEXCEPTIONMSG"]._serialized_start = 589
-    _globals["_RECORDRETRYEXCEPTIONMSG"]._serialized_end = 701
-    _globals["_SYSTEMCOULDNOTWRITE"]._serialized_start = 703
-    _globals["_SYSTEMCOULDNOTWRITE"]._serialized_end = 767
-    _globals["_SYSTEMCOULDNOTWRITEMSG"]._serialized_start = 769
-    _globals["_SYSTEMCOULDNOTWRITEMSG"]._serialized_end = 879
-    _globals["_SYSTEMEXECUTINGCMD"]._serialized_start = 881
-    _globals["_SYSTEMEXECUTINGCMD"]._serialized_end = 914
-    _globals["_SYSTEMEXECUTINGCMDMSG"]._serialized_start = 916
-    _globals["_SYSTEMEXECUTINGCMDMSG"]._serialized_end = 1024
-    _globals["_SYSTEMSTDOUT"]._serialized_start = 1026
-    _globals["_SYSTEMSTDOUT"]._serialized_end = 1054
-    _globals["_SYSTEMSTDOUTMSG"]._serialized_start = 1056
-    _globals["_SYSTEMSTDOUTMSG"]._serialized_end = 1152
-    _globals["_SYSTEMSTDERR"]._serialized_start = 1154
-    _globals["_SYSTEMSTDERR"]._serialized_end = 1182
-    _globals["_SYSTEMSTDERRMSG"]._serialized_start = 1184
-    _globals["_SYSTEMSTDERRMSG"]._serialized_end = 1280
-    _globals["_SYSTEMREPORTRETURNCODE"]._serialized_start = 1282
-    _globals["_SYSTEMREPORTRETURNCODE"]._serialized_end = 1326
-    _globals["_SYSTEMREPORTRETURNCODEMSG"]._serialized_start = 1328
-    _globals["_SYSTEMREPORTRETURNCODEMSG"]._serialized_end = 1444
-    _globals["_FORMATTING"]._serialized_start = 1446
-    _globals["_FORMATTING"]._serialized_end = 1471
-    _globals["_FORMATTINGMSG"]._serialized_start = 1473
-    _globals["_FORMATTINGMSG"]._serialized_end = 1565
-    _globals["_NOTE"]._serialized_start = 1567
-    _globals["_NOTE"]._serialized_end = 1586
-    _globals["_NOTEMSG"]._serialized_start = 1588
-    _globals["_NOTEMSG"]._serialized_end = 1668
+  DESCRIPTOR._options = None
+  _EVENTINFO_EXTRAENTRY._options = None
+  _EVENTINFO_EXTRAENTRY._serialized_options = b'8\001'
+  _globals['_EVENTINFO']._serialized_start=62
+  _globals['_EVENTINFO']._serialized_end=335
+  _globals['_EVENTINFO_EXTRAENTRY']._serialized_start=291
+  _globals['_EVENTINFO_EXTRAENTRY']._serialized_end=335
+  _globals['_GENERICMESSAGE']._serialized_start=337
+  _globals['_GENERICMESSAGE']._serialized_end=391
+  _globals['_RETRYEXTERNALCALL']._serialized_start=393
+  _globals['_RETRYEXTERNALCALL']._serialized_end=442
+  _globals['_RETRYEXTERNALCALLMSG']._serialized_start=444
+  _globals['_RETRYEXTERNALCALLMSG']._serialized_end=550
+  _globals['_RECORDRETRYEXCEPTION']._serialized_start=552
+  _globals['_RECORDRETRYEXCEPTION']._serialized_end=587
+  _globals['_RECORDRETRYEXCEPTIONMSG']._serialized_start=589
+  _globals['_RECORDRETRYEXCEPTIONMSG']._serialized_end=701
+  _globals['_SYSTEMCOULDNOTWRITE']._serialized_start=703
+  _globals['_SYSTEMCOULDNOTWRITE']._serialized_end=767
+  _globals['_SYSTEMCOULDNOTWRITEMSG']._serialized_start=769
+  _globals['_SYSTEMCOULDNOTWRITEMSG']._serialized_end=879
+  _globals['_SYSTEMEXECUTINGCMD']._serialized_start=881
+  _globals['_SYSTEMEXECUTINGCMD']._serialized_end=914
+  _globals['_SYSTEMEXECUTINGCMDMSG']._serialized_start=916
+  _globals['_SYSTEMEXECUTINGCMDMSG']._serialized_end=1024
+  _globals['_SYSTEMSTDOUT']._serialized_start=1026
+  _globals['_SYSTEMSTDOUT']._serialized_end=1054
+  _globals['_SYSTEMSTDOUTMSG']._serialized_start=1056
+  _globals['_SYSTEMSTDOUTMSG']._serialized_end=1152
+  _globals['_SYSTEMSTDERR']._serialized_start=1154
+  _globals['_SYSTEMSTDERR']._serialized_end=1182
+  _globals['_SYSTEMSTDERRMSG']._serialized_start=1184
+  _globals['_SYSTEMSTDERRMSG']._serialized_end=1280
+  _globals['_SYSTEMREPORTRETURNCODE']._serialized_start=1282
+  _globals['_SYSTEMREPORTRETURNCODE']._serialized_end=1326
+  _globals['_SYSTEMREPORTRETURNCODEMSG']._serialized_start=1328
+  _globals['_SYSTEMREPORTRETURNCODEMSG']._serialized_end=1444
+  _globals['_FORMATTING']._serialized_start=1446
+  _globals['_FORMATTING']._serialized_end=1471
+  _globals['_FORMATTINGMSG']._serialized_start=1473
+  _globals['_FORMATTINGMSG']._serialized_end=1565
+  _globals['_NOTE']._serialized_start=1567
+  _globals['_NOTE']._serialized_end=1586
+  _globals['_NOTEMSG']._serialized_start=1588
+  _globals['_NOTEMSG']._serialized_end=1668
 # @@protoc_insertion_point(module_scope)
diff --git a/pyproject.toml b/pyproject.toml
index 7c84afe3..d1d7e3ab 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -77,6 +77,27 @@ dependencies = [
   "types-PyYAML~=6.0",
 ]
 
+[tool.hatch.envs.build]
+detached = true
+features = ["build"]
+
+[tool.hatch.envs.build.scripts]
+check-all = [
+    "- check-wheel",
+    "- check-sdist",
+]
+check-wheel = [
+    "twine check dist/*",
+    "find ./dist/dbt_common-*.whl -maxdepth 1 -type f | xargs python -m pip install --force-reinstall --find-links=dist/",
+    "pip freeze | grep dbt-common",
+]
+check-sdist = [
+    "check-wheel-contents dist/*.whl --ignore W007,W008",
+    "find ./dist/dbt_common-*.gz -maxdepth 1 -type f | xargs python -m pip install --force-reinstall --find-links=dist/",
+    "pip freeze | grep dbt-common",
+]
+protobuf = "protoc -I=./dbt_common/events --python_out=./dbt_common/events ./dbt_common/events/types.proto"
+
 [tool.ruff]
 line-length = 120
 select = [