55#
66# This script can be run and tested locally. To do so, you should check out
77# a second aws-sdk-kotlin repository so that you can work on the script and still
8- # run it without it immediately bailing for an unclean working tree (and to avoid creating
9- # temporary branches ).
8+ # run it without it immediately bailing for an unclean working tree (and to avoid mutating
9+ # your local repository ).
1010#
1111# Example:
12- # `aws-sdk-kotlin/` - the main repo you're working out of
12+ # `aws-sdk-kotlin/` - the main repo you're working out of <path-to-working-dir> below
1313# `/tmp/aws-sdk-kotlin/` - the repo you're testing against
1414#
15+ # Generate code using the current HEAD of the repository.
16+
1517# ```
16- # $ cd test /aws-sdk-kotlin
17- # $ ../../aws-sdk-kotlin /.github/scripts/codegen-diff-revisions.py . <some commit hash to diff against>
18+ # $ cd /tmp /aws-sdk-kotlin
19+ # $ <path-to-working-dir> /.github/scripts/codegen-diff-revisions.py codegen --bootstrap +s3,+dynamodb
1820# ```
1921#
20- # It will diff the generated code from HEAD against any commit hash you feed it. If you want to test
21- # a specific range, change the HEAD of the test repository.
2222#
23- # This script requires `diff2html-cli` to be installed from NPM:
23+ # Generate diffs
24+ #
2425# ```
25- # $ npm install -g [email protected] 26+ # $ cd /tmp/aws-sdk-kotlin
27+ # HEAD_SHA=$(git rev-parse <my-head-sha>)
28+ # BASE_SHA=$(git rev-parse <my-base-branch>)
29+ # HEAD_BRANCH_NAME="__tmp-localonly-head"
30+ # BASE_BRANCH_NAME="__tmp-localonly-base"
31+ #
32+ # <path-to-working-dir>/.github/scripts/codegen-diff-revisions.py --head-sha $HEAD_SHA generate-diffs --base-sha $BASE_SHA $BASE_BRANCH_NAME $HEAD_BRANCH_NAME
33+ # ```
34+ #
35+ # This script requires `difftags` to be installed from the smithy-rs repository. This requires installing a working
36+ # rust toolchain (cargo, rustc, etc).
37+ # ```
38+ # curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
39+ # ```
40+ #
41+ # Install difftags from smithy-rs
42+ # ```
43+ # git clone --depth 1 https://github.com/smithy-lang/smithy-rs.git
44+ # cd smithy-rs/tools/ci-build/difftags
45+ # cargo install --path .
46+ # difftags -h
2647# ```
2748# Make sure the local version matches the version referenced from the GitHub Actions workflow.
2849
3354import tempfile
3455import shlex
3556
36- OUTPUT_PATH = "tmp-codegen-diff/ "
57+ OUTPUT_PATH = "tmp-codegen-diff"
3758
3859COMMIT_AUTHOR_NAME = "GitHub Action (generated codegen diff)"
3960COMMIT_AUTHOR_EMAIL = "[email protected] " @@ -103,40 +124,7 @@ def generate_and_commit_generated_code(sha, services_to_bootstrap):
103124 run (f"git -c 'user.name={ COMMIT_AUTHOR_NAME } ' -c 'user.email={ COMMIT_AUTHOR_EMAIL } ' commit --no-verify -m 'Generated code for { sha } ' --allow-empty" )
104125
105126
106- # Writes an HTML template for diff2html so that we can add contextual information
107- def write_html_template (title , subtitle , tmp_file ):
108- tmp_file .writelines (map (lambda line : line .encode (), [
109- "<!doctype html>" ,
110- "<html>" ,
111- "<head>" ,
112- ' <metadata charset="utf-8">' ,
113- f' <title>Codegen diff for the { title } : { subtitle } </title>' ,
114- ' <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/github.min.css" / >' ,
115- ' <!--diff2html-css-->' ,
116- ' <!--diff2html-js-ui-->' ,
117- ' <script>' ,
118- ' document.addEventListener("DOMContentLoaded", () => {' ,
119- ' const targetElement = document.getElementById("diff");' ,
120- ' const diff2htmlUi = new Diff2HtmlUI(targetElement);' ,
121- ' //diff2html-fileListToggle' ,
122- ' //diff2html-synchronisedScroll' ,
123- ' //diff2html-highlightCode' ,
124- ' });' ,
125- ' </script>' ,
126- "</head>" ,
127- '<body style="font-family: sans-serif;">' ,
128- f" <h1>Codegen diff for the { title } </h1>" ,
129- f" <p>{ subtitle } </p>" ,
130- ' <div id="diff">' ,
131- ' <!--diff2html-diff-->' ,
132- ' </div>' ,
133- "</body>" ,
134- "</html>" ,
135- ]))
136- tmp_file .flush ()
137-
138-
139- def make_diff (opts , title , path_to_diff , suffix , ignore_whitespace ):
127+ def make_diff (opts , title , path_to_diff , outsubdir , ignore_whitespace ):
140128 base_sha = opts .base_sha
141129 head_sha = opts .head_sha
142130 ws_flag = "-b" if ignore_whitespace else ""
@@ -146,32 +134,36 @@ def make_diff(opts, title, path_to_diff, suffix, ignore_whitespace):
146134 eprint (f"No diff output for { base_sha } ..{ head_sha } " )
147135 return None
148136
149- run ( f'mkdir -p { OUTPUT_PATH } /{ base_sha } /{ head_sha } ' )
150- dest_path = f" { base_sha } /{ head_sha } /diff- { suffix } .html"
137+ dest_path = f" { base_sha } /{ head_sha } /{ outsubdir } "
138+ run ( f'mkdir -p { OUTPUT_PATH } /{ dest_path } ' )
151139 whitespace_context = "(ignoring whitespace)" if ignore_whitespace else ""
152- with tempfile .NamedTemporaryFile () as tmp_file :
153- write_html_template (title , f"rev. { head_sha } { whitespace_context } " , tmp_file )
154-
155- # Generate HTML diff. This uses the diff2html-cli, which defers to `git diff` under the hood.
156- # All arguments after the first `--` go to the `git diff` command.
157- diff_cmd = f"diff2html -s line -f html -d word -i command --hwt " \
158- f"{ tmp_file .name } -F { OUTPUT_PATH } /{ dest_path } -- " \
159- f"-U20 { ws_flag } { opts .base_branch } { opts .head_branch } -- { path_to_diff } "
140+
141+ with tempfile .NamedTemporaryFile (mode = 'w' ) as tmp_file :
142+ diff_cmd = f"git diff -U30 { ws_flag } { opts .base_branch } { opts .head_branch } -- { path_to_diff } "
160143 eprint (f"Running diff cmd: { diff_cmd } " )
161- run (diff_cmd )
144+ output = get_cmd_output (diff_cmd )
145+ tmp_file .write (output )
146+
147+ subtitle = f"rev. { base_sha } ..{ head_sha } { whitespace_context } "
148+ generate_html_cmd = f"difftags --title \" { title } \" --subtitle \" { subtitle } \" --output-dir { OUTPUT_PATH } /{ dest_path } { tmp_file .name } "
149+ eprint (f"Running generate html cmd: { generate_html_cmd } " )
150+ run (generate_html_cmd )
151+
162152 return dest_path
163153
164154
165155def diff_link (diff_text , empty_diff_text , diff_location , alternate_text , alternate_location ):
166156 if diff_location is None :
167157 return empty_diff_text
168158
169- return f"[{ diff_text } ]({ CDN_URL } /codegen-diff/{ diff_location } ) ([{ alternate_text } ]({ CDN_URL } /codegen-diff/{ alternate_location } ))"
159+ return f"[{ diff_text } ]({ CDN_URL } /codegen-diff/{ diff_location } /index.html ) ([{ alternate_text } ]({ CDN_URL } /codegen-diff/{ alternate_location } /index.html ))"
170160
171161
172162def make_diffs (opts ):
173- sdk_ws = make_diff (opts , 'AWS SDK' , f'{ OUTPUT_PATH } /services' , 'aws-sdk' , ignore_whitespace = False )
174- sdk_no_ws = make_diff (opts , 'AWS SDK' , f'{ OUTPUT_PATH } /services' , 'aws-sdk-ignore-ws' , ignore_whitespace = True )
163+ path_to_diff = f"{ OUTPUT_PATH } /services"
164+
165+ sdk_ws = make_diff (opts , 'AWS SDK' , path_to_diff , "aws-sdk" , ignore_whitespace = False )
166+ sdk_no_ws = make_diff (opts , 'AWS SDK' , path_to_diff , "aws-sdk-ignore-ws" , ignore_whitespace = True )
175167 sdk_links = diff_link ('AWS SDK' , 'No codegen difference in the AWS SDK' , sdk_ws , 'ignoring whitespace' , sdk_no_ws )
176168
177169 return f'A new generated diff is ready to view.\\ n\\ n- { sdk_links } \\ n'
0 commit comments