dd3be612e3df1450de40a74fadc6df3c2885e9b1
- Author
- Marc Cornellà <marc@mcornella.com>
- Committer
- GitHub <noreply@github.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/.github/dependencies.yml b/.github/dependencies.yml
2new file mode 100644
3index 0000000000000000000000000000000000000000..8c46395d7b69790daacd86ae92adcc04325f1dcd
4--- /dev/null
5+++ b/.github/dependencies.yml
6@@ -0,0 +1,20 @@
7+dependencies:
8+ plugins/gitfast:
9+ repo: felipec/git-completion
10+ branch: master
11+ version: tag:v1.3.7
12+ postcopy: |
13+ set -e
14+ rm -rf git-completion.plugin.zsh Makefile README.adoc t tools
15+ test -e git-completion.zsh && mv -f git-completion.zsh _git
16+ plugins/z:
17+ branch: master
18+ repo: agkozak/zsh-z
19+ version: 6bfe418332866d15373392164df11b4fbec2083f
20+ precopy: |
21+ set -e
22+ test -e README.md && mv -f README.md MANUAL.md
23+ postcopy: |
24+ set -e
25+ test -e _zshz && mv -f _zshz _z
26+ test -e zsh-z.plugin.zsh && mv -f zsh-z.plugin.zsh z.plugin.zsh
27diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
28new file mode 100644
29index 0000000000000000000000000000000000000000..c27ad79982808324f1559b5e12d34ef1770d62db
30--- /dev/null
31+++ b/.github/workflows/dependencies.yml
32@@ -0,0 +1,26 @@
33+name: Update dependencies
34+on:
35+ workflow_dispatch: {}
36+ # schedule:
37+ # - cron: '34 3 * * */8'
38+
39+jobs:
40+ check:
41+ name: Check for updates
42+ runs-on: ubuntu-latest
43+ steps:
44+ - name: Checkout
45+ if: github.repository == 'ohmyzsh/ohmyzsh'
46+ uses: actions/checkout@v4
47+ - name: Authenticate as @ohmyzsh
48+ uses: ohmyzsh/github-app-token@v2
49+ with:
50+ app-id: ${{ secrets.OHMYZSH_APP_ID }}
51+ private-key: ${{ secrets.OHMYZSH_APP_PRIVATE_KEY }}
52+ - name: Process dependencies
53+ env:
54+ GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
55+ TMP_DIR: ${{ env.RUNNER_TEMP }}
56+ run: |
57+ gh auth login --with-token <<< "${GITHUB_TOKEN}"
58+ python3 .github/workflows/dependencies/updater.py
59diff --git a/.github/workflows/dependencies/updater.py b/.github/workflows/dependencies/updater.py
60new file mode 100644
61index 0000000000000000000000000000000000000000..5af19d14c5308f28f8865e9e0866d39cde24354b
62--- /dev/null
63+++ b/.github/workflows/dependencies/updater.py
64@@ -0,0 +1,450 @@
65+import os
66+import subprocess
67+import sys
68+import requests
69+import shutil
70+import yaml
71+from copy import deepcopy
72+from typing import Optional, TypedDict
73+
74+# Get TMP_DIR variable from environment
75+TMP_DIR = os.path.join(os.environ.get("TMP_DIR", "/tmp"), "ohmyzsh")
76+# Relative path to dependencies.yml file
77+DEPS_YAML_FILE = ".github/dependencies.yml"
78+# Dry run flag
79+DRY_RUN = os.environ.get("DRY_RUN", "0") == "1"
80+
81+import timeit
82+class CodeTimer:
83+ def __init__(self, name=None):
84+ self.name = " '" + name + "'" if name else ''
85+
86+ def __enter__(self):
87+ self.start = timeit.default_timer()
88+
89+ def __exit__(self, exc_type, exc_value, traceback):
90+ self.took = (timeit.default_timer() - self.start) * 1000.0
91+ print('Code block' + self.name + ' took: ' + str(self.took) + ' ms')
92+
93+
94+### YAML representation
95+def str_presenter(dumper, data):
96+ """
97+ Configures yaml for dumping multiline strings
98+ Ref: https://stackoverflow.com/a/33300001
99+ """
100+ if len(data.splitlines()) > 1: # check for multiline string
101+ return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
102+ return dumper.represent_scalar('tag:yaml.org,2002:str', data)
103+
104+yaml.add_representer(str, str_presenter)
105+yaml.representer.SafeRepresenter.add_representer(str, str_presenter)
106+
107+
108+# Types
109+class DependencyDict(TypedDict):
110+ repo: str
111+ branch: str
112+ version: str
113+ precopy: Optional[str]
114+ postcopy: Optional[str]
115+
116+class DependencyYAML(TypedDict):
117+ dependencies: dict[str, DependencyDict]
118+
119+class UpdateStatus(TypedDict):
120+ has_updates: bool
121+ version: Optional[str]
122+ compare_url: Optional[str]
123+ head_ref: Optional[str]
124+ head_url: Optional[str]
125+
126+
127+class CommandRunner:
128+ class Exception(Exception):
129+ def __init__(self, message, returncode, stage, stdout, stderr):
130+ super().__init__(message)
131+ self.returncode = returncode
132+ self.stage = stage
133+ self.stdout = stdout
134+ self.stderr = stderr
135+
136+ @staticmethod
137+ def run_or_fail(command: list[str], stage: str, *args, **kwargs):
138+ if DRY_RUN and command[0] == "gh":
139+ command.insert(0, "echo")
140+
141+ result = subprocess.run(command, *args, capture_output=True, **kwargs)
142+
143+ if result.returncode != 0:
144+ raise CommandRunner.Exception(
145+ f"{stage} command failed with exit code {result.returncode}", returncode=result.returncode,
146+ stage=stage,
147+ stdout=result.stdout.decode("utf-8"),
148+ stderr=result.stderr.decode("utf-8")
149+ )
150+
151+ return result
152+
153+
154+class DependencyStore:
155+ store: DependencyYAML = {
156+ "dependencies": {}
157+ }
158+
159+ @staticmethod
160+ def set(data: DependencyYAML):
161+ DependencyStore.store = data
162+
163+ @staticmethod