FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
scala-cli/.github/scripts/process_release_notes.sc at main · VirtusLab/scala-cli · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
VirtusLab
/
scala-cli
Public
Notifications
You must be signed in to change notification settings
Fork
166
Star
641
Code
Issues
302
Pull requests
11
Discussions
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Discussions
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
scala-cli
/
.github
/
scripts
/
process_release_notes.sc
Copy path
More file actions
More file actions
Latest commit
History
History
History
executable file
·
151 lines (137 loc) · 6.16 KB
Breadcrumbs
scala-cli
/
.github
/
scripts
/
process_release_notes.sc
Copy path
File metadata and controls
executable file
·
151 lines (137 loc) · 6.16 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!
/usr/bin/env -S scala-cli shebang
//>
using
scala
3
//>
using
toolkit
default
//>
using
options
-Werror
-Wunused:all
case
class
Replacement
(
find
:
String
,
replace
:
String
)
//
Hardcoded regex replacements for processing release notes
//
These transform GitHub-idiomatic syntax to website-compatible Markdown
val
replacements
:
Seq
[
Replacement
]
=
Seq
(
//
1. Contributor link: Transform "by @user in" to "by [@user](https://github.com/user) in"
//
Excludes bots: dependabot, github-actions, scala-steward
//
Only matches if not already a link (negative lookahead to avoid matching already-formatted entries)
//
Must come BEFORE PR link pattern to avoid interference
//
The pattern stops at the first " in" and doesn't match if there's a formatted link before it
Replacement
(
find
=
"
by @(?!dependabot
\\
[bot
\\
]|github-actions
\\
[bot
\\
]|scala-steward)([^
\\
[
\\
]]+?) in(?!.*
\\
[@.*?
\\
]
\\
()
"
,
replace
=
"
by [@$1](https://github.com/$1) in
"
),
//
2. New contributor link: Transform "@user made" to "[@user](https://github.com/user) made"
//
Excludes bots: dependabot, github-actions, scala-steward
//
Only matches if not already a link (negative lookbehind and lookahead to avoid matching already-formatted entries)
Replacement
(
find
=
"
(?<!
\\
[)@(?!dependabot
\\
[bot
\\
]|github-actions
\\
[bot
\\
]|scala-steward)(.*?) made(?!.*
\\
]
\\
()
"
,
replace
=
"
[@$1](https://github.com/$1) made
"
),
//
3. PR link: Transform "in https://github.com/VirtusLab/scala-cli/pull/123" to "in [#123](https://github.com/VirtusLab/scala-cli/pull/123)"
//
Only matches if not already formatted as a markdown link
Replacement
(
find
=
"
in https://github
\\
.com/VirtusLab/scala-cli/pull/(.*?)$(?!.*
\\
]
\\
()
"
,
replace
=
"
in [#$1](https://github.com/VirtusLab/scala-cli/pull/$1)
"
)
)
def
applyReplacements
(
text
:
String
,
replacements
:
Seq
[
Replacement
])
:
String
=
{
//
Process line by line to handle $ end-of-line anchors correctly
val
lines
=
text.linesIterator.toSeq
val
processedLines
=
lines.map { line
=>
replacements.foldLeft(line) { (current, replacement)
=>
try
val
regex
=
replacement.find.r
//
Manually handle replacement to avoid issues with $ in replacement strings
var
result
=
current
val
matches
=
regex.findAllMatchIn(current).toSeq.reverse
//
Process from end to avoid offset issues
for
matchData
<-
matches
do
//
Build replacement string by substituting $1, $2, etc. with actual group values
var
replacementText
=
replacement.replace
//
Replace $1, $2, etc. with actual group values (in reverse order to avoid replacing $11 when we mean $1)
for
i
<-
matchData.groupCount to
1
by
-
1
do
val
groupValue
=
if
matchData.group(i)
!=
null
then
matchData.group(i)
else
"
"
replacementText
=
replacementText.replace(
s
"
$$
$i
"
, groupValue)
//
Replace the matched portion
result
=
result.substring(
0
, matchData.start)
+
replacementText
+
result.substring(matchData.end)
result
catch
case
e
:
Exception
=>
System
.err.println(
s
"
Warning: Failed to apply regex '
${replacement.find}
':
${e.getMessage}
"
)
if
System
.getenv(
"
DEBUG
"
)
==
"
true
"
then
e.printStackTrace()
current
}
}
//
Rejoin lines with newlines, preserving original line endings
val
lineEnding
=
if
text.contains(
"
\r\n
"
)
then
"
\r\n
"
else
if
text.contains(
"
\n
"
)
then
"
\n
"
else
System
.lineSeparator()
processedLines.mkString(lineEnding)
+
(
if
text.endsWith(
"
\n
"
)
||
text.endsWith(
"
\r\n
"
)
then
lineEnding
else
"
"
)
}
def
printUsageMessage
()
:
Unit
=
{
println(
"
Usage: process_release_notes.sc <command> <file>
"
)
println(
"
Commands:
"
)
println(
"
apply - Apply regexes to the file (modifies in place)
"
)
println(
"
check - Check if file needs regexes applied (exits with error if needed)
"
)
println(
"
verify - Verify file has regexes applied (exits with error if not)
"
)
}
if
args.length
<
2
then
println(
s
"
Error: too few arguments:
${args.length}
"
)
printUsageMessage()
sys.exit(
1
)
val
command
=
args(
0
)
val
filePath
=
os.
Path
(args(
1
), os.pwd)
if
!
os.exists(filePath)
then
println(
s
"
Error: file does not exist:
$filePath
"
)
sys.exit(
1
)
if
System
.getenv(
"
DEBUG
"
)
==
"
true
"
then
println(
s
"
Loaded
${replacements.length}
replacement patterns
"
)
replacements.zipWithIndex.foreach {
case
(r, i)
=>
println(
s
"
Pattern
${i
+
1
}
: Find='
${r.find}
', Replace='
${r.replace}
'
"
)
}
val
originalContent
=
os.read(filePath)
val
transformedContent
=
applyReplacements(originalContent, replacements)
command
match
case
"
apply
"
=>
os.write.over(filePath, transformedContent)
println(
s
"
Applied regexes to:
$filePath
"
)
case
"
check
"
=>
if
originalContent
!=
transformedContent
then
println(
s
"
Error: File
$filePath
needs regexes applied
"
)
println(
"
Run: .github/scripts/process_release_notes.sc apply <file>
"
)
sys.exit(
1
)
else
println(
s
"
File
$filePath
is already processed correctly
"
)
sys.exit(
0
)
case
"
verify
"
=>
//
Check for patterns that should have been transformed
//
All patterns have negative lookaheads to avoid matching already-formatted entries
val
patternsToCheck
=
replacements
val
needsTransformation
=
patternsToCheck.exists { replacement
=>
try
val
regex
=
replacement.find.r
regex.findFirstIn(originalContent).isDefined
catch
case
_
:
Exception
=>
false
}
if
needsTransformation
then
println(
s
"
Error: File
$filePath
contains patterns that need transformation
"
)
println(
"
The following patterns were found that should be transformed:
"
)
patternsToCheck.foreach { replacement
=>
try
val
regex
=
replacement.find.r
if
regex.findFirstIn(originalContent).isDefined
then
println(
s
"
- Pattern:
${replacement.find}
"
)
catch
case
_
:
Exception
=>
()
}
println(
"
Run: .github/scripts/process_release_notes.sc apply <file>
"
)
sys.exit(
1
)
else
println(
s
"
File
$filePath
is properly formatted
"
)
sys.exit(
0
)
case
_
=>
println(
s
"
Error: unknown command:
$command
"
)
printUsageMessage()
sys.exit(
1
)
Back
|
FazBrowse Home
|
New Git URL