Skip to content

Commit db58159

Browse files
committed
Merge branch 'main' into pr/T01iK/60
2 parents d5c83a2 + e43b885 commit db58159

11 files changed

Lines changed: 629 additions & 21 deletions
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
name: Format PR icons
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
pr_number:
7+
description: Pull request number to format
8+
required: true
9+
type: number
10+
11+
permissions:
12+
contents: write
13+
issues: read
14+
pull-requests: read
15+
16+
jobs:
17+
format:
18+
name: Format added icons
19+
runs-on: ubuntu-latest
20+
env:
21+
PR_NUMBER: ${{ inputs.pr_number }}
22+
GH_TOKEN: ${{ github.token }}
23+
steps:
24+
- name: Check out trusted formatter
25+
uses: actions/checkout@v7
26+
with:
27+
path: base
28+
ref: ${{ github.event.repository.default_branch }}
29+
fetch-depth: 1
30+
31+
- name: Get pull request head
32+
id: pr
33+
run: |
34+
gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json \
35+
headRefName,headRepository,headRefOid,maintainerCanModify \
36+
--jq '"head_ref=\(.headRefName)\nhead_repository=\(.headRepository.nameWithOwner)\nhead_sha=\(.headRefOid)\nmaintainer_can_modify=\(.maintainerCanModify)"' >> "$GITHUB_OUTPUT"
37+
38+
- name: Require maintainer edits
39+
if: >-
40+
steps.pr.outputs.head_repository != github.repository &&
41+
steps.pr.outputs.maintainer_can_modify != 'true'
42+
run: |
43+
echo "This PR does not allow edits from maintainers." >&2
44+
exit 1
45+
46+
- name: Check out pull request
47+
uses: actions/checkout@v7
48+
with:
49+
repository: ${{ steps.pr.outputs.head_repository }}
50+
ref: ${{ steps.pr.outputs.head_sha }}
51+
path: pr
52+
token: ${{ github.token }}
53+
54+
- name: Set up uv
55+
uses: astral-sh/setup-uv@v7
56+
with:
57+
enable-cache: true
58+
59+
- name: Set up Python
60+
uses: actions/setup-python@v7
61+
with:
62+
python-version: "3.13"
63+
64+
- name: Format added icons
65+
id: format
66+
run: |
67+
set -euo pipefail
68+
mkdir -p format/icons
69+
70+
mapfile -t added_icons < <(
71+
gh api --paginate "repos/${{ github.repository }}/pulls/$PR_NUMBER/files" \
72+
--jq '.[] | select(.status == "added" and (.filename | startswith("icons/"))) | .filename'
73+
)
74+
75+
if ((${#added_icons[@]} == 0)); then
76+
echo "No added icons found in PR #$PR_NUMBER."
77+
echo "changed=false" >> "$GITHUB_OUTPUT"
78+
exit 0
79+
fi
80+
81+
for path in "${added_icons[@]}"; do
82+
relative_path="${path#icons/}"
83+
if [[ "$relative_path" == */* ]]; then
84+
echo "Icon path must be directly under icons/: $path" >&2
85+
exit 1
86+
fi
87+
cp "pr/$path" "format/icons/$relative_path"
88+
done
89+
90+
(
91+
cd format
92+
uv run --project ../base --locked python ../base/format_icons.py
93+
)
94+
95+
changed=false
96+
for path in "${added_icons[@]}"; do
97+
relative_path="${path#icons/}"
98+
if ! cmp -s "format/icons/$relative_path" "pr/$path"; then
99+
cp "format/icons/$relative_path" "pr/$path"
100+
changed=true
101+
fi
102+
done
103+
echo "changed=$changed" >> "$GITHUB_OUTPUT"
104+
105+
- name: Commit formatted icons to pull request
106+
if: steps.format.outputs.changed == 'true'
107+
working-directory: pr
108+
env:
109+
HEAD_REF: ${{ steps.pr.outputs.head_ref }}
110+
PUSH_TOKEN: >-
111+
${{ steps.pr.outputs.head_repository == github.repository &&
112+
github.token ||
113+
secrets.MAINTAINER_TOKEN }}
114+
run: |
115+
set -euo pipefail
116+
if [[ -z "$PUSH_TOKEN" ]]; then
117+
echo "MAINTAINER_TOKEN is required to push to fork PR branches." >&2
118+
exit 1
119+
fi
120+
git config user.name "github-actions[bot]"
121+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
122+
git add -- icons
123+
git commit -m "Format icons"
124+
git -c "http.extraheader=AUTHORIZATION: bearer $PUSH_TOKEN" \
125+
push origin "HEAD:$HEAD_REF"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Validate plugin submission
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- "catalogue.json"
7+
- "icons/**"
8+
- "validate_submission.py"
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
validate:
15+
name: Validate plugin submission
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Check out pull request
19+
uses: actions/checkout@v7
20+
with:
21+
fetch-depth: 0
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v7
25+
with:
26+
python-version: "3.x"
27+
28+
- name: Validate catalogue submission
29+
env:
30+
GITHUB_TOKEN: ${{ github.token }}
31+
run: python validate_submission.py --base "${{ github.event.pull_request.base.sha }}" --head "${{ github.event.pull_request.head.sha }}"

‎.gitignore‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
.venv/
2-
uv.lock
3-
42
.ruff_cache/

‎README.md‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,4 @@ To submit your plugin to the OpenAction Marketplace, please follow these steps:
3030

3131
Once you have added your entry to the appropriate section, submit a Pull Request to this repository for review.
3232

33-
### Alternative Method (The Easy Way)
34-
35-
If you prefer an easier route, simply get in contact with us via Matrix, Discord, or by opening a GitHub Issue in this repository. Drop your plugin's repository URL, and a maintainer will add the plugin for you!
33+
Pull requests that change the catalogue are checked automatically. The check verifies the repository topic, manifest metadata, repository description, bundle ID, latest-release artifacts, icon format and resolution, section placement, and repository URL ordering before maintainers review the submission.

‎catalogue.json‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
"repository": "https://github.com/OpenActionPlugins/system",
3030
"description": "An OpenAction plugin for displaying system information"
3131
},
32+
"us.rivul.tacto": {
33+
"name": "Tacto Connect",
34+
"author": "Rivulus",
35+
"repository": "https://github.com/RivulusLive/tacto-connect-source",
36+
"description": "OpenAction plugin providing Tacto mobile and keyboard device support"
37+
},
3238
"com.ags.info_clock": {
3339
"name": "Info Clock",
3440
"author": "Alex Godinez",
@@ -146,6 +152,12 @@
146152
"ai_assisted": true
147153
}
148154
},
155+
"at.terrorwolf.helldivers2": {
156+
"name": "Helldivers2",
157+
"author": "Terrorwolf",
158+
"repository": "https://github.com/Terrorwolf01/opendeck-helldivers2",
159+
"description": "A Plugin Providing all Helldivers2 Stratagems."
160+
},
149161
"at.terrorwolf.linkwarden": {
150162
"name": "Linkwarden",
151163
"author": "Terrorwolf",

‎format_icons.py‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
import logging
12
import os
2-
from PIL import Image
33
import shutil
4-
import logging
54
from pathlib import Path
5+
6+
from PIL import Image
67
from tqdm import tqdm
78

89

10+
def same_pixels(a, b):
11+
"""Compare decoded pixels, ignoring PNG compression differences."""
12+
with Image.open(a) as ia, Image.open(b) as ib:
13+
return ia.size == ib.size and ia.convert("RGBA").tobytes() == ib.convert("RGBA").tobytes()
14+
15+
916
def process_images(input_dir, quality, palette_colors):
1017
total_files = 0
1118
modified_files = 0
@@ -54,12 +61,18 @@ def process_images(input_dir, quality, palette_colors):
5461
save_kwargs = {"compress_level": 9 - int((quality / 100) * 9), "optimize": True}
5562
img.save(temp_filepath, "PNG", **save_kwargs)
5663

57-
# Count as modified only if we actually created a new file
64+
# Keep the existing file if the pixels are identical (zlib output differs per platform)
65+
existing = os.path.join(input_dir, new_filename)
66+
if os.path.exists(existing) and same_pixels(temp_filepath, existing):
67+
os.remove(temp_filepath)
68+
new_size += os.path.getsize(existing)
69+
continue
70+
5871
modified_files += 1
5972
new_size += os.path.getsize(temp_filepath)
6073

61-
except Exception as e:
62-
logging.warning(f"Could not process {filename}: {str(e)}")
74+
except Exception as e: # noqa: BLE001
75+
logging.getLogger(__name__).warning(f"Could not process {filename}: {e!s}")
6376
continue
6477

6578
# Replace original files with processed ones
10.5 KB
Loading

‎icons/us.rivul.tacto.png‎

6.59 KB
Loading

‎update_descriptions.py‎

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import sys
21
import json
2+
import sys
33
import time
4-
import requests
54
from urllib.parse import urlparse
5+
6+
import requests
67
from tqdm import tqdm
78

89
# Constants
@@ -122,12 +123,6 @@ def main():
122123
global skip_update
123124
global wait_on_rate_limit
124125

125-
global failed
126-
global invalid_repo
127-
global performed
128-
global skipped
129-
global succeeded
130-
131126
for arg in args:
132127
if arg.lower() == "--skip-update":
133128
skip_update = True
@@ -142,12 +137,12 @@ def main():
142137
ids.append(arg)
143138
else:
144139
print(RED + "Unrecognised argument: " + arg + CLEAR)
145-
exit(1)
140+
sys.exit(1)
146141

147142
if len(ids) == 0:
148143
if start_from:
149144
print(RED + "No plugins to be updated." + CLEAR)
150-
exit(1)
145+
sys.exit(1)
151146
ids = all_ids
152147

153148
data = update_descriptions(data, ids)
@@ -166,7 +161,7 @@ def main():
166161
"Plugins succeeded or skipped: "
167162
+ str(succeeded + skipped)
168163
+ " "
169-
+ "{:.2f}%".format((succeeded + skipped) / performed * 100)
164+
+ f"{(succeeded + skipped) / performed * 100:.2f}%"
170165
)
171166

172167

0 commit comments

Comments
 (0)