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
84aa29ce
Commit
84aa29ce
authored
Jan 09, 2020
by
Kate Lovett
Committed by
Flutter GitHub Bot
Jan 09, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Gold Pre-submit flow for contributors without permissions (#47551)
parent
a245cd78
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
540 additions
and
135 deletions
+540
-135
animation_controller.dart
packages/flutter/lib/src/animation/animation_controller.dart
+2
-1
flutter_goldens.dart
packages/flutter_goldens/lib/flutter_goldens.dart
+107
-24
flutter_goldens_test.dart
packages/flutter_goldens/test/flutter_goldens_test.dart
+205
-65
json_templates.dart
packages/flutter_goldens/test/json_templates.dart
+31
-0
skia_client.dart
packages/flutter_goldens_client/lib/skia_client.dart
+195
-45
No files found.
packages/flutter/lib/src/animation/animation_controller.dart
View file @
84aa29ce
...
@@ -248,7 +248,8 @@ class AnimationController extends Animation<double>
...
@@ -248,7 +248,8 @@ class AnimationController extends Animation<double>
_internalSetValue
(
value
??
lowerBound
);
_internalSetValue
(
value
??
lowerBound
);
}
}
/// Creates an animation controller with no upper or lower bound for its value.
/// Creates an animation controller with no upper or lower bound for its
/// value.
///
///
/// * [value] is the initial value of the animation.
/// * [value] is the initial value of the animation.
///
///
...
...
packages/flutter_goldens/lib/flutter_goldens.dart
View file @
84aa29ce
...
@@ -268,10 +268,6 @@ class FlutterSkiaGoldFileComparator extends FlutterGoldenFileComparator {
...
@@ -268,10 +268,6 @@ class FlutterSkiaGoldFileComparator extends FlutterGoldenFileComparator {
/// * [FlutterLocalFileComparator], another
/// * [FlutterLocalFileComparator], another
/// [FlutterGoldenFileComparator] that tests golden images locally on your
/// [FlutterGoldenFileComparator] that tests golden images locally on your
/// current machine.
/// current machine.
// TODO(Piinks): Better handling for first-time contributors that cannot decrypt
// the service account is needed. Gold has a new feature `goldctl imgtest check`
// that could work. There is also the previous implementation that did not use
// goldctl for this edge case. https://github.com/flutter/flutter/issues/46687
class
FlutterPreSubmitFileComparator
extends
FlutterGoldenFileComparator
{
class
FlutterPreSubmitFileComparator
extends
FlutterGoldenFileComparator
{
/// Creates a [FlutterPreSubmitFileComparator] that will test golden file
/// Creates a [FlutterPreSubmitFileComparator] that will test golden file
/// images against baselines requested from Flutter Gold.
/// images against baselines requested from Flutter Gold.
...
@@ -299,41 +295,132 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator {
...
@@ -299,41 +295,132 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator {
final
Platform
platform
,
{
final
Platform
platform
,
{
SkiaGoldClient
goldens
,
SkiaGoldClient
goldens
,
LocalFileComparator
defaultComparator
,
LocalFileComparator
defaultComparator
,
final
Directory
testBasedir
,
})
async
{
})
async
{
defaultComparator
??=
goldenFileComparator
as
LocalFileComparator
;
defaultComparator
??=
goldenFileComparator
as
LocalFileComparator
;
final
Directory
baseDirectory
=
FlutterGoldenFileComparator
.
getBaseDirectory
(
final
Directory
baseDirectory
=
testBasedir
??
FlutterGoldenFileComparator
.
getBaseDirectory
(
defaultComparator
,
defaultComparator
,
platform
,
platform
,
suffix:
'
${math.Random().nextInt(10000)}
'
,
suffix:
'
${math.Random().nextInt(10000)}
'
,
);
);
baseDirectory
.
createSync
(
recursive:
true
);
if
(!
baseDirectory
.
existsSync
())
baseDirectory
.
createSync
(
recursive:
true
);
goldens
??=
SkiaGoldClient
(
baseDirectory
);
goldens
??=
SkiaGoldClient
(
baseDirectory
);
await
goldens
.
auth
();
await
goldens
.
tryjobInit
();
final
bool
hasWritePermission
=
!
platform
.
environment
[
'GOLD_SERVICE_ACCOUNT'
].
startsWith
(
'ENCRYPTED'
);
return
FlutterPreSubmitFileComparator
(
baseDirectory
.
uri
,
goldens
);
if
(
hasWritePermission
)
{
await
goldens
.
auth
();
await
goldens
.
tryjobInit
();
return
_AuthorizedFlutterPreSubmitComparator
(
baseDirectory
.
uri
,
goldens
,
platform:
platform
,
);
}
goldens
.
emptyAuth
();
return
_UnauthorizedFlutterPreSubmitComparator
(
baseDirectory
.
uri
,
goldens
,
platform:
platform
,
);
}
}
@override
@override
Future
<
bool
>
compare
(
Uint8List
imageBytes
,
Uri
golden
)
async
{
Future
<
bool
>
compare
(
Uint8List
imageBytes
,
Uri
golden
)
async
{
golden
=
_addPrefix
(
golden
);
assert
(
await
update
(
golden
,
imageBytes
);
false
,
final
File
goldenFile
=
getGoldenFile
(
golden
);
'The FlutterPreSubmitFileComparator has been used to execute a golden '
'file test; this should never happen. Presubmit golden file testing '
return
skiaClient
.
tryjobAdd
(
golden
.
path
,
goldenFile
);
'should be executed by either the _AuthorizedFlutterPreSubmitComparator '
'or the _UnauthorizedFlutterPreSubmitComparator based on contributor '
'permissions.'
);
return
false
;
}
}
/// Decides based on the current environment whether goldens tests should be
/// Decides based on the current environment whether goldens tests should be
/// performed as pre-submit tests with Skia Gold.
/// performed as pre-submit tests with Skia Gold.
static
bool
isAvailableForEnvironment
(
Platform
platform
)
{
static
bool
isAvailableForEnvironment
(
Platform
platform
)
{
final
String
cirrusPR
=
platform
.
environment
[
'CIRRUS_PR'
]
??
''
;
final
String
cirrusPR
=
platform
.
environment
[
'CIRRUS_PR'
]
??
''
;
final
bool
hasWritePermission
=
platform
.
environment
[
'CIRRUS_USER_PERMISSION'
]
==
'admin'
||
platform
.
environment
[
'CIRRUS_USER_PERMISSION'
]
==
'write'
;
return
platform
.
environment
.
containsKey
(
'CIRRUS_CI'
)
return
platform
.
environment
.
containsKey
(
'CIRRUS_CI'
)
&&
cirrusPR
.
isNotEmpty
&&
cirrusPR
.
isNotEmpty
&&
platform
.
environment
.
containsKey
(
'GOLD_SERVICE_ACCOUNT'
)
&&
platform
.
environment
.
containsKey
(
'GOLD_SERVICE_ACCOUNT'
);
&&
hasWritePermission
;
}
}
class
_AuthorizedFlutterPreSubmitComparator
extends
FlutterPreSubmitFileComparator
{
_AuthorizedFlutterPreSubmitComparator
(
final
Uri
basedir
,
final
SkiaGoldClient
skiaClient
,
{
final
FileSystem
fs
=
const
LocalFileSystem
(),
final
Platform
platform
=
const
LocalPlatform
(),
})
:
super
(
basedir
,
skiaClient
,
fs:
fs
,
platform:
platform
,
);
@override
Future
<
bool
>
compare
(
Uint8List
imageBytes
,
Uri
golden
)
async
{
golden
=
_addPrefix
(
golden
);
await
update
(
golden
,
imageBytes
);
final
File
goldenFile
=
getGoldenFile
(
golden
);
return
skiaClient
.
tryjobAdd
(
golden
.
path
,
goldenFile
);
}
}
class
_UnauthorizedFlutterPreSubmitComparator
extends
FlutterPreSubmitFileComparator
{
_UnauthorizedFlutterPreSubmitComparator
(
final
Uri
basedir
,
final
SkiaGoldClient
skiaClient
,
{
final
FileSystem
fs
=
const
LocalFileSystem
(),
final
Platform
platform
=
const
LocalPlatform
(),
})
:
super
(
basedir
,
skiaClient
,
fs:
fs
,
platform:
platform
,
);
@override
Future
<
bool
>
compare
(
Uint8List
imageBytes
,
Uri
golden
)
async
{
golden
=
_addPrefix
(
golden
);
await
update
(
golden
,
imageBytes
);
final
File
goldenFile
=
getGoldenFile
(
golden
);
// Check for match to existing baseline.
if
(
await
skiaClient
.
imgtestCheck
(
golden
.
path
,
goldenFile
))
return
true
;
// We do not have a matching image, so we need to check a few things
// manually. We wait until this point to do this work so request traffic
// low.
skiaClient
.
getExpectations
();
final
String
testName
=
skiaClient
.
cleanTestName
(
golden
.
path
);
final
List
<
String
>
testExpectations
=
skiaClient
.
expectations
[
testName
];
if
(
testExpectations
==
null
)
{
// This is a new test.
print
(
'No expectations provided by Skia Gold for test:
$golden
. '
'This may be a new test. If this is an unexpected result, check '
'https://flutter-gold.skia.org.
\n
'
);
return
true
;
}
// Contributors without the proper permissions to execute a tryjob can make
// a golden file change through Gold's ignore feature instead.
final
bool
ignoreResult
=
await
skiaClient
.
testIsIgnoredForPullRequest
(
platform
.
environment
[
'CIRRUS_PR'
]
??
''
,
golden
.
path
,
);
// If true, this is an intended change.
return
ignoreResult
;
}
}
}
}
...
@@ -399,12 +486,8 @@ class FlutterSkippingGoldenFileComparator extends FlutterGoldenFileComparator {
...
@@ -399,12 +486,8 @@ class FlutterSkippingGoldenFileComparator extends FlutterGoldenFileComparator {
/// Decides based on the current environment whether this comparator should be
/// Decides based on the current environment whether this comparator should be
/// used.
/// used.
static
bool
isAvailableForEnvironment
(
Platform
platform
)
{
static
bool
isAvailableForEnvironment
(
Platform
platform
)
{
return
(
platform
.
environment
.
containsKey
(
'SWARMING_TASK_ID'
)
return
platform
.
environment
.
containsKey
(
'SWARMING_TASK_ID'
)
||
platform
.
environment
.
containsKey
(
'CIRRUS_CI'
))
||
platform
.
environment
.
containsKey
(
'CIRRUS_CI'
);
// A service account means that this is a Gold shard. At this point, it
// means we don't have permission to use the account, so we will pass
// through to the [FlutterLocalFileComparator].
&&
!
platform
.
environment
.
containsKey
(
'GOLD_SERVICE_ACCOUNT'
);
}
}
}
}
...
...
packages/flutter_goldens/test/flutter_goldens_test.dart
View file @
84aa29ce
This diff is collapsed.
Click to expand it.
packages/flutter_goldens/test/json_templates.dart
View file @
84aa29ce
...
@@ -169,6 +169,37 @@ String digestResponseTemplate({
...
@@ -169,6 +169,37 @@ String digestResponseTemplate({
'''
;
'''
;
}
}
/// Json response template for Skia Gold ignore request:
/// https://flutter-gold.skia.org/json/ignores
String
ignoreResponseTemplate
(
{
String
pullRequestNumber
=
'0000'
,
String
testName
=
'flutter.golden_test.1'
,
String
otherTestName
=
'flutter.golden_test.1'
,
String
expires
=
'2019-09-06T21:28:18.815336Z'
,
String
otherExpires
=
'2019-09-06T21:28:18.815336Z'
,
})
{
return
'''
[
{
"id": "7579425228619212078",
"name": "contributor@getMail.com",
"updatedBy": "contributor@getMail.com",
"expires": "
$expires
",
"query": "ext=png&name=
$testName
",
"note": "https://github.com/flutter/flutter/pull/
$pullRequestNumber
"
},
{
"id": "7579425228619212078",
"name": "contributor@getMail.com",
"updatedBy": "contributor@getMail.com",
"expires": "
$otherExpires
",
"query": "ext=png&name=
$otherTestName
",
"note": "https://github.com/flutter/flutter/pull/99999"
}
]
'''
;
}
/// Json response template for Skia Gold image request:
/// Json response template for Skia Gold image request:
/// https://flutter-gold.skia.org/img/images/[imageHash].png
/// https://flutter-gold.skia.org/img/images/[imageHash].png
List
<
List
<
int
>>
imageResponseTemplate
()
{
List
<
List
<
int
>>
imageResponseTemplate
()
{
...
...
packages/flutter_goldens_client/lib/skia_client.dart
View file @
84aa29ce
This diff is collapsed.
Click to expand it.
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