Skip to content

Commit d706713

Browse files
committed
Merge branch 'main' into fix_classifyFence_initialization
2 parents 73f3efd + 39647c3 commit d706713

456 files changed

Lines changed: 6012 additions & 19297 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/valid-tags.txt

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
[GEN]
2-
[ZH]
3-
[BFME]
4-
[CMAKE]
5-
[GITHUB]
6-
[CORE]
7-
[LINUX]
1+
bugfix
2+
build
3+
chore
4+
ci
5+
docs
6+
fix
7+
feat
8+
perf
9+
refactor
10+
revert
11+
style
12+
test
13+
tweak
14+
unify
Lines changed: 134 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
name: Validate Pull Request
22

3+
# Minimal permissions: read code, write PR comments.
34
permissions:
45
contents: read
56
pull-requests: write
67

8+
# Uses pull_request_target to access secrets for PR comments on forks.
79
on:
8-
pull_request:
10+
pull_request_target:
911
branches:
1012
- main
1113
types:
@@ -14,83 +16,171 @@ on:
1416
- synchronize
1517
- reopened
1618

19+
# Avoid racing on PR comments when multiple events fire quickly.
20+
concurrency:
21+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
22+
cancel-in-progress: true
23+
1724
jobs:
1825
validate-title-and-commits:
1926
name: Validate Title and Commits
20-
runs-on: ubuntu-latest
21-
timeout-minutes: 5
27+
runs-on: ubuntu-slim
28+
timeout-minutes: 3
29+
30+
# Expose context as env vars to avoid inline ${{ }} in run blocks (injection hardening).
31+
env:
32+
PR_NUMBER: ${{ github.event.pull_request.number }}
33+
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
34+
BASE_REF: ${{ github.base_ref }}
35+
REPO: ${{ github.repository }}
2236

2337
steps:
24-
- name: Checkout Code
38+
- name: Checkout base branch
2539
uses: actions/checkout@v4
40+
with:
41+
ref: ${{ github.base_ref }}
42+
fetch-depth: 0
43+
44+
- name: Fetch PR head
45+
run: git fetch origin "$PR_HEAD_SHA"
2646

2747
- name: Load valid tags
2848
id: load-tags
2949
run: |
30-
if [ ! -f ./.github/workflows/valid-tags.txt ]; then
31-
echo "::error::.github/workflows/valid-tags.txt file not found"
50+
TAGS_FILE=".github/workflows/valid-tags.txt"
51+
52+
if [ ! -f "$TAGS_FILE" ]; then
53+
echo "::error::$TAGS_FILE file not found"
3254
exit 1
3355
fi
3456
35-
echo "**Valid tags**: $(cat ./.github/workflows/valid-tags.txt | tr '\n' ',' | sed 's/,/, /g' | sed 's/, $//')" >> $GITHUB_STEP_SUMMARY
57+
# Normalize line endings and remove empty lines
58+
TAGS=$(tr -d '\r' < "$TAGS_FILE" | sed '/^$/d')
3659
37-
TAG_REGEX=$(sed 's/[]\/$*.^|[]/\\&/g' ./.github/workflows/valid-tags.txt | paste -sd "|" -)
60+
VALID_TAGS=$(echo "$TAGS" | tr '\n' ',' | sed 's/,$//; s/,/, /g')
61+
echo "**Valid tags**: $VALID_TAGS" >> "$GITHUB_STEP_SUMMARY"
62+
echo "valid-tags=$VALID_TAGS" >> "$GITHUB_OUTPUT"
3863
39-
# Matches:
40-
# 1) One or more valid tags at the beginning, directly adjacent, followed by at least one space, then text
41-
# 2) Text that does not start with '[' (i.e. no tags)
42-
echo "regex=^((($TAG_REGEX)){1,}[[:space:]]+.*|[^[]+.*)$" >> $GITHUB_OUTPUT
64+
TAG_REGEX=$(echo "$TAGS" | paste -sd "|" -)
4365
44-
echo "Built the regex: ^((($TAG_REGEX)){1,}[[:space:]]+.*|[^[]+.*)$"
66+
# Matches:
67+
# Conventional commit: type or type(scope) followed by colon, single space, then uppercase text
68+
REGEX="^(($TAG_REGEX)(\\([^)]+\\))?: [A-Z].*)$"
69+
echo "regex=$REGEX" >> "$GITHUB_OUTPUT"
70+
echo "Built the regex: $REGEX"
4571
4672
- name: Validate PR title
47-
id: validate_title
73+
id: validate-title
74+
env:
75+
REGEX: ${{ steps.load-tags.outputs.regex }}
4876
run: |
49-
echo "### Validate PR Title" >> $GITHUB_STEP_SUMMARY
50-
REGEX="${{ steps.load-tags.outputs.regex }}"
77+
echo "### Validate PR Title" >> "$GITHUB_STEP_SUMMARY"
5178
TITLE=$(jq -r '.pull_request.title // "No title found"' "$GITHUB_EVENT_PATH")
5279
53-
ESCAPED_TITLE=$(echo "$TITLE" | sed 's/["\`\\$]/\\&/g')
54-
5580
if [[ ! "$TITLE" =~ $REGEX ]]; then
56-
echo "- ❌ PR title \"$ESCAPED_TITLE\" is invalid." >> $GITHUB_STEP_SUMMARY
57-
echo "TITLE_VALID=false" >> $GITHUB_OUTPUT
81+
echo "- ❌ PR title \"$TITLE\" is invalid." >> "$GITHUB_STEP_SUMMARY"
82+
echo "title-valid=false" >> "$GITHUB_OUTPUT"
83+
DELIM="TITLE_EOF_$(openssl rand -hex 8)"
84+
{
85+
echo "INVALID_TITLE<<$DELIM"
86+
echo "$TITLE"
87+
echo "$DELIM"
88+
} >> "$GITHUB_ENV"
5889
else
59-
echo "- ✅ PR title \"$ESCAPED_TITLE\" is valid." >> $GITHUB_STEP_SUMMARY
60-
echo "TITLE_VALID=true" >> $GITHUB_OUTPUT
90+
echo "- ✅ PR title \"$TITLE\" is valid." >> "$GITHUB_STEP_SUMMARY"
91+
echo "title-valid=true" >> "$GITHUB_OUTPUT"
6192
fi
6293
6394
- name: Validate PR commits
64-
id: validate_commits
95+
id: validate-commits
96+
if: (success() || failure()) && steps.load-tags.outcome == 'success'
97+
env:
98+
REGEX: ${{ steps.load-tags.outputs.regex }}
6599
run: |
66-
echo "### Validate PR Commits" >> $GITHUB_STEP_SUMMARY
67-
REGEX="${{ steps.load-tags.outputs.regex }}"
68-
git fetch --prune --unshallow origin ${{ github.base_ref }}
69-
COMMITS=$(git log origin/${{ github.base_ref }}..HEAD --pretty=format:"%s" --no-merges)
100+
echo "### Validate PR Commits" >> "$GITHUB_STEP_SUMMARY"
101+
COMMITS=$(git log "$BASE_REF".."$PR_HEAD_SHA" --pretty=format:"%s" --no-merges)
70102
71-
INVALID_COMMITS=0
72-
73-
while read -r COMMIT_MSG; do
74-
if [[ -z "$COMMIT_MSG" ]]; then
75-
continue
76-
fi
77-
ESCAPED_MSG=$(echo "$COMMIT_MSG" | sed 's/["\`\\$]/\\&/g')
78-
if [[ ! "$COMMIT_MSG" =~ $REGEX ]]; then
79-
echo "- ❌ Commit message \"$ESCAPED_MSG\" is invalid." >> $GITHUB_STEP_SUMMARY
80-
INVALID_COMMITS=$((INVALID_COMMITS+1))
81-
else
82-
echo "- ✅ Commit message \"$ESCAPED_MSG\" is valid." >> $GITHUB_STEP_SUMMARY
103+
if [[ -z "$COMMITS" ]]; then
104+
echo "- ⚠️ No non-merge commits found." >> "$GITHUB_STEP_SUMMARY"
105+
echo "commits-valid=true" >> "$GITHUB_OUTPUT"
106+
exit 0
83107
fi
108+
109+
INVALID_COMMITS=0
110+
INVALID_LIST=""
111+
112+
while IFS= read -r COMMIT_MSG; do
113+
if [[ -z "$COMMIT_MSG" ]]; then
114+
continue
115+
fi
116+
if [[ ! "$COMMIT_MSG" =~ $REGEX ]]; then
117+
echo "- ❌ Commit message \"$COMMIT_MSG\" is invalid." >> "$GITHUB_STEP_SUMMARY"
118+
INVALID_COMMITS=$((INVALID_COMMITS + 1))
119+
SANITIZED_MSG=$(echo "$COMMIT_MSG" | tr -d '\`')
120+
INVALID_LIST="${INVALID_LIST}- \`${SANITIZED_MSG}\`"$'\n'
121+
else
122+
echo "- ✅ Commit message \"$COMMIT_MSG\" is valid." >> "$GITHUB_STEP_SUMMARY"
123+
fi
84124
done <<< "$COMMITS"
85125
86126
if [[ $INVALID_COMMITS -gt 0 ]]; then
87-
echo "COMMITS_VALID=false" >> $GITHUB_OUTPUT
127+
echo "commits-valid=false" >> "$GITHUB_OUTPUT"
128+
DELIM="COMMITS_EOF_$(openssl rand -hex 8)"
129+
{
130+
echo "INVALID_COMMITS_LIST<<$DELIM"
131+
printf '%s' "$INVALID_LIST"
132+
echo "$DELIM"
133+
} >> "$GITHUB_ENV"
88134
else
89-
echo "COMMITS_VALID=true" >> $GITHUB_OUTPUT
135+
echo "commits-valid=true" >> "$GITHUB_OUTPUT"
90136
fi
91137
92-
- name: Validation return code
138+
# Always clean up old failure comments, even when validation now passes.
139+
- name: Delete stale bot comments
140+
if: always() && steps.load-tags.outcome == 'success'
141+
env:
142+
GH_TOKEN: ${{ github.token }}
93143
run: |
94-
if [[ "${{ steps.validate_title.outputs.TITLE_VALID }}" != "true" || "${{ steps.validate_commits.outputs.COMMITS_VALID }}" != "true" ]]; then
95-
exit 1
144+
gh api --paginate "repos/$REPO/issues/$PR_NUMBER/comments" \
145+
--jq '.[] | select(.user.login == "github-actions[bot]" and (.body | startswith("### ⚠️ Title/Commit Validation Failed"))) | .id' \
146+
| while read -r comment_id; do
147+
gh api -X DELETE "repos/$REPO/issues/comments/$comment_id" || true
148+
done || true
149+
150+
# Post a new failure comment with details on what's wrong.
151+
- name: Comment on PR if validation failed
152+
if: always() && steps.load-tags.outcome == 'success' && (steps.validate-title.outputs.title-valid != 'true' || steps.validate-commits.outputs.commits-valid != 'true')
153+
env:
154+
GH_TOKEN: ${{ github.token }}
155+
VALID_TAGS_RAW: ${{ steps.load-tags.outputs.valid-tags }}
156+
run: |
157+
VALID_TAGS=$(echo "$VALID_TAGS_RAW" | sed 's/[^, ][^, ]*/`&`/g')
158+
BODY="### ⚠️ Title/Commit Validation Failed"
159+
160+
if [[ -n "$INVALID_TITLE" ]]; then
161+
SANITIZED_TITLE=$(echo "$INVALID_TITLE" | tr -d '\`')
162+
BODY="$BODY"$'\n\n'"**Invalid PR title:**"
163+
BODY="$BODY"$'\n'"- \`$SANITIZED_TITLE\`"
164+
fi
165+
166+
if [[ -n "$INVALID_COMMITS_LIST" ]]; then
167+
BODY="$BODY"$'\n\n'"**Invalid commit messages:**"
168+
BODY="$BODY"$'\n'"$INVALID_COMMITS_LIST"
96169
fi
170+
171+
BODY="$BODY"$'\n'"PR titles and commit messages must follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) format:"
172+
BODY="$BODY"$'\n'"\`\`\`"
173+
BODY="$BODY"$'\n'"type: Description"
174+
BODY="$BODY"$'\n'"type(scope): Description"
175+
BODY="$BODY"$'\n'"\`\`\`"
176+
BODY="$BODY"$'\n\n'"**Allowed types:** $VALID_TAGS"
177+
BODY="$BODY"$'\n\n'"See [CONTRIBUTING.md](https://github.com/$REPO/blob/$BASE_REF/CONTRIBUTING.md#pull-request-documentation) for details."
178+
179+
gh pr comment "$PR_NUMBER" \
180+
--repo "$REPO" \
181+
--body "$BODY"
182+
183+
# Separate fail step so the comment is always posted before the job fails.
184+
- name: Fail if validation did not pass
185+
if: always() && steps.load-tags.outcome == 'success' && (steps.validate-title.outputs.title-valid != 'true' || steps.validate-commits.outputs.commits-valid != 'true')
186+
run: exit 1

CONTRIBUTING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Optionally, the pull request number can be appended to the comment. This can onl
8383

8484
### Pull request documentation
8585

86-
The title of a new Pull Request, and/or commit(s) within, begins with a [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) tag. The tag is followed by a concise and descriptive sentence about the change and/or commit, beginning with an upper case letter and ending without a dot. The sentence ideally begins with a word that describes the action that the change takes, for example `fix *this*`, `change *that*`, `add *those*`, `refactor *thing*`.
86+
The title of a new Pull Request, and/or commit(s) within, begins with a [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) tag. The tag is followed by a concise and descriptive sentence about the change and/or commit, beginning with an upper case letter and ending without a dot. The sentence ideally begins with a word that describes the action that the change takes, for example `Fix *this*`, `Change *that*`, `Add *those*`, `Refactor *thing*`.
8787

8888
Allowed (extended) commit title types are:
8989
```
@@ -96,6 +96,7 @@ fix:
9696
feat:
9797
perf:
9898
refactor:
99+
revert:
99100
style:
100101
test:
101102
tweak:
@@ -106,7 +107,7 @@ For the optional scope behind the type pick a suitable word that describes the o
106107

107108
Good:
108109
```
109-
bugfix(system): fix uninitialized memory access in Get_OS_Info
110+
bugfix(system): Fix uninitialized memory access in Get_OS_Info
110111
```
111112

112113
Bad:

Core/GameEngine/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ set(GAMEENGINE_SRC
239239
# Include/GameLogic/AIDock.h
240240
# Include/GameLogic/AIGuard.h
241241
# Include/GameLogic/AIGuardRetaliate.h
242-
# Include/GameLogic/AIPathfind.h
242+
Include/GameLogic/AIPathfind.h
243243
# Include/GameLogic/AIPlayer.h
244244
# Include/GameLogic/AISkirmishPlayer.h
245245
# Include/GameLogic/AIStateMachine.h
@@ -843,7 +843,7 @@ set(GAMEENGINE_SRC
843843
# Source/GameLogic/AI/AIGroup.cpp
844844
# Source/GameLogic/AI/AIGuard.cpp
845845
# Source/GameLogic/AI/AIGuardRetaliate.cpp
846-
# Source/GameLogic/AI/AIPathfind.cpp
846+
Source/GameLogic/AI/AIPathfind.cpp
847847
# Source/GameLogic/AI/AIPlayer.cpp
848848
# Source/GameLogic/AI/AISkirmishPlayer.cpp
849849
# Source/GameLogic/AI/AIStates.cpp
@@ -1138,6 +1138,7 @@ set(GAMEENGINE_SRC
11381138
Source/GameNetwork/NetCommandWrapperList.cpp
11391139
Source/GameNetwork/NetMessageStream.cpp
11401140
Source/GameNetwork/NetPacket.cpp
1141+
Source/GameNetwork/NetPacketStructs.cpp
11411142
Source/GameNetwork/Network.cpp
11421143
Source/GameNetwork/NetworkUtil.cpp
11431144
Source/GameNetwork/Transport.cpp

GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h renamed to Core/GameEngine/Include/GameLogic/AIPathfind.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,14 @@ class PathfindCell
326326

327327
UnsignedInt costSoFar( PathfindCell *parent );
328328

329+
#if RETAIL_COMPATIBLE_PATHFINDING
330+
// Forward insertion sort that is 100% retail compatible
331+
void forwardInsertionSortRetailCompatible(PathfindCellList& list);
332+
#endif
333+
334+
// Forward insertion sort, in ascending cost order
335+
void forwardInsertionSort(PathfindCellList& list);
336+
329337
/// put self on "open" list in ascending cost order
330338
void putOnSortedOpenList( PathfindCellList &list );
331339

@@ -652,7 +660,7 @@ class Pathfinder : PathfindServicesInterface, public Snapshot
652660
void loadPostProcess();
653661

654662
Bool clientSafeQuickDoesPathExist( const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to ); ///< Can we build any path at all between the locations (terrain & buildings check - fast)
655-
Bool clientSafeQuickDoesPathExistForUI( const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to ); ///< Can we build any path at all between the locations (terrain onlyk - fast)
663+
Bool clientSafeQuickDoesPathExistForUI( const LocomotorSet& locomotorSet, const Coord3D *from, const Coord3D *to ); ///< Can we build any path at all between the locations (terrain only - fast)
656664
Bool slowDoesPathExist( Object *obj, const Coord3D *from,
657665
const Coord3D *to, ObjectID ignoreObject=INVALID_ID ); ///< Can we build any path at all between the locations (terrain, buildings & units check - slower)
658666

Core/GameEngine/Include/GameNetwork/GameMessageParser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class GameMessageParser : public MemoryPoolObject
7878
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessageParser, "GameMessageParser")
7979
public:
8080
GameMessageParser();
81-
GameMessageParser(GameMessage *msg);
81+
GameMessageParser(const GameMessage *msg);
8282
//virtual ~GameMessageParser();
8383

8484
GameMessageParserArgumentType *getFirstArgumentType();

0 commit comments

Comments
 (0)