augint-tools 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.1
2
+ Name: augint-tools
3
+ Version: 1.0.0
4
+ Summary: Standard tools for Augmenting Integrations
5
+ Home-page: https://github.com/svange/openbrain
6
+ License: AGPL-3.0-only
7
+ Author: Samuel Vange
8
+ Author-email: 7166607+svange@users.noreply.github.com
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: boto3 (>=1.28.51,<2.0.0)
16
+ Requires-Dist: pygithub (>=2.3.0,<3.0.0)
17
+ Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Augmenting Integrations Tools
21
+ ![ci status](https://github.com/svange/augint-tools/actions/workflows/pipeline.yaml/badge.svg?branch=main)
22
+
23
+ ![PyPI - Version](https://img.shields.io/pypi/v/openbrain)
24
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
25
+ <a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
26
+ [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square)](https://conventionalcommits.org)
27
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?style=flat-square&logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
28
+ [![Made with GH Actions](https://img.shields.io/badge/CI-GitHub_Actions-blue?logo=github-actions&logoColor=white)](https://github.com/features/actions "Go to GitHub Actions homepage")
29
+ [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
30
+
31
+ # Secrets
32
+ Push secrets from .env to GH Actions.
33
+
@@ -0,0 +1,13 @@
1
+ # Augmenting Integrations Tools
2
+ ![ci status](https://github.com/svange/augint-tools/actions/workflows/pipeline.yaml/badge.svg?branch=main)
3
+
4
+ ![PyPI - Version](https://img.shields.io/pypi/v/openbrain)
5
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
6
+ <a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
7
+ [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square)](https://conventionalcommits.org)
8
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?style=flat-square&logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
9
+ [![Made with GH Actions](https://img.shields.io/badge/CI-GitHub_Actions-blue?logo=github-actions&logoColor=white)](https://github.com/features/actions "Go to GitHub Actions homepage")
10
+ [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
11
+
12
+ # Secrets
13
+ Push secrets from .env to GH Actions.
@@ -0,0 +1,230 @@
1
+ [tool.poetry]
2
+ name = "augint-tools"
3
+ version = "1.0.0"
4
+ description = "Standard tools for Augmenting Integrations"
5
+ authors = ["Samuel Vange <7166607+svange@users.noreply.github.com>"]
6
+ readme = "README.md"
7
+ license = "AGPL-3.0-only"
8
+ packages = [{ include = "src" }]
9
+ homepage = "https://github.com/svange/openbrain"
10
+
11
+ [tool.poetry.scripts]
12
+ ai-secrets = "src.secrets:cli"
13
+
14
+ [tool.poetry.plugins."commitizen.plugin"] # completely untested
15
+ cz_conventional_commits = "commitizen.cz.conventional_commits:ConventionalCommitsCz"
16
+ #cz_jira = "commitizen.cz.jira:JiraSmartCz"
17
+ cz_customize = "commitizen.cz.customize:CustomizeCommitsCz"
18
+ cargo = "commitizen.providers:CargoProvider"
19
+ commitizen = "commitizen.providers:CommitizenProvider"
20
+ composer = "commitizen.providers:ComposerProvider"
21
+ npm = "commitizen.providers:NpmProvider"
22
+ pep621 = "commitizen.providers:Pep621Provider"
23
+ poetry = "commitizen.providers:PoetryProvider"
24
+ scm = "commitizen.providers:ScmProvider"
25
+
26
+ [tool.semantic_release]
27
+ major_on_zero = false
28
+ commit_message = "chore(release): release {version}"
29
+
30
+ # End from video
31
+ [tool.semantic_release.branches.main]
32
+ match = "main"
33
+ #commit_message = "chore(release): release {version}"
34
+ prerelease = false
35
+
36
+ [tool.semantic_release.branches.dev]
37
+ match = "dev"
38
+ #commit_message = "chore(pre-release): release {version}"
39
+ prerelease_token = "dev"
40
+ prerelease = true
41
+
42
+ version_toml = [
43
+ "pyproject.toml:tool.poetry.version",
44
+ ]
45
+ version_variable = [
46
+ "openbrain/__init__.py:__version__",
47
+ ]
48
+ build_command = "pip install poetry && poetry build"
49
+ #logging_use_named_masks = true
50
+ #major_on_zero = true
51
+ tag_format = "v{version}"
52
+ #exclude_commit_patterns = [
53
+ # 'skip: ',
54
+ #]
55
+
56
+ [tool.semantic_release.publish]
57
+ dist_glob_patterns = ["dist/*"]
58
+ upload_to_vcs_release = true
59
+ type = "github"
60
+
61
+ [tool.semantic_release.remote.token]
62
+ env = "GITHUB_TOKEN"
63
+ fallback_env = "GH_TOKEN"
64
+
65
+
66
+
67
+ [tool.commitizen]
68
+ name = "cz_conventional_commits"
69
+ tag_format = "v$version"
70
+ version_scheme = "SemVer"
71
+ version_provider = "poetry" #"scm"
72
+ update_changelog_on_bump = true
73
+ major_version_zero = true
74
+ #version = "3.9.1"
75
+ #version_files = [
76
+ # "pyproject.toml:version",
77
+ # "openbrain/__version__.py",
78
+ # ".pre-commit-config.yaml:rev:.+Openbrain",
79
+ #]
80
+
81
+ [tool.poetry.plugins."commitizen.scheme"]
82
+ pep440 = "commitizen.version_schemes:Pep440"
83
+ semver = "commitizen.version_schemes:SemVer"
84
+
85
+ [tool.poetry.dependencies]
86
+ python = "^3.10"
87
+ boto3 = "^1.28.51"
88
+ pygithub = "^2.3.0"
89
+ python-dotenv = "^1.0.1"
90
+
91
+
92
+ [tool.poetry.group.dev.dependencies]
93
+ pytest = "^7.4.2"
94
+ faker = "^19.6.1"
95
+ retry = "^0.9.2"
96
+ flake8 = "^7.1.0"
97
+ black = "^23.9.1"
98
+ reorder-python-imports = "^3.10.0"
99
+ python-semantic-release = "^9.8.5"
100
+ ruff = "^0.0.291"
101
+ mypy = "^1.5.1"
102
+ commitizen = "^3.9.1"
103
+ isort = "^5.12.0"
104
+ pre-commit = "^3.4.0"
105
+ coverage = "^7.3.2"
106
+ pygithub = "^2.1.1"
107
+
108
+ [tool.coverage] # not tested
109
+ [tool.coverage.report]
110
+ show_missing = true
111
+ exclude_lines = [
112
+ # Have to re-enable the standard pragma
113
+ 'pragma: no cover',
114
+ # Don't complain about missing debug-only code:
115
+ 'def __repr__',
116
+ 'if self\.debug',
117
+ # Don't complain if tests don't hit defensive assertion code:
118
+ 'raise AssertionError',
119
+ 'raise NotImplementedError',
120
+ # Don't complain if non-runnable code isn't run:
121
+ 'if 0:',
122
+ 'if __name__ == .__main__.:',
123
+ 'if TYPE_CHECKING:',
124
+ ]
125
+ omit = [
126
+ 'env/*',
127
+ 'venv/*',
128
+ '.venv/*',
129
+ '*/virtualenv/*',
130
+ '*/virtualenvs/*',
131
+ '*/tests/*',
132
+ ]
133
+
134
+ [tool.pytest.ini_options]
135
+ addopts = '-m "not remote_tests and not redundant"'
136
+
137
+ [tool.ruff]
138
+ line-length = 130
139
+ ignore = [
140
+ "E501",
141
+ "D1",
142
+ "D415"
143
+ ]
144
+ # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
145
+ select = ["E", "F"]
146
+
147
+ [tool.ruff.isort]
148
+ known-first-party = ["commitizen", "tests"]
149
+
150
+ [tool.ruff.pydocstyle]
151
+ convention = "google"
152
+
153
+ [tool.mypy]
154
+ files = "commitizen"
155
+ disallow_untyped_decorators = true
156
+ disallow_subclassing_any = true
157
+ warn_return_any = true
158
+ warn_redundant_casts = true
159
+ warn_unused_ignores = true
160
+ warn_unused_configs = true
161
+
162
+ [[tool.mypy.overrides]]
163
+ module = "py.*" # Legacy pytest dependencies
164
+ ignore_missing_imports = true
165
+
166
+ [tool.black]
167
+ line-length = 130
168
+ target-version = ['py310']
169
+ include = '\.pyi?$'
170
+ exclude = '''
171
+ /(
172
+ \.git
173
+ | \.hg
174
+ | \.mypy_cache
175
+ | \.tox
176
+ | \.venv
177
+ | _build
178
+ | buck-out
179
+ | build
180
+ )/
181
+ '''
182
+
183
+ [tool.flake8]
184
+ max-line-length = 130
185
+ extend-ignore = ["D203", "E203", "E251", "E266", "E302", "E305", "E401", "E402", "E501", "F401", "F403", "W503"]
186
+ exclude = [".git", "__pycache__", "dist"]
187
+ max-complexity = 10
188
+
189
+ [tool.isort]
190
+ atomic = true
191
+ profile = "black"
192
+ line_length = 130
193
+ skip_gitignore = true
194
+
195
+ # Allow autofix for all enabled rules (when `--fix`) is provided.
196
+ fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
197
+ unfixable = []
198
+
199
+ # Exclude a variety of commonly ignored directories.
200
+ exclude = [
201
+ ".bzr",
202
+ ".direnv",
203
+ ".eggs",
204
+ ".git",
205
+ ".git-rewrite",
206
+ ".hg",
207
+ ".mypy_cache",
208
+ ".nox",
209
+ ".pants.d",
210
+ ".pytype",
211
+ ".ruff_cache",
212
+ ".svn",
213
+ ".tox",
214
+ ".venv",
215
+ "__pypackages__",
216
+ "_build",
217
+ "buck-out",
218
+ "build",
219
+ "dist",
220
+ "node_modules",
221
+ "venv",
222
+ ]
223
+
224
+ # Same as Black.
225
+ line-length = 130
226
+
227
+ # Allow unused variables when underscore-prefixed.
228
+ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
229
+
230
+ target-version = "py310"
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"
@@ -0,0 +1,28 @@
1
+ import os
2
+
3
+ import boto3
4
+
5
+ os.environ["AWS_PROFILE"] = "personal"
6
+
7
+
8
+ def list_ec2_resources():
9
+ ec2 = boto3.resource("ec2")
10
+
11
+ print("Listing EC2 Instances:")
12
+ for instance in ec2.instances.all():
13
+ print(instance.id, instance.state, instance.instance_type)
14
+
15
+ print("\nListing EBS Snapshots:")
16
+ ec2_client = boto3.client("ec2")
17
+ snapshots = ec2_client.describe_snapshots(OwnerIds=["self"])
18
+ for snapshot in snapshots["Snapshots"]:
19
+ print(snapshot["SnapshotId"], snapshot["VolumeId"], snapshot["VolumeSize"])
20
+
21
+ print("\nListing Elastic IPs:")
22
+ elastic_ips = ec2_client.describe_addresses()
23
+ for eip in elastic_ips["Addresses"]:
24
+ print(eip["PublicIp"], eip.get("InstanceId", "Unassociated"))
25
+
26
+
27
+ if __name__ == "__main__":
28
+ list_ec2_resources()
@@ -0,0 +1,40 @@
1
+ {
2
+ "version":1,
3
+ "disable_existing_loggers":true,
4
+ "formatters":{
5
+ "standard":{
6
+ "format":"%(asctime)s [%(levelname)s] %(name)s: %(message)s"
7
+ }
8
+ },
9
+ "handlers":{
10
+ "default":{
11
+ "level":"INFO",
12
+ "formatter":"standard",
13
+ "class":"logging.StreamHandler",
14
+ "stream":"ext://sys.stdout"
15
+ }
16
+ },
17
+ "loggers":{
18
+ "":{
19
+ "handlers":[
20
+ "default"
21
+ ],
22
+ "level":"WARNING",
23
+ "propagate":false
24
+ },
25
+ "my.packg":{
26
+ "handlers":[
27
+ "default"
28
+ ],
29
+ "level":"INFO",
30
+ "propagate":false
31
+ },
32
+ "__main__":{
33
+ "handlers":[
34
+ "default"
35
+ ],
36
+ "level":"DEBUG",
37
+ "propagate":false
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,88 @@
1
+ import json
2
+ import os
3
+ from pathlib import Path
4
+ from dotenv import load_dotenv
5
+ from github import Github, Auth
6
+
7
+ import click
8
+ from src.util import log
9
+
10
+ @click.command()
11
+ @click.option("--verbose", "-v", help="Verbose output.", is_flag=True)
12
+ @click.argument("filename", type=click.Path(exists=True, readable=True), default=".env")
13
+ def cli(verbose: bool, filename: click.Path):
14
+ if verbose:
15
+ log.info("Verbose output enabled.")
16
+
17
+ results = perform_update(filename)
18
+ log.info(results)
19
+
20
+
21
+ def perform_update(filename: click.Path):
22
+ if not filename:
23
+ raise ValueError("No filename specified. Exiting to avoid an accident.")
24
+
25
+ load_dotenv(str(filename))
26
+ github_repo = os.environ.get("GH_REPO", "ObInfra")
27
+ github_org = os.environ.get("GH_ORG", None)
28
+ github_user = os.environ.get("GH_USER", None)
29
+
30
+ file_path = Path(filename.__str__())
31
+ # Read the .env file and convert it to a JSON object
32
+ env_data = {}
33
+ with file_path.open("r") as file:
34
+ for line in file:
35
+ line = line.strip()
36
+ if not line or line.startswith("#") or line.startswith(";") or "=" not in line:
37
+ continue
38
+ key, value = line.strip().split("=", 1)
39
+ # Skip AWS Variables as they'll only confuse the pipeline
40
+ if key.startswith("AWS_PROFILE"):
41
+ continue
42
+ env_data[key] = os.getenv(key)
43
+ env_json = json.dumps(env_data)
44
+
45
+ results = []
46
+ result = create_or_update_github_secrets(
47
+ github_repo=github_repo, github_org=github_org, github_user=github_user, env_data=env_data
48
+ )
49
+ results.append(result)
50
+
51
+ return results
52
+
53
+
54
+ def create_or_update_github_secrets(github_org, github_repo, github_user, env_data):
55
+ auth = Auth.Token(os.environ.get("GH_TOKEN", None))
56
+ g = Github(auth=auth)
57
+ if github_org:
58
+ g_org = g.get_organization(github_org)
59
+ repo = g_org.get_repo(github_repo)
60
+ elif github_user:
61
+ g_user = g.get_user(github_user)
62
+ repo = g_user.get_repo(github_repo)
63
+ else:
64
+ raise ValueError("Must specify either GITHUB_ORG or GH_USER")
65
+ secrets = [secret for secret in repo.get_secrets()]
66
+ secret_names = [secret.name for secret in secrets]
67
+
68
+ results = []
69
+ for env_var_name, env_var_value in env_data.items():
70
+ # Create or update secrets
71
+ if env_var_name in secret_names:
72
+ log.info(f"Updating secret {env_var_name}...")
73
+ results.append(repo.create_secret(env_var_name, env_var_value))
74
+
75
+ else:
76
+ log.info(f"Creating secret {env_var_name}...")
77
+ results.append(repo.create_secret(env_var_name, env_var_value))
78
+
79
+ for secret_name in secret_names:
80
+ if secret_name not in env_data.keys():
81
+ log.info(f"Deleting secret {secret_name}...")
82
+ results.append(repo.delete_secret(secret_name))
83
+
84
+ return results
85
+
86
+
87
+ if __name__ == "__main__":
88
+ cli()
@@ -0,0 +1,16 @@
1
+ import json
2
+ import logging.config
3
+ import os
4
+ import pathlib
5
+
6
+ this_dir = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
7
+
8
+ logging_config_path = this_dir / "resources/logging.json"
9
+
10
+ with open(logging_config_path, "r") as f:
11
+ LOGGING_CONFIG = json.load(f)
12
+
13
+ logging.config.dictConfig(LOGGING_CONFIG)
14
+
15
+ log = logging.getLogger(__name__)
16
+ log.debug("Logging is configured.")