Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8398c6dd9b | |||
| 716e3fc6b9 | |||
| 492864d5ae | |||
| 470b09798e | |||
| 2a6605592c | |||
| 31e4b8e392 | |||
| d31afa09e1 | |||
| 86eeef2a72 | |||
| 93f42839f9 | |||
| 06a27404f9 | |||
| 1e3480e658 | |||
| 4e390394a9 | |||
| 1477a3d10e | |||
| e97a96205a | |||
| a1423f1cc1 | |||
| f8f1823594 | |||
| 3983b2902a | |||
| 81d3a1ebaa | |||
| 88fc9fc9c4 | |||
| d2439576fb | |||
| ad0bc84c50 | |||
| 640265e80e | |||
| 441e9eb32f | |||
| 895a6b6f2b | |||
| a233ddcd91 | |||
| 35fe0f61a6 | |||
| 62de56f33a | |||
| e50c6c3434 | |||
| 90169ac033 | |||
| 806feb95f3 | |||
| 2306c9acea | |||
| e2fcd0be74 | |||
| a0c4787eda | |||
| 7577084fbf | |||
| ea9b44627a | |||
| c1c819e6d7 | |||
| c21ecf9c3b | |||
| 2f3d32aa55 | |||
| 476d0b84d5 | |||
| a7961df1c1 | |||
| e417a013fa | |||
| 58abdaaf74 | |||
| af16a4a4a8 | |||
| b04c37caf3 | |||
| 9a563364ea | |||
| f3209619c5 | |||
| 131757ce31 | |||
| 9ca58e6e8a | |||
| 53058b00a1 | |||
| bd5e08752e | |||
| 72aa81e593 | |||
| 2bbfa7d84e | |||
| 0194d0815f | |||
| 5826130bc8 |
@@ -0,0 +1,4 @@
|
||||
GITEA_ACCESS_TOKEN=528ed6363ba47884c05235cff9ba47e38b4201d5
|
||||
GITEA_USERNAME=hoangvv
|
||||
GITEA_PASSWORD=smartyourlife
|
||||
GITEA_HOST = https://git.nextzenos.com/api/v1
|
||||
@@ -21,3 +21,5 @@
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
venv/
|
||||
*.zip
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"key": "nextzenos",
|
||||
"name": "NextZenos",
|
||||
"sort": 1
|
||||
},
|
||||
{
|
||||
"key": "nextdns",
|
||||
"name": "NextDNS",
|
||||
"sort": 2
|
||||
},
|
||||
{
|
||||
"key": "nextcloud",
|
||||
"name": "NextCloud",
|
||||
"sort": 3
|
||||
},
|
||||
{
|
||||
"key": "nextvpn",
|
||||
"name": "NextVPN",
|
||||
"sort": 4
|
||||
},
|
||||
{
|
||||
"key": "nextnas",
|
||||
"name": "NextNAS",
|
||||
"sort": 5
|
||||
},
|
||||
{
|
||||
"key": "nextweb",
|
||||
"name": "NextWeb",
|
||||
"sort": 6
|
||||
},
|
||||
{
|
||||
"key": "nextfirewall",
|
||||
"name": "NextFirewall",
|
||||
"sort": 7
|
||||
},
|
||||
{
|
||||
"key": "accountcenter",
|
||||
"name": "AccountCenter",
|
||||
"sort": 8
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"key": "database",
|
||||
"name": "Database",
|
||||
"sort": 1
|
||||
},
|
||||
{
|
||||
"key": "tool",
|
||||
"name": "Utility",
|
||||
"sort": 3
|
||||
},
|
||||
{
|
||||
"key": "vpn",
|
||||
"name": "VPN",
|
||||
"sort": 4
|
||||
},
|
||||
{
|
||||
"key": "nas",
|
||||
"name": "NAS",
|
||||
"sort": 5
|
||||
},
|
||||
{
|
||||
"key": "cli",
|
||||
"name": "CLI",
|
||||
"sort": 6
|
||||
},
|
||||
{
|
||||
"key": "api",
|
||||
"name": "API",
|
||||
"sort": 7
|
||||
},
|
||||
{
|
||||
"key": "sso",
|
||||
"name": "SSO",
|
||||
"sort": 8
|
||||
},
|
||||
{
|
||||
"key": "network",
|
||||
"name": "Network",
|
||||
"sort": 9
|
||||
},
|
||||
{
|
||||
"key": "cloud",
|
||||
"name": "Cloud",
|
||||
"sort": 10
|
||||
},
|
||||
{
|
||||
"key": "storage",
|
||||
"name": "Storage",
|
||||
"sort": 11
|
||||
},
|
||||
{
|
||||
"key": "monitoring",
|
||||
"name": "Monitoring",
|
||||
"sort": 12
|
||||
},
|
||||
{
|
||||
"key": "web",
|
||||
"name": "Web",
|
||||
"sort": 13
|
||||
},
|
||||
{
|
||||
"key": "security",
|
||||
"name": "Security"
|
||||
},
|
||||
{
|
||||
"key": "os",
|
||||
"name": "OS",
|
||||
"sort": 14
|
||||
},
|
||||
{
|
||||
"key": "appstore",
|
||||
"name": "AppStore",
|
||||
"sort": 15
|
||||
}
|
||||
],
|
||||
"version": "1.0.0",
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"id": "account_center",
|
||||
"name": "AccountCenter",
|
||||
"version": "1.0.4",
|
||||
"description": "Account Center is a platform for managing user accounts and permissions",
|
||||
"installation": {
|
||||
"host_type": "local",
|
||||
"path": "/root/dev/docker-apps/Authentik/AccountCenter",
|
||||
"app_type": "authentik",
|
||||
"deployment": {
|
||||
"type": "docker",
|
||||
"container_name": "acc_center,acc_center_worker_01,acc_center_cache,acc_center_db",
|
||||
"access": "acc_center",
|
||||
"http_port": 9000,
|
||||
"https_port": 9443
|
||||
}
|
||||
},
|
||||
"required": "true",
|
||||
"tags": [
|
||||
"sso",
|
||||
"security",
|
||||
"monitoring"
|
||||
],
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"id": "bifrost",
|
||||
"name": "Bifrost",
|
||||
"description": "Bifrost is a platform for building and deploying applications.",
|
||||
"installation": {
|
||||
"host_type": "local",
|
||||
"deployment": {
|
||||
"type": "native"
|
||||
}
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"key": "accountcenter",
|
||||
"name": "AccountCenter",
|
||||
"sort": 1
|
||||
},
|
||||
{
|
||||
"key": "nextzenos",
|
||||
"name": "NextZenos",
|
||||
"sort": 2
|
||||
},
|
||||
{
|
||||
"key": "nextdns",
|
||||
"name": "NextDNS",
|
||||
"sort": 3
|
||||
},
|
||||
{
|
||||
"key": "nextcloud",
|
||||
"name": "NextCloud",
|
||||
"sort": 4
|
||||
},
|
||||
{
|
||||
"key": "nextvpn",
|
||||
"name": "NextVPN",
|
||||
"sort": 5
|
||||
},
|
||||
{
|
||||
"key": "nextnas",
|
||||
"name": "NextNAS",
|
||||
"sort": 6
|
||||
},
|
||||
{
|
||||
"key": "nextweb",
|
||||
"name": "NextWeb",
|
||||
"sort": 7
|
||||
},
|
||||
{
|
||||
"key": "nextfirewall",
|
||||
"name": "NextFirewall",
|
||||
"sort": 8
|
||||
}
|
||||
],
|
||||
"required": "true",
|
||||
"tags": [
|
||||
"tool",
|
||||
"database",
|
||||
"os"
|
||||
],
|
||||
"version": "1.0.0",
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
+14
-11
@@ -1,14 +1,17 @@
|
||||
{
|
||||
"id": "nextcloud",
|
||||
"name": "NextCloud",
|
||||
"version": "1.0",
|
||||
"description": "",
|
||||
"id": "nextcloud",
|
||||
"name": "NextCloud",
|
||||
"version": "1.0",
|
||||
"description": "Self-hosted productivity platform for file sharing, collaboration, and communication",
|
||||
"installation": {
|
||||
"host_type": "local",
|
||||
"deployment": {
|
||||
"type": "docker"
|
||||
},
|
||||
"location": {
|
||||
"host_type": "local",
|
||||
"installation_path": "/opt/bifrost/apps/nextcloud"
|
||||
},
|
||||
"lastModified": 1746671214
|
||||
"type": "native"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"storage",
|
||||
"cloud"
|
||||
],
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
+11
-7
@@ -2,13 +2,17 @@
|
||||
"id": "nextdns",
|
||||
"name": "NextDNS",
|
||||
"version": "1.0",
|
||||
"description": "",
|
||||
"deployment": {
|
||||
"type": "native"
|
||||
},
|
||||
"location": {
|
||||
"description": "NextDNS provides a DNS-based content filtering service to protect devices from malware, ads, and adult content",
|
||||
"installation": {
|
||||
"host_type": "remote",
|
||||
"host": "10.0.0.1"
|
||||
"host": "10.0.0.1",
|
||||
"deployment": {
|
||||
"type": "native"
|
||||
}
|
||||
},
|
||||
"lastModified": 1746671214
|
||||
"tags": [
|
||||
"security"
|
||||
],
|
||||
"lastModified": 1746671214,
|
||||
"required": "true"
|
||||
}
|
||||
+16
-11
@@ -1,14 +1,19 @@
|
||||
{
|
||||
"id": "nextfirewall",
|
||||
"name": "NextFirewall",
|
||||
"version": "1.0",
|
||||
"description": "",
|
||||
"id": "nextfirewall",
|
||||
"name": "NextFirewall",
|
||||
"version": "1.0",
|
||||
"description": "Advanced firewall solution for network security with comprehensive filtering and protection features",
|
||||
"installation": {
|
||||
"host_type": "remote",
|
||||
"host": "10.0.0.1",
|
||||
"deployment": {
|
||||
"type": "native"
|
||||
},
|
||||
"location": {
|
||||
"host_type": "remote",
|
||||
"host": "10.0.0.1"
|
||||
},
|
||||
"lastModified": 1746671214
|
||||
"type": "native"
|
||||
}
|
||||
},
|
||||
"required": "true",
|
||||
"tags": [
|
||||
"security",
|
||||
"network"
|
||||
],
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
+14
-10
@@ -1,13 +1,17 @@
|
||||
{
|
||||
"id": "nextnas",
|
||||
"name": "NextNAS",
|
||||
"version": "1.0",
|
||||
"description": "",
|
||||
"id": "nextnas",
|
||||
"name": "NextNAS",
|
||||
"version": "1.0",
|
||||
"description": "Network-attached storage system for secure file sharing and backup management",
|
||||
"installation": {
|
||||
"host_type": "local",
|
||||
"deployment": {
|
||||
"type": "native"
|
||||
},
|
||||
"location": {
|
||||
"host_type": "local"
|
||||
},
|
||||
"lastModified": 1746671214
|
||||
"type": "native"
|
||||
}
|
||||
},
|
||||
"required": "true",
|
||||
"tags": [
|
||||
"storage"
|
||||
],
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
+15
-11
@@ -1,14 +1,18 @@
|
||||
{
|
||||
"id": "nextvpn",
|
||||
"name": "NextVPN",
|
||||
"version": "1.0",
|
||||
"description": "",
|
||||
"id": "nextvpn",
|
||||
"name": "NextVPN",
|
||||
"version": "1.0",
|
||||
"description": "Secure VPN solution for encrypted network connections and remote access",
|
||||
"installation": {
|
||||
"host_type": "local",
|
||||
"deployment": {
|
||||
"type": "docker"
|
||||
},
|
||||
"location": {
|
||||
"host_type": "local",
|
||||
"installation_path": "/opt/bifrost/apps/nextvpn"
|
||||
},
|
||||
"lastModified": 1746671214
|
||||
"type": "docker"
|
||||
}
|
||||
},
|
||||
"required": "true",
|
||||
"tags": [
|
||||
"vpn",
|
||||
"network"
|
||||
],
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
+15
-12
@@ -1,15 +1,18 @@
|
||||
{
|
||||
"id": "nextweb",
|
||||
"name": "NextWeb",
|
||||
"version": "1.2",
|
||||
"description": "The new generation of Linux server operation and maintenance management panel",
|
||||
"id": "nextweb",
|
||||
"name": "NextWeb",
|
||||
"version": "1.2",
|
||||
"description": "The new generation of Linux server operation and maintenance management panel",
|
||||
"installation": {
|
||||
"host_type": "local",
|
||||
"deployment": {
|
||||
"type": "docker"
|
||||
},
|
||||
"location": {
|
||||
"host_type": "local",
|
||||
"installation_path": "/opt/bifrost/apps/nextweb"
|
||||
},
|
||||
"apps": [],
|
||||
"lastModified": 1746671214
|
||||
"type": "docker"
|
||||
}
|
||||
},
|
||||
"required": "true",
|
||||
"apps": [],
|
||||
"tags": [
|
||||
"web"
|
||||
],
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
+20
-10
@@ -1,14 +1,24 @@
|
||||
{
|
||||
"id": "nextzenos",
|
||||
"name": "NextZenOS",
|
||||
"version": "1.4",
|
||||
"description": "",
|
||||
"id": "nextzenos",
|
||||
"name": "NextzenOS",
|
||||
"version": "1.4",
|
||||
"description": "Comprehensive operating system designed for network and server management",
|
||||
"required": "true",
|
||||
"installation": {
|
||||
"host_type": "local",
|
||||
"path": "/var/lib/casaos",
|
||||
"deployment": {
|
||||
"type": "native"
|
||||
"type": "native"
|
||||
},
|
||||
"location": {
|
||||
"host_type": "local"
|
||||
},
|
||||
"apps": [],
|
||||
"lastModified": 1746671214
|
||||
"sso": {
|
||||
"provider_type": "oauth2"
|
||||
}
|
||||
},
|
||||
"apps": [],
|
||||
"tags": [
|
||||
"storage",
|
||||
"os",
|
||||
"appstore"
|
||||
],
|
||||
"lastModified": 1746671214
|
||||
}
|
||||
+13
-8
@@ -1,9 +1,14 @@
|
||||
REGISTRY_PATH = $(shell pwd)/registry
|
||||
REGISTRY_REPO = git.nextzenos.com/NextZen/bifrost-registry.git
|
||||
update_registry:
|
||||
( cd $(REGISTRY_PATH) && \
|
||||
@read -p "Enter your commit message: " commit_msg; \
|
||||
git pull https://$(GIT_USER):$(GIT_PASS)@$(REGISTRY_REPO) || true; \
|
||||
git add . && \
|
||||
git commit -m "$${commit_msg:-update}" || true; \
|
||||
git push https://$(GIT_USER):$(GIT_PASS)@$(REGISTRY_REPO) || true )
|
||||
REGISTRY_REPO = git.nextzenos.com/CDN/bifrost-registry.git
|
||||
PYTHON = $(REGISTRY_PATH)/venv/bin/python
|
||||
update_registry: package_registry upload_registry clean_registry
|
||||
|
||||
package_registry:
|
||||
(cd $(REGISTRY_PATH) && \
|
||||
zip -r registry.zip *.json -x .gitignore .git .mk)
|
||||
|
||||
upload_registry:
|
||||
$(PYTHON) $(REGISTRY_PATH)/scripts/main.py
|
||||
|
||||
clean_registry:
|
||||
rm -rf $(REGISTRY_PATH)/*.zip
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
python-dotenv ; python_version > '3.10'
|
||||
git+https://github.com/dblueai/giteapy.git ; python_version > '3.10'
|
||||
open-interpreter ; python_version > '3.10'
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
from .config import GiteaConfig
|
||||
from .api import GiteaApi
|
||||
from .utils import GiteaUtils
|
||||
|
||||
__all__ = ["GiteaConfig", "GiteaApi", "GiteaUtils"]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,26 @@
|
||||
import giteapy
|
||||
from .config import GiteaConfig
|
||||
|
||||
|
||||
class GiteaApi:
|
||||
|
||||
def __init__(self):
|
||||
self.config = GiteaConfig().configuration
|
||||
|
||||
def admin_gitea_instance(self):
|
||||
return giteapy.AdminApi(giteapy.ApiClient(self.config))
|
||||
|
||||
def repo_gitea_instance(self):
|
||||
return giteapy.RepositoryApi(giteapy.ApiClient(self.config))
|
||||
|
||||
def user_gitea_instance(self):
|
||||
return giteapy.UserApi(giteapy.ApiClient(self.config))
|
||||
|
||||
def org_gitea_instance(self):
|
||||
return giteapy.OrganizationApi(giteapy.ApiClient(self.config))
|
||||
|
||||
def misc_gitea_instance(self):
|
||||
return giteapy.MiscellaneousApi(giteapy.ApiClient(self.config))
|
||||
|
||||
def issue_gitea_instance(self):
|
||||
return giteapy.IssueApi(giteapy.ApiClient(self.config))
|
||||
@@ -0,0 +1,12 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
import giteapy
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class GiteaConfig:
|
||||
def __init__(self):
|
||||
self.configuration = giteapy.Configuration()
|
||||
self.configuration.host = os.getenv("GITEA_HOST")
|
||||
self.configuration.api_key["Authorization"] = os.getenv("GITEA_ACCESS_TOKEN")
|
||||
self.configuration.api_key_prefix["Authorization"] = "Bearer"
|
||||
@@ -0,0 +1,57 @@
|
||||
import giteapy
|
||||
from datetime import datetime
|
||||
from .config import GiteaConfig
|
||||
from .api import GiteaApi
|
||||
|
||||
|
||||
class GiteaUtils:
|
||||
def __init__(self, gitea_instance: GiteaApi):
|
||||
self.config = GiteaConfig().configuration
|
||||
self.repo_instance = gitea_instance.repo_gitea_instance()
|
||||
|
||||
def update_release(self, **params):
|
||||
try:
|
||||
self.repo_instance.repo_edit_release(
|
||||
owner=params["owner"],
|
||||
repo=params["repo"],
|
||||
id=params["release_id"], # Release ID
|
||||
body=giteapy.EditReleaseOption(
|
||||
name=f"Bifrost Registry {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
),
|
||||
)
|
||||
print("Update release success")
|
||||
except Exception as e:
|
||||
print(f"Update release failed: {e}")
|
||||
|
||||
def get_release(self, **params):
|
||||
try:
|
||||
return self.repo_instance.repo_get_release(
|
||||
owner=params["owner"],
|
||||
repo=params["repo"],
|
||||
id=params["release_id"], # Release ID
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Get release failed: {e}")
|
||||
return None
|
||||
|
||||
def delete_release_attachment(self, **params):
|
||||
try:
|
||||
self.repo_instance.repo_delete_release_attachment(
|
||||
owner=params["owner"],
|
||||
repo=params["repo"],
|
||||
id=params["release_id"], # Release ID
|
||||
attachment_id=params["attachment_id"],
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Delete release attachment failed: {e}")
|
||||
|
||||
def create_release_attachment(self, **params):
|
||||
try:
|
||||
self.repo_instance.repo_create_release_attachment(
|
||||
owner=params["owner"],
|
||||
repo=params["repo"],
|
||||
id=params["release_id"], # Release ID
|
||||
attachment=params["attachment_path"],
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Create release attachment failed: {e}")
|
||||
Executable
+195
@@ -0,0 +1,195 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from dotenv import load_dotenv
|
||||
from interpreter import OpenInterpreter
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
def get_git_credentials():
|
||||
if len(sys.argv) != 4:
|
||||
print("Usage: python gen_commit.py <GIT_USER> <GIT_PASS> <PROJECT_PATH>")
|
||||
sys.exit(1)
|
||||
return sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
|
||||
|
||||
def get_git_diff(project_path):
|
||||
"""Run git diff and return the output."""
|
||||
result = os.popen(f'cd "{project_path}" && git diff').read()
|
||||
return result.strip()
|
||||
|
||||
|
||||
def gen_commit(project_path):
|
||||
"""Generate commit message using OpenInterpreter based on git diff output."""
|
||||
agent = OpenInterpreter()
|
||||
agent.llm.model = "gpt-4o"
|
||||
agent.auto_run = True
|
||||
|
||||
convention_path = os.path.join(os.path.dirname(__file__), "resources/commit_convention.md")
|
||||
with open(convention_path, "r") as f:
|
||||
convention_content = f.read()
|
||||
|
||||
agent.system_message = f"""
|
||||
You are a helpful assistant that generates concise, conventional commit messages based on code diffs.
|
||||
|
||||
Guidelines:
|
||||
- Use English.
|
||||
- Do not include explanations—only output commit message in under 100 characters.
|
||||
- Follow this convention:
|
||||
{convention_content}
|
||||
"""
|
||||
|
||||
diff_output = get_git_diff(project_path)
|
||||
if not diff_output:
|
||||
return "chore: no changes to commit"
|
||||
|
||||
prompt = f"""
|
||||
Analyze the following git diff and generate a commit message:
|
||||
|
||||
|
||||
{diff_output}
|
||||
"""
|
||||
|
||||
response = agent.chat(prompt)
|
||||
if isinstance(response, list) and response and isinstance(response[-1], dict) and "content" in response[-1]:
|
||||
return response[-1]["content"].strip()
|
||||
return str(response).strip()
|
||||
|
||||
|
||||
async def has_submodules():
|
||||
"""Check if the repository has any submodules."""
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
"git", "config", "--file", ".gitmodules", "--get-regexp", r"^submodule\.",
|
||||
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
return bool(stdout.decode().strip())
|
||||
|
||||
|
||||
async def get_submodule_info():
|
||||
if not await has_submodules():
|
||||
return {}
|
||||
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
"git", "config", "--file", ".gitmodules", "--get-regexp", r"^submodule\..*\.path$",
|
||||
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
|
||||
if stderr:
|
||||
print(f"Error getting submodule paths:\n{stderr.decode()}")
|
||||
return {}
|
||||
|
||||
submodule_info = {}
|
||||
for line in stdout.decode().splitlines():
|
||||
parts = line.split()
|
||||
if len(parts) == 2:
|
||||
name = parts[0].split('.')[1]
|
||||
path = parts[1]
|
||||
abs_path = os.path.abspath(path)
|
||||
submodule_info[abs_path] = name
|
||||
return submodule_info
|
||||
|
||||
|
||||
async def commit_and_push_submodules():
|
||||
if not await has_submodules():
|
||||
print("No submodules found in this repository.")
|
||||
return
|
||||
|
||||
print("Checking for submodule changes...")
|
||||
submodule_info = await get_submodule_info()
|
||||
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
"git submodule foreach --quiet 'if [ -n \"$(git status --porcelain)\" ]; then echo $path; fi'",
|
||||
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if stderr:
|
||||
print(f"Error checking submodules:\n{stderr.decode()}")
|
||||
return
|
||||
|
||||
submodule_paths = stdout.decode().strip().split('\n')
|
||||
git_user, git_pass, _ = get_git_credentials()
|
||||
|
||||
for submodule_path in submodule_paths:
|
||||
if not submodule_path:
|
||||
continue
|
||||
|
||||
abs_path = os.path.abspath(submodule_path)
|
||||
name = submodule_info.get(abs_path, submodule_path)
|
||||
print(f"Processing submodule: {name} at {abs_path}")
|
||||
|
||||
commit_msg = gen_commit(abs_path)
|
||||
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
"git", "remote", "get-url", "origin",
|
||||
cwd=abs_path, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if stderr:
|
||||
print(f"Error getting remote URL for {name}:\n{stderr.decode()}")
|
||||
continue
|
||||
|
||||
remote_url = stdout.decode().strip().replace(".git", "").replace("https://", "")
|
||||
remote_url = f"https://{git_user}:{git_pass}@{remote_url}"
|
||||
|
||||
commands = [
|
||||
f"cd {abs_path} && git add .",
|
||||
f'cd {abs_path} && git commit -m "{commit_msg}" || true',
|
||||
f"cd {abs_path} && git push {remote_url} || true",
|
||||
]
|
||||
|
||||
for cmd in commands:
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if stdout:
|
||||
print(stdout.decode())
|
||||
if stderr:
|
||||
print(f"Submodule '{name}' stderr:\n{stderr.decode()}")
|
||||
|
||||
|
||||
async def push_code():
|
||||
git_user, git_pass, project_path = get_git_credentials()
|
||||
os.chdir(project_path)
|
||||
print(f"Changed to project path: {project_path}")
|
||||
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
"git", "remote", "get-url", "origin",
|
||||
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if stderr:
|
||||
print(f"Failed to get remote URL: {stderr.decode()}")
|
||||
git_repo = stdout.decode().strip().replace(".git", "").replace("https://", "")
|
||||
remote_url = f"https://{git_user}:{git_pass}@{git_repo}"
|
||||
|
||||
await commit_and_push_submodules()
|
||||
|
||||
commit_msg = gen_commit(project_path)
|
||||
print(f"Generated commit message:\n{commit_msg}\n")
|
||||
|
||||
commands = [
|
||||
f"git pull {remote_url} || true",
|
||||
"git add .",
|
||||
f'git commit -m "{commit_msg}" || true',
|
||||
f"git push {remote_url} || true",
|
||||
]
|
||||
|
||||
for cmd in commands:
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
if proc.returncode != 0:
|
||||
print(f"Command failed: {cmd}")
|
||||
print(stderr.decode())
|
||||
elif stderr:
|
||||
# Not an error; just info output
|
||||
print(stderr.decode())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(push_code())
|
||||
@@ -0,0 +1,127 @@
|
||||
# Conventional Commit Messages
|
||||
|
||||
See how [a minor change](#examples) to your commit message style can make a difference.
|
||||
|
||||
> [!TIP]
|
||||
> Take a look at **[git-conventional-commits](https://github.com/qoomon/git-conventional-commits)** , a CLI util to ensure these conventions, determine version and generate changelogs
|
||||
|
||||
## Commit Message Formats
|
||||
|
||||
### Default
|
||||
<pre>
|
||||
<b><a href="#types"><type></a></b></font>(<b><a href="#scopes"><optional scope></a></b>): <b><a href="#description"><description></a></b>
|
||||
<sub>empty separator line</sub>
|
||||
<b><a href="#body"><optional body></a></b>
|
||||
<sub>empty separator line</sub>
|
||||
<b><a href="#footer"><optional footer></a></b>
|
||||
</pre>
|
||||
|
||||
### Merge Commit
|
||||
<pre>
|
||||
Merge branch '<b><branch name></b>'
|
||||
</pre>
|
||||
<sup>Follows default git merge message</sup>
|
||||
|
||||
### Revert Commit
|
||||
<pre>
|
||||
Revert "<b><reverted commit subject line></b>"
|
||||
</pre>
|
||||
<sup>Follows default git revert message</sup>
|
||||
|
||||
### Inital Commit
|
||||
```
|
||||
chore: init
|
||||
```
|
||||
|
||||
### Types
|
||||
- API or UI relevant changes
|
||||
- `feat` Commits, that add or remove a new feature to the API or UI
|
||||
- `fix` Commits, that fix an API or UI bug of a preceded `feat` commit
|
||||
- `refactor` Commits, that rewrite/restructure your code, however do not change any API or UI behaviour
|
||||
- `perf` Commits are special `refactor` commits, that improve performance
|
||||
- `style` Commits, that do not affect the meaning (white-space, formatting, missing semi-colons, etc)
|
||||
- `test` Commits, that add missing tests or correcting existing tests
|
||||
- `docs` Commits, that affect documentation only
|
||||
- `build` Commits, that affect build components like build tools, dependencies, project version, ci pipelines, ...
|
||||
- `ops` Commits, that affect operational components like infrastructure, deployment, backup, recovery, ...
|
||||
- `chore` Miscellaneous commits e.g. modifying `.gitignore`
|
||||
|
||||
### Scopes
|
||||
The `scope` provides additional contextual information.
|
||||
* Is an **optional** part of the format
|
||||
* Allowed Scopes depend on the specific project
|
||||
* Don't use issue identifiers as scopes
|
||||
|
||||
### Breaking Changes Indicator
|
||||
Breaking changes should be indicated by an `!` before the `:` in the subject line e.g. `feat(api)!: remove status endpoint`
|
||||
- Is an **optional** part of the format
|
||||
- Breaking changes **must** be described in the [commit footer section](#footer)
|
||||
|
||||
### Description
|
||||
The `description` contains a concise description of the change.
|
||||
- It is a **mandatory** part of the format
|
||||
- Use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
- Think of `This commit will...` or `This commit should...`
|
||||
- Don't capitalize the first letter
|
||||
- No dot (`.`) at the end
|
||||
|
||||
### Body
|
||||
The `body` should include the motivation for the change and contrast this with previous behavior.
|
||||
- Is an **optional** part of the format
|
||||
- Use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
- This is the place to mention issue identifiers and their relations
|
||||
|
||||
### Footer
|
||||
The `footer` should contain any information about **Breaking Changes** and is also the place to **reference Issues** that this commit refers to.
|
||||
- Is an **optional** part of the format
|
||||
- **optionally** reference an issue by its id.
|
||||
- **Breaking Changes** should start with the word `BREAKING CHANGE:` followed by space or two newlines. The rest of the commit message is then used for this.
|
||||
|
||||
### Versioning
|
||||
- **If** your next release contains commit with...
|
||||
- **breaking changes** incremented the **major version**
|
||||
- **API relevant changes** (`feat` or `fix`) incremented the **minor version**
|
||||
- **Else** increment the **patch version**
|
||||
|
||||
|
||||
### Examples
|
||||
- ```
|
||||
feat: add email notifications on new direct messages
|
||||
```
|
||||
- ```
|
||||
feat(shopping cart): add the amazing button
|
||||
```
|
||||
- ```
|
||||
feat!: remove ticket list endpoint
|
||||
|
||||
refers to JIRA-1337
|
||||
|
||||
BREAKING CHANGE: ticket endpoints no longer supports list all entities.
|
||||
```
|
||||
- ```
|
||||
fix(shopping-cart): prevent order an empty shopping cart
|
||||
```
|
||||
- ```
|
||||
fix(api): fix wrong calculation of request body checksum
|
||||
```
|
||||
- ```
|
||||
fix: add missing parameter to service call
|
||||
|
||||
The error occurred due to <reasons>.
|
||||
```
|
||||
- ```
|
||||
perf: decrease memory footprint for determine uniqe visitors by using HyperLogLog
|
||||
```
|
||||
- ```
|
||||
build: update dependencies
|
||||
```
|
||||
- ```
|
||||
build(release): bump version to 1.0.0
|
||||
```
|
||||
- ```
|
||||
refactor: implement fibonacci number calculation as recursion
|
||||
```
|
||||
- ```
|
||||
style: remove empty line
|
||||
```
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
How to show uncommitted changes in Git
|
||||
|
||||
The command you are looking for is git diff.
|
||||
|
||||
git diff - Show changes between commits, commit and working tree, etc
|
||||
|
||||
Here are some of the options it expose which you can use
|
||||
|
||||
git diff (no parameters)
|
||||
Print out differences between your working directory and the index.
|
||||
|
||||
git diff --cached:
|
||||
Print out differences between the index and HEAD (current commit).
|
||||
|
||||
git diff HEAD:
|
||||
Print out differences between your working directory and the HEAD.
|
||||
|
||||
git diff --name-only
|
||||
Show only names of changed files.
|
||||
|
||||
git diff --name-status
|
||||
Show only names and status of changed files.
|
||||
@@ -0,0 +1,37 @@
|
||||
from gitea.api import GiteaApi
|
||||
from gitea.config import GiteaConfig
|
||||
import giteapy
|
||||
import os
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from gitea import GiteaUtils
|
||||
|
||||
|
||||
current_file_path = os.path.abspath(__file__)
|
||||
params = {
|
||||
"owner": "CDN",
|
||||
"repo": "bifrost-registry",
|
||||
"release_id": 8845,
|
||||
"attachment_path": os.path.abspath(
|
||||
os.path.join(os.path.dirname(current_file_path), "..", "registry.zip")
|
||||
),
|
||||
}
|
||||
|
||||
def main():
|
||||
gitea_instance = GiteaApi()
|
||||
gitea_utils = GiteaUtils(gitea_instance)
|
||||
assets = gitea_utils.get_release(**params).assets
|
||||
if not os.path.isfile(params["attachment_path"]):
|
||||
print(f"File {params['attachment_path']} does not exist")
|
||||
exit(1)
|
||||
gitea_utils.update_release(**params)
|
||||
for asset in assets:
|
||||
if asset.name == "registry.zip":
|
||||
params["attachment_id"] = asset.id
|
||||
gitea_utils.delete_release_attachment(**params)
|
||||
gitea_utils.create_release_attachment(**params)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user