Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
8fbd8706
Unverified
Commit
8fbd8706
authored
Sep 23, 2022
by
godofredoc
Committed by
GitHub
Sep 23, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a script to post-process docs. (#112228)
parent
e1671628
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
323 additions
and
1 deletion
+323
-1
post_process_docs.dart
dev/bots/post_process_docs.dart
+155
-0
pubspec.yaml
dev/bots/pubspec.yaml
+3
-1
post_process_docs_test.dart
dev/bots/test/post_process_docs_test.dart
+165
-0
No files found.
dev/bots/post_process_docs.dart
0 → 100644
View file @
8fbd8706
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:convert'
;
import
'dart:io'
;
import
'package:intl/intl.dart'
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:platform/platform.dart'
as
platform
;
import
'package:process/process.dart'
;
const
String
kDocsRoot
=
'dev/docs'
;
const
String
kPublishRoot
=
'
$kDocsRoot
/doc'
;
class
CommandException
implements
Exception
{}
Future
<
void
>
main
()
async
{
await
postProcess
();
}
/// Post-processes an APIs documentation zip file to modify the footer and version
/// strings for commits promoted to either beta or stable channels.
Future
<
void
>
postProcess
()
async
{
final
String
revision
=
await
gitRevision
(
fullLength:
true
);
print
(
'Docs revision being processed:
$revision
'
);
final
Directory
tmpFolder
=
Directory
.
systemTemp
.
createTempSync
();
final
String
zipDestination
=
path
.
join
(
tmpFolder
.
path
,
'api_docs.zip'
);
if
(!
Platform
.
environment
.
containsKey
(
'SDK_CHECKOUT_PATH'
))
{
print
(
'SDK_CHECKOUT_PATH env variable is required for this script'
);
exit
(
1
);
}
final
String
checkoutPath
=
Platform
.
environment
[
'SDK_CHECKOUT_PATH'
]!;
final
String
docsPath
=
path
.
join
(
checkoutPath
,
'dev'
,
'docs'
);
await
runProcessWithValidations
(
<
String
>[
'curl'
,
'-L'
,
'https://storage.googleapis.com/flutter_infra_release/flutter/
$revision
/api_docs.zip'
,
'--output'
,
zipDestination
,
'--fail'
,
],
docsPath
,
);
// Unzip to docs folder.
await
runProcessWithValidations
(
<
String
>[
'unzip'
,
'-o'
,
zipDestination
,
],
docsPath
,
);
// Generate versions file.
await
runProcessWithValidations
(
<
String
>[
'flutter'
,
'--version'
],
docsPath
,
);
final
File
versionFile
=
File
(
'version'
);
final
String
version
=
versionFile
.
readAsStringSync
();
// Recreate footer
final
String
publishPath
=
path
.
join
(
docsPath
,
'doc'
,
'api'
,
'footer.js'
);
final
File
footerFile
=
File
(
publishPath
)..
createSync
(
recursive:
true
);
createFooter
(
footerFile
,
version
);
}
/// Gets the git revision of the current checkout. [fullLength] if true will return
/// the full commit hash, if false it will return the first 10 characters only.
Future
<
String
>
gitRevision
({
bool
fullLength
=
false
,
@visibleForTesting
platform
.
Platform
platform
=
const
platform
.
LocalPlatform
(),
@visibleForTesting
ProcessManager
processManager
=
const
LocalProcessManager
(),
})
async
{
const
int
kGitRevisionLength
=
10
;
final
ProcessResult
gitResult
=
processManager
.
runSync
(<
String
>[
'git'
,
'rev-parse'
,
'HEAD'
]);
if
(
gitResult
.
exitCode
!=
0
)
{
throw
'git rev-parse exit with non-zero exit code:
${gitResult.exitCode}
'
;
}
final
String
gitRevision
=
(
gitResult
.
stdout
as
String
).
trim
();
if
(
fullLength
)
{
return
gitRevision
;
}
return
gitRevision
.
length
>
kGitRevisionLength
?
gitRevision
.
substring
(
0
,
kGitRevisionLength
)
:
gitRevision
;
}
/// Wrapper function to run a subprocess checking exit code and printing stderr and stdout.
/// [executable] is a string with the script/binary to execute, [args] is the list of flags/arguments
/// and [workingDirectory] is as string to the working directory where the subprocess will be run.
Future
<
void
>
runProcessWithValidations
(
List
<
String
>
command
,
String
workingDirectory
,
{
@visibleForTesting
ProcessManager
processManager
=
const
LocalProcessManager
(),
})
async
{
final
ProcessResult
result
=
processManager
.
runSync
(
command
,
stdoutEncoding:
utf8
,
workingDirectory:
workingDirectory
);
if
(
result
.
exitCode
==
0
)
{
print
(
'Stdout:
${result.stdout}
'
);
}
else
{
print
(
'StdErr:
${result.stderr}
'
);
throw
CommandException
();
}
}
/// Get the name of the release branch.
///
/// On LUCI builds, the git HEAD is detached, so first check for the env
/// variable "LUCI_BRANCH"; if it is not set, fall back to calling git.
Future
<
String
>
getBranchName
({
@visibleForTesting
platform
.
Platform
platform
=
const
platform
.
LocalPlatform
(),
@visibleForTesting
ProcessManager
processManager
=
const
LocalProcessManager
(),
})
async
{
final
RegExp
gitBranchRegexp
=
RegExp
(
r'^## (.*)'
);
final
String
?
luciBranch
=
platform
.
environment
[
'LUCI_BRANCH'
];
if
(
luciBranch
!=
null
&&
luciBranch
.
trim
().
isNotEmpty
)
{
return
luciBranch
.
trim
();
}
final
ProcessResult
gitResult
=
processManager
.
runSync
(<
String
>[
'git'
,
'status'
,
'-b'
,
'--porcelain'
]);
if
(
gitResult
.
exitCode
!=
0
)
{
throw
'git status exit with non-zero exit code:
${gitResult.exitCode}
'
;
}
final
RegExpMatch
?
gitBranchMatch
=
gitBranchRegexp
.
firstMatch
((
gitResult
.
stdout
as
String
).
trim
().
split
(
'
\n
'
).
first
);
return
gitBranchMatch
==
null
?
''
:
gitBranchMatch
.
group
(
1
)!.
split
(
'...'
).
first
;
}
/// Updates the footer of the api documentation with the correct branch and versions.
/// [footerPath] is the path to the location of the footer js file and [version] is a
/// string with the version calculated by the flutter tool.
Future
<
void
>
createFooter
(
File
footerFile
,
String
version
,
{
@visibleForTesting
String
?
timestampParam
,
@visibleForTesting
String
?
branchParam
,
@visibleForTesting
String
?
revisionParam
})
async
{
final
String
timestamp
=
timestampParam
??
DateFormat
(
'yyyy-MM-dd HH:mm'
).
format
(
DateTime
.
now
());
final
String
gitBranch
=
branchParam
??
await
getBranchName
();
final
String
revision
=
revisionParam
??
await
gitRevision
();
final
String
gitBranchOut
=
gitBranch
.
isEmpty
?
''
:
'•
$gitBranch
'
;
footerFile
.
writeAsStringSync
(
'''
(function() {
var span = document.querySelector('
footer
>
span
');
if (span) {
span.innerText = '
Flutter
$version
•
$timestamp
•
$revision
$gitBranchOut
';
}
var sourceLink = document.querySelector('
a
.
source
-
link
');
if (sourceLink) {
sourceLink.href = sourceLink.href.replace('
/
master
/
', '
/
$revision
/
');
}
})();
'''
);
}
dev/bots/pubspec.yaml
View file @
8fbd8706
...
...
@@ -7,6 +7,7 @@ environment:
dependencies
:
args
:
2.3.1
crypto
:
3.0.2
intl
:
0.17.0
flutter_devicelab
:
path
:
../devicelab
http_parser
:
4.0.1
...
...
@@ -23,6 +24,7 @@ dependencies:
async
:
2.9.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
boolean_selector
:
2.1.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
checked_yaml
:
2.0.1
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
clock
:
1.1.1
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
collection
:
1.16.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
convert
:
3.0.2
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
coverage
:
1.6.1
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
...
...
@@ -69,4 +71,4 @@ dependencies:
dev_dependencies
:
test_api
:
0.4.14
# PUBSPEC CHECKSUM:
09b7
# PUBSPEC CHECKSUM:
7a48
dev/bots/test/post_process_docs_test.dart
0 → 100644
View file @
8fbd8706
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:io'
;
import
'package:file/memory.dart'
;
import
'package:platform/platform.dart'
;
import
'../../../packages/flutter_tools/test/src/fake_process_manager.dart'
;
import
'../post_process_docs.dart'
;
import
'common.dart'
;
void
main
(
)
async
{
group
(
'getBranch'
,
()
{
const
String
branchName
=
'stable'
;
test
(
'getBranchName does not call git if env LUCI_BRANCH provided'
,
()
async
{
final
Platform
platform
=
FakePlatform
(
environment:
<
String
,
String
>{
'LUCI_BRANCH'
:
branchName
,
},
);
final
ProcessManager
processManager
=
FakeProcessManager
.
empty
();
final
String
calculatedBranchName
=
await
getBranchName
(
platform:
platform
,
processManager:
processManager
,
);
expect
(
calculatedBranchName
,
branchName
);
});
test
(
'getBranchName calls git if env LUCI_BRANCH not provided'
,
()
async
{
final
Platform
platform
=
FakePlatform
(
environment:
<
String
,
String
>{},
);
final
ProcessManager
processManager
=
FakeProcessManager
.
list
(
<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'git'
,
'status'
,
'-b'
,
'--porcelain'
],
stdout:
'##
$branchName
'
,
),
],
);
final
String
calculatedBranchName
=
await
getBranchName
(
platform:
platform
,
processManager:
processManager
);
expect
(
calculatedBranchName
,
branchName
,
);
expect
(
processManager
,
hasNoRemainingExpectations
);
});
test
(
'getBranchName calls git if env LUCI_BRANCH is empty'
,
()
async
{
final
Platform
platform
=
FakePlatform
(
environment:
<
String
,
String
>{
'LUCI_BRANCH'
:
''
,
},
);
final
ProcessManager
processManager
=
FakeProcessManager
.
list
(
<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'git'
,
'status'
,
'-b'
,
'--porcelain'
],
stdout:
'##
$branchName
'
,
),
],
);
final
String
calculatedBranchName
=
await
getBranchName
(
platform:
platform
,
processManager:
processManager
,
);
expect
(
calculatedBranchName
,
branchName
,
);
expect
(
processManager
,
hasNoRemainingExpectations
);
});
});
group
(
'gitRevision'
,
()
{
test
(
'Return short format'
,
()
async
{
const
String
commitHash
=
'e65f01793938e13cac2d321b9fcdc7939f9b2ea6'
;
final
ProcessManager
processManager
=
FakeProcessManager
.
list
(
<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'git'
,
'rev-parse'
,
'HEAD'
],
stdout:
commitHash
,
),
],
);
final
String
revision
=
await
gitRevision
(
processManager:
processManager
);
expect
(
processManager
,
hasNoRemainingExpectations
);
expect
(
revision
,
commitHash
.
substring
(
0
,
10
));
});
test
(
'Return full length'
,
()
async
{
const
String
commitHash
=
'e65f01793938e13cac2d321b9fcdc7939f9b2ea6'
;
final
ProcessManager
processManager
=
FakeProcessManager
.
list
(
<
FakeCommand
>[
const
FakeCommand
(
command:
<
String
>[
'git'
,
'rev-parse'
,
'HEAD'
],
stdout:
commitHash
,
),
],
);
final
String
revision
=
await
gitRevision
(
fullLength:
true
,
processManager:
processManager
);
expect
(
processManager
,
hasNoRemainingExpectations
);
expect
(
revision
,
commitHash
);
});
});
group
(
'runProcessWithValidation'
,
()
{
test
(
'With no error'
,
()
async
{
const
List
<
String
>
command
=
<
String
>[
'git'
,
'rev-parse'
,
'HEAD'
];
final
ProcessManager
processManager
=
FakeProcessManager
.
list
(
<
FakeCommand
>[
const
FakeCommand
(
command:
command
,
),
],
);
await
runProcessWithValidations
(
command
,
''
,
processManager:
processManager
);
expect
(
processManager
,
hasNoRemainingExpectations
);
});
test
(
'With error'
,
()
async
{
const
List
<
String
>
command
=
<
String
>[
'git'
,
'rev-parse'
,
'HEAD'
];
final
ProcessManager
processManager
=
FakeProcessManager
.
list
(
<
FakeCommand
>[
const
FakeCommand
(
command:
command
,
exitCode:
1
,
),
],
);
try
{
await
runProcessWithValidations
(
command
,
''
,
processManager:
processManager
);
throw
Exception
(
'Exception was not thrown'
);
}
on
CommandException
catch
(
e
)
{
expect
(
e
,
isA
<
Exception
>());
}
});
});
group
(
'generateFooter'
,
()
{
test
(
'generated correctly'
,
()
async
{
const
String
expectedContent
=
'''
(function() {
var span = document.querySelector('
footer
>
span
');
if (span) {
span.innerText = '
Flutter
3.0
.
0
•
2022
-
09
-
22
14
:
09
•
abcdef
•
stable
';
}
var sourceLink = document.querySelector('
a
.
source
-
link
');
if (sourceLink) {
sourceLink.href = sourceLink.href.replace('
/
master
/
', '
/
abcdef
/
');
}
})();
'''
;
final
MemoryFileSystem
fs
=
MemoryFileSystem
();
final
File
footerFile
=
fs
.
file
(
'/a/b/c/footer.js'
)..
createSync
(
recursive:
true
);
await
createFooter
(
footerFile
,
'3.0.0'
,
timestampParam:
'2022-09-22 14:09'
,
branchParam:
'stable'
,
revisionParam:
'abcdef'
);
final
String
content
=
await
footerFile
.
readAsString
();
expect
(
content
,
expectedContent
);
});
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment