Skip to content

Commit 751acd7

Browse files
authored
Enhance Dependency Tracking and Issue Creation Github Action (#444)
* wip: new script and yaml format * Update variables * Update scripts * Update workflow * Update workflow filename * Untrack json file
1 parent 098bae9 commit 751acd7

File tree

33 files changed

+325
-211
lines changed

33 files changed

+325
-211
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import requests
2+
import json
3+
import sys
4+
import yaml
5+
from urllib.parse import urlparse
6+
7+
REGISTRIES = {
8+
"repositories": lambda info: get_latest_github_release(info.get("repository_url")),
9+
"crates": lambda info: get_latest_crate_version(info.get("name")),
10+
"javascript_packages": lambda info: get_latest_npm_version(info.get("name")),
11+
"python_packages": lambda info: get_latest_pypi_version(info.get("name")),
12+
}
13+
14+
def get_latest_github_release(repo_url):
15+
try:
16+
path = urlparse(repo_url).path.strip("/")
17+
owner, repo = path.split("/")[-2:]
18+
api_url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest"
19+
response = requests.get(api_url)
20+
if response.status_code == 200:
21+
data = response.json()
22+
return data["tag_name"], data["html_url"]
23+
except Exception as e:
24+
print(f"Error fetching GitHub release for {repo_url}: {e}")
25+
return None, None
26+
27+
def get_latest_crate_version(crate_name):
28+
try:
29+
response = requests.get(f"https://crates.io/api/v1/crates/{crate_name}")
30+
if response.status_code == 200:
31+
data = response.json()["crate"]
32+
latest_version = data["max_stable_version"]
33+
return latest_version, f"https://crates.io/crates/{crate_name}/{latest_version}"
34+
except Exception as e:
35+
print(f"Error fetching crate version for {crate_name}: {e}")
36+
return None, None
37+
38+
def get_latest_npm_version(package_name):
39+
try:
40+
response = requests.get(f"https://registry.npmjs.org/{package_name}")
41+
if response.status_code == 200:
42+
data = response.json()
43+
latest_version = data["dist-tags"]["latest"]
44+
return latest_version, f"https://www.npmjs.com/package/{package_name}/v/{latest_version}"
45+
except Exception as e:
46+
print(f"Error fetching npm package version for {package_name}: {e}")
47+
return None, None
48+
49+
def get_latest_pypi_version(package_name):
50+
try:
51+
response = requests.get(f"https://pypi.org/pypi/{package_name}/json")
52+
if response.status_code == 200:
53+
data = response.json()["info"]
54+
latest_version = data["version"]
55+
return latest_version, f"https://pypi.org/project/{package_name}/{latest_version}/"
56+
except Exception as e:
57+
print(f"Error fetching PyPI package version for {package_name}: {e}")
58+
return None, None
59+
60+
def check_releases(releases_source_file):
61+
try:
62+
with open(releases_source_file, "r") as file:
63+
data = yaml.safe_load(file)
64+
dependencies = data.get("dependencies", {})
65+
except Exception as e:
66+
print(f"Error reading releases source file '{releases_source_file}': {e}")
67+
sys.exit(1)
68+
69+
outdated_dependencies = []
70+
71+
for category, items in dependencies.items():
72+
if category not in REGISTRIES:
73+
continue
74+
75+
for name, info in items.items():
76+
current_version = info.get("version")
77+
latest_version, latest_url = REGISTRIES[category](info)
78+
79+
if latest_version and latest_version != current_version:
80+
outdated_dependencies.append({
81+
"name": name,
82+
"category": category,
83+
"current_version": current_version,
84+
"latest_version": latest_version,
85+
"latest_release_url": latest_url,
86+
})
87+
88+
return outdated_dependencies
89+
90+
def main(releases_source_file):
91+
try:
92+
outdated_dependencies = check_releases(releases_source_file)
93+
output = {
94+
"outdated_dependencies": outdated_dependencies,
95+
"outdated_count": len(outdated_dependencies),
96+
}
97+
with open("outdated_dependencies.json", "w") as f:
98+
json.dump(output, f, indent=2)
99+
print(json.dumps(output))
100+
except Exception as e:
101+
print(f"Error in main execution: {e}")
102+
sys.exit(1)
103+
104+
if __name__ == "__main__":
105+
main("variables.yml")

.github/scripts/create_issues.py

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,13 @@
22
import json
33
import os
44
import sys
5-
from urllib.parse import urlparse
65

76
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN")
87

9-
10-
def parse_github_url(url):
11-
"""Extract owner and repo from a GitHub URL."""
12-
try:
13-
path = urlparse(url).path.strip("/")
14-
return path.split("/")[-2:]
15-
except Exception as e:
16-
print(f"Error parsing GitHub URL: {e}")
17-
sys.exit(1)
18-
19-
20-
def issue_exists(owner, repo, title):
8+
def issue_exists(title):
219
"""Check if an issue with the same title already exists."""
2210
try:
23-
url = f"https://api.github.com/repos/polkadot-developers/polkadot-docs/issues"
11+
url = "https://api.github.com/repos/polkadot-developers/polkadot-docs/issues"
2412
headers = {
2513
"Authorization": f"token {GITHUB_TOKEN}",
2614
"Accept": "application/vnd.github.v3+json",
@@ -37,15 +25,14 @@ def issue_exists(owner, repo, title):
3725
print(f"Error checking for existing issues: {e}")
3826
sys.exit(1)
3927

40-
41-
def create_github_issue(owner, repo, title, body):
28+
def create_github_issue(title, body):
4229
"""Create a GitHub issue using the GitHub API."""
4330
try:
44-
if issue_exists(owner, repo, title):
31+
if issue_exists(title):
4532
print(f"Issue '{title}' already exists. Skipping creation.")
4633
return
4734

48-
url = f"https://api.github.com/repos/polkadot-developers/polkadot-docs/issues"
35+
url = "https://api.github.com/repos/polkadot-developers/polkadot-docs/issues"
4936
headers = {
5037
"Authorization": f"token {GITHUB_TOKEN}",
5138
"Accept": "application/vnd.github.v3+json",
@@ -57,41 +44,38 @@ def create_github_issue(owner, repo, title, body):
5744
print(f"Successfully created issue '{title}'")
5845
return
5946
else:
60-
print(
61-
f"Failed to create issue '{title}'. Status code: {response.status_code}"
62-
)
47+
print(f"Failed to create issue '{title}'. Status code: {response.status_code}")
6348
print(response.text)
6449
sys.exit(1)
6550
except Exception as e:
6651
print(f"Error creating issue: {e}")
6752
sys.exit(1)
6853

69-
7054
def main():
71-
# Check if GITHUB_TOKEN is set
7255
if not GITHUB_TOKEN:
7356
print("Error: GITHUB_TOKEN environment variable is not set.")
7457
sys.exit(1)
7558

76-
# Read the JSON file with outdated repositories
7759
try:
78-
with open("outdated_repositories.json", "r") as f:
60+
with open("outdated_dependencies.json", "r") as f:
7961
data = json.load(f)
8062
except Exception as e:
8163
print(f"Error reading JSON file: {e}")
8264
sys.exit(1)
8365

84-
for repo in data.get("outdated_repos", []):
85-
owner, repo_name = parse_github_url(repo["repository"])
86-
title = f"Update needed: {repo_name} ({repo['current_version']} -> {repo['latest_version']})"
87-
body = f"""A new release has been detected for {repo['repository']}.
88-
Current version: {repo['current_version']}
89-
Latest version: {repo['latest_version']}
66+
for dep in data.get("outdated_dependencies", []):
67+
title = f"Update needed: {dep['name']} ({dep['current_version']} -> {dep['latest_version']})"
68+
body = f"""A new release has been detected for {dep['name']}.
9069
91-
Please review the change log and update the documentation accordingly."""
70+
Category: {dep['category']}
71+
Current version: {dep['current_version']}
72+
Latest version: {dep['latest_version']}
9273
93-
create_github_issue(owner, repo_name, title, body)
74+
Latest release: [View here]({dep['latest_release_url']})
75+
76+
Please review the change log and update the documentation accordingly."""
9477

78+
create_github_issue(title, body)
9579

9680
if __name__ == "__main__":
97-
main()
81+
main()
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
name: Check Repositories
1+
name: Check Dependencies
22

33
on:
44
schedule: # Run every day at midnight.
55
- cron: '0 0 * * *'
66
workflow_dispatch: # Allows manual triggering of the workflow.
77

88
jobs:
9-
check-repositories:
9+
check-dependencies:
1010
runs-on: ubuntu-latest
1111
permissions:
1212
issues: write
@@ -24,12 +24,12 @@ jobs:
2424
python -m pip install --upgrade pip
2525
pip install requests pyyaml
2626
27-
- name: Check for Outdated Repositories
28-
id: check_repositories
27+
- name: Check for Outdated Dependencies
28+
id: check_dependencies
2929
run: |
30-
python .github/scripts/check_repositories.py
30+
python .github/scripts/check_dependencies.py
3131
32-
- name: Create GitHub Issues for Outdated Repositories
32+
- name: Create GitHub Issues for Outdated Dependencies
3333
env:
3434
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3535
run: |

.snippets/code/develop/toolkit/interoperability/asset-transfer-api/reference/tx-result.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,6 @@ A promise containing the result of constructing the transaction.
133133

134134
The `ConstructedFormat` type is a conditional type that returns a specific type based on the value of the TxResult `format` field.
135135

136-
- **Payload format** - if the format field is set to `'payload'`, the `ConstructedFormat` type will return a [`GenericExtrinsicPayload`](https://github.com/polkadot-js/api/blob/{{ dependencies.polkadot_js_api.version}}/packages/types/src/extrinsic/ExtrinsicPayload.ts#L83){target=\_blank}
136+
- **Payload format** - if the format field is set to `'payload'`, the `ConstructedFormat` type will return a [`GenericExtrinsicPayload`](https://github.com/polkadot-js/api/blob/{{ dependencies.repositories.polkadot_js_api.version}}/packages/types/src/extrinsic/ExtrinsicPayload.ts#L83){target=\_blank}
137137
- **Call format** - if the format field is set to `'call'`, the `ConstructedFormat` type will return a hexadecimal string (`0x${string}`). This is the encoded representation of the extrinsic call
138-
- **Submittable format** - if the format field is set to `'submittable'`, the `ConstructedFormat` type will return a [`SubmittableExtrinsic`](https://github.com/polkadot-js/api/blob/{{ dependencies.polkadot_js_api.version}}/packages/api-base/src/types/submittable.ts#L56){target=\_blank}. This is a Polkadot.js type that represents a transaction that can be submitted to the blockchain
138+
- **Submittable format** - if the format field is set to `'submittable'`, the `ConstructedFormat` type will return a [`SubmittableExtrinsic`](https://github.com/polkadot-js/api/blob/{{ dependencies.repositories.polkadot_js_api.version}}/packages/api-base/src/types/submittable.ts#L56){target=\_blank}. This is a Polkadot.js type that represents a transaction that can be submitted to the blockchain

develop/interoperability/test-and-debug.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ For scenarios where real blockchain state is required, [Chopsticks](/tutorials/p
2121

2222
Setting up a live network with multiple interconnected parachains for XCM testing can be complex and resource-intensive.
2323

24-
The [`xcm-emulator`](https://github.com/paritytech/polkadot-sdk/tree/{{dependencies.polkadot_sdk.stable_version}}/cumulus/xcm/xcm-emulator){target=\_blank} is a tool designed to simulate the execution of XCM programs using predefined runtime configurations. These configurations include those utilized by live networks like Kusama, Polkadot, and Asset Hub.
24+
The [`xcm-emulator`](https://github.com/paritytech/polkadot-sdk/tree/{{dependencies.repositories.polkadot_sdk.version}}/cumulus/xcm/xcm-emulator){target=\_blank} is a tool designed to simulate the execution of XCM programs using predefined runtime configurations. These configurations include those utilized by live networks like Kusama, Polkadot, and Asset Hub.
2525

2626
This tool enables testing of cross-chain message passing, providing a way to verify outcomes, weights, and side effects efficiently. It achieves this by utilizing mocked runtimes for both the relay chain and connected parachains, enabling developers to focus on message logic and configuration without needing a live network.
2727

@@ -44,27 +44,27 @@ The XCM Emulator provides both advantages and limitations when testing cross-cha
4444

4545
### How Does It Work?
4646

47-
The `xcm-emulator` provides macros for defining a mocked testing environment. Check all the existing macros and functionality in the [XCM Emulator source code](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.polkadot_sdk.stable_version}}/cumulus/xcm/xcm-emulator/src/lib.rs){target=\_blank}. The most important macros are:
47+
The `xcm-emulator` provides macros for defining a mocked testing environment. Check all the existing macros and functionality in the [XCM Emulator source code](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.repositories.polkadot_sdk.version}}/cumulus/xcm/xcm-emulator/src/lib.rs){target=\_blank}. The most important macros are:
4848

49-
- [**`decl_test_relay_chains`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.polkadot_sdk.stable_version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L355){target=\_blank} - defines runtime and configuration for the relay chains. Example:
49+
- [**`decl_test_relay_chains`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.repositories.polkadot_sdk.version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L355){target=\_blank} - defines runtime and configuration for the relay chains. Example:
5050

5151
```rust
5252
--8<-- 'https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/cumulus/parachains/integration-tests/emulated/chains/relays/westend/src/lib.rs:26:47'
5353
```
5454

55-
- [**`decl_test_parachains`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.polkadot_sdk.stable_version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L590){target=\_blank} - defines runtime and configuration for the parachains. Example:
55+
- [**`decl_test_parachains`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.repositories.polkadot_sdk.version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L590){target=\_blank} - defines runtime and configuration for the parachains. Example:
5656

5757
```rust
5858
--8<-- 'https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs:32:55'
5959
```
6060

61-
- [**`decl_test_bridges`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.polkadot_sdk.stable_version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L1178){target=\_blank} - creates bridges between chains, specifying the source, target, and message handler. Example:
61+
- [**`decl_test_bridges`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.repositories.polkadot_sdk.version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L1178){target=\_blank} - creates bridges between chains, specifying the source, target, and message handler. Example:
6262

6363
```rust
6464
--8<-- 'https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/cumulus/parachains/integration-tests/emulated/networks/rococo-westend-system/src/lib.rs:63:74'
6565
```
6666

67-
- [**`decl_test_networks`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.polkadot_sdk.stable_version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L916){target=\_blank} - defines a testing network with relay chains, parachains, and bridges, implementing message transport and processing logic. Example:
67+
- [**`decl_test_networks`**](https://github.com/paritytech/polkadot-sdk/blob/{{dependencies.repositories.polkadot_sdk.version}}/cumulus/xcm/xcm-emulator/src/lib.rs#L916){target=\_blank} - defines a testing network with relay chains, parachains, and bridges, implementing message transport and processing logic. Example:
6868

6969
```rust
7070
--8<-- 'https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/cumulus/parachains/integration-tests/emulated/networks/westend-system/src/lib.rs:38:52'
@@ -74,4 +74,4 @@ By leveraging these macros, developers can customize their testing networks by d
7474

7575
This framework enables thorough testing of runtime and cross-chain interactions, enabling developers to effectively design, test, and optimize cross-chain functionality.
7676

77-
To see a complete example of implementing and executing tests, refer to the [integration tests](https://github.com/paritytech/polkadot-sdk/tree/{{dependencies.polkadot_sdk.stable_version}}/cumulus/parachains/integration-tests/emulated){target=\_blank} in the Polkadot SDK repository.
77+
To see a complete example of implementing and executing tests, refer to the [integration tests](https://github.com/paritytech/polkadot-sdk/tree/{{dependencies.repositories.polkadot_sdk.version}}/cumulus/parachains/integration-tests/emulated){target=\_blank} in the Polkadot SDK repository.

develop/interoperability/xcm-config.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The executor is highly configurable, with the [XCM builder](https://paritytech.g
1515

1616
## XCM Executor Configuration
1717

18-
The `Config` trait defines the XCM executor’s configuration, which requires several associated types. Each type has specific trait bounds that the concrete implementation must fulfill. Some types, such as `RuntimeCall`, come with a default implementation in most cases, while others use the unit type `()` as the default. For many of these types, selecting the appropriate implementation carefully is crucial. Predefined solutions and building blocks can be adapted to your specific needs. These solutions can be found in the [`xcm-builder`](https://github.com/paritytech/polkadot-sdk/tree/{{dependencies.polkadot_sdk.stable_version}}/polkadot/xcm/xcm-builder){target=\_blank} folder.
18+
The `Config` trait defines the XCM executor’s configuration, which requires several associated types. Each type has specific trait bounds that the concrete implementation must fulfill. Some types, such as `RuntimeCall`, come with a default implementation in most cases, while others use the unit type `()` as the default. For many of these types, selecting the appropriate implementation carefully is crucial. Predefined solutions and building blocks can be adapted to your specific needs. These solutions can be found in the [`xcm-builder`](https://github.com/paritytech/polkadot-sdk/tree/{{dependencies.repositories.polkadot_sdk.version}}/polkadot/xcm/xcm-builder){target=\_blank} folder.
1919

2020
Each type is explained below, along with an overview of some of its implementations:
2121

0 commit comments

Comments
 (0)