Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • project/automatic_updates
  • issue/automatic_updates-3159719
  • issue/automatic_updates-3227923
  • issue/automatic_updates-3227927
  • issue/automatic_updates-3227122
  • issue/automatic_updates-3227940
  • issue/automatic_updates-3228095
  • issue/automatic_updates-3228101
  • issue/automatic_updates-3228115
  • issue/automatic_updates-3228125
  • issue/automatic_updates-3228359
  • issue/automatic_updates-3228392
  • issue/automatic_updates-3225753
  • issue/automatic_updates-3227588
  • issue/automatic_updates-3228521
  • issue/automatic_updates-3228539
  • issue/automatic_updates-3226570
  • issue/automatic_updates-3228806
  • issue/automatic_updates-3227575
  • issue/automatic_updates-3229485
  • issue/automatic_updates-3228955
  • issue/automatic_updates-3230024
  • issue/automatic_updates-3230250
  • issue/automatic_updates-3230249
  • issue/automatic_updates-3230264
  • issue/automatic_updates-3230510
  • issue/automatic_updates-3230235
  • issue/automatic_updates-3230050
  • issue/automatic_updates-3230934
  • issue/automatic_updates-3230049
  • issue/automatic_updates-3230507
  • issue/automatic_updates-3231153
  • issue/automatic_updates-3231992
  • issue/automatic_updates-3232003
  • issue/automatic_updates-3232004
  • issue/automatic_updates-3231996
  • issue/automatic_updates-3231999
  • issue/automatic_updates-3230668
  • issue/automatic_updates-3232000
  • issue/automatic_updates-3232420
  • issue/automatic_updates-3232729
  • issue/automatic_updates-3232761
  • issue/automatic_updates-3231997
  • issue/automatic_updates-3232927
  • issue/automatic_updates-3232959
  • issue/automatic_updates-3233124
  • issue/automatic_updates-3230856
  • issue/automatic_updates-3233493
  • issue/automatic_updates-3233587
  • issue/automatic_updates-3233521
  • issue/automatic_updates-3236405
  • issue/automatic_updates-3236299
  • issue/automatic_updates-3238586
  • issue/automatic_updates-3238647
  • issue/automatic_updates-3238717
  • issue/automatic_updates-3238846
  • issue/automatic_updates-3238852
  • issue/automatic_updates-3238866
  • issue/automatic_updates-3238714
  • issue/automatic_updates-3239103
  • issue/automatic_updates-3233138
  • issue/automatic_updates-3239466
  • issue/automatic_updates-3239645
  • issue/automatic_updates-3239673
  • issue/automatic_updates-3277775
  • issue/automatic_updates-3280923
  • issue/automatic_updates-3275315
  • issue/automatic_updates-3279527
  • issue/automatic_updates-3279733
  • issue/automatic_updates-3281405
  • issue/automatic_updates-3281397
  • issue/automatic_updates-3280204
  • issue/automatic_updates-3277817
  • issue/automatic_updates-3277230
  • issue/automatic_updates-3276534
  • issue/automatic_updates-3279538
  • issue/automatic_updates-3280168
  • issue/automatic_updates-3271502
  • issue/automatic_updates-3283644
  • issue/automatic_updates-3302524
  • issue/automatic_updates-3275883
  • issue/automatic_updates-3280180
  • issue/automatic_updates-3274837
  • issue/automatic_updates-3281473
  • issue/automatic_updates-3281634
  • issue/automatic_updates-3239889
  • issue/automatic_updates-3240753
  • issue/automatic_updates-3233103
  • issue/automatic_updates-3240971
  • issue/automatic_updates-3233564
  • issue/automatic_updates-3241380
  • issue/automatic_updates-3241105
  • issue/automatic_updates-3242626
  • issue/automatic_updates-3242724
  • issue/automatic_updates-3243057
  • issue/automatic_updates-3243348
  • issue/automatic_updates-3243339
  • issue/automatic_updates-3243422
  • issue/automatic_updates-3243436
  • issue/automatic_updates-3243600
  • issue/automatic_updates-3243851
  • issue/automatic_updates-3243405
  • issue/automatic_updates-3244338
  • issue/automatic_updates-3244337
  • issue/automatic_updates-3244360
  • issue/automatic_updates-3244358
  • issue/automatic_updates-3244679
  • issue/automatic_updates-3244939
  • issue/automatic_updates-3244976
  • issue/automatic_updates-3245376
  • issue/automatic_updates-3245388
  • issue/automatic_updates-3245428
  • issue/automatic_updates-3245655
  • issue/automatic_updates-3245766
  • issue/automatic_updates-3245810
  • issue/automatic_updates-3245846
  • issue/automatic_updates-3246036
  • issue/automatic_updates-3246194
  • issue/automatic_updates-3246203
  • issue/automatic_updates-3246283
  • issue/automatic_updates-3279064
  • issue/automatic_updates-3246420
  • issue/automatic_updates-3246638
  • issue/automatic_updates-3246660
  • issue/automatic_updates-3246673
  • issue/automatic_updates-3246695
  • issue/automatic_updates-3245996
  • issue/automatic_updates-3247308
  • issue/automatic_updates-3247478
  • issue/automatic_updates-3247479
  • issue/automatic_updates-3279086
  • issue/automatic_updates-3248312
  • issue/automatic_updates-3248523
  • issue/automatic_updates-3248527
  • issue/automatic_updates-3244412
  • issue/automatic_updates-3248976
  • issue/automatic_updates-3248909
  • issue/automatic_updates-3246507
  • issue/automatic_updates-3249531
  • issue/automatic_updates-3249517
  • issue/automatic_updates-3249983
  • issue/automatic_updates-3249135
  • issue/automatic_updates-3250136
  • issue/automatic_updates-3250386
  • issue/automatic_updates-3251701
  • issue/automatic_updates-3250696
  • issue/automatic_updates-3248911
  • issue/automatic_updates-3227420
  • issue/automatic_updates-3252071
  • issue/automatic_updates-3252097
  • issue/automatic_updates-3252109
  • issue/automatic_updates-3252126
  • issue/automatic_updates-3249130
  • issue/automatic_updates-3251972
  • issue/automatic_updates-3252187
  • issue/automatic_updates-3252328
  • issue/automatic_updates-3252324
  • issue/automatic_updates-3252533
  • issue/automatic_updates-3253055
  • issue/automatic_updates-3253186
  • issue/automatic_updates-3253395
  • issue/automatic_updates-3253400
  • issue/automatic_updates-3253624
  • issue/automatic_updates-3253647
  • issue/automatic_updates-3253649
  • issue/automatic_updates-3253858
  • issue/automatic_updates-3254166
  • issue/automatic_updates-3254207
  • issue/automatic_updates-3279108
  • issue/automatic_updates-3254606
  • issue/automatic_updates-3254616
  • issue/automatic_updates-3254911
  • issue/automatic_updates-3255011
  • issue/automatic_updates-3255014
  • issue/automatic_updates-3255320
  • issue/automatic_updates-3277562
  • issue/automatic_updates-3255678
  • issue/automatic_updates-3256958
  • issue/automatic_updates-3257115
  • issue/automatic_updates-3257432
  • issue/automatic_updates-3257446
  • issue/automatic_updates-3257473
  • issue/automatic_updates-3257134
  • issue/automatic_updates-3257849
  • issue/automatic_updates-3258065
  • issue/automatic_updates-3258056
  • issue/automatic_updates-3258048
  • issue/automatic_updates-3258045
  • issue/automatic_updates-3258464
  • issue/automatic_updates-3258611
  • issue/automatic_updates-3258646
  • issue/automatic_updates-3258661
  • issue/automatic_updates-3258667
  • issue/automatic_updates-3258590
  • issue/automatic_updates-3259228
  • issue/automatic_updates-3259656
  • issue/automatic_updates-3252299
  • issue/automatic_updates-3259664
  • issue/automatic_updates-3259822
  • issue/automatic_updates-3259810
  • issue/automatic_updates-3259814
  • issue/automatic_updates-3260368
  • issue/automatic_updates-3257845
  • issue/automatic_updates-3260664
  • issue/automatic_updates-3260672
  • issue/automatic_updates-3260698
  • issue/automatic_updates-3260662
  • issue/automatic_updates-3260669
  • issue/automatic_updates-3260668
  • issue/automatic_updates-3261637
  • issue/automatic_updates-3261772
  • issue/automatic_updates-3261847
  • issue/automatic_updates-3262016
  • issue/automatic_updates-3262244
  • issue/automatic_updates-3262303
  • issue/automatic_updates-3261642
  • issue/automatic_updates-3262359
  • issue/automatic_updates-3262542
  • issue/automatic_updates-3261098
  • issue/automatic_updates-3260666
  • issue/automatic_updates-3262587
  • issue/automatic_updates-3262965
  • issue/automatic_updates-3263155
  • issue/automatic_updates-3263223
  • issue/automatic_updates-3254755
  • issue/automatic_updates-3261758
  • issue/automatic_updates-3258059
  • issue/automatic_updates-3259196
  • issue/automatic_updates-3263865
  • issue/automatic_updates-3262284
  • issue/automatic_updates-3264554
  • issue/automatic_updates-3248928
  • issue/automatic_updates-3248929
  • issue/automatic_updates-3265072
  • issue/automatic_updates-3265057
  • issue/automatic_updates-3265873
  • issue/automatic_updates-3266092
  • issue/automatic_updates-3266633
  • issue/automatic_updates-3266640
  • issue/automatic_updates-3266687
  • issue/automatic_updates-3266981
  • issue/automatic_updates-3267387
  • issue/automatic_updates-3267389
  • issue/automatic_updates-3267411
  • issue/automatic_updates-3267603
  • issue/automatic_updates-3265874
  • issue/automatic_updates-3267577
  • issue/automatic_updates-3267386
  • issue/automatic_updates-3268363
  • issue/automatic_updates-3268868
  • issue/automatic_updates-3268612
  • issue/automatic_updates-3269097
  • issue/automatic_updates-3267632
  • issue/automatic_updates-3270736
  • issue/automatic_updates-3271144
  • issue/automatic_updates-3271226
  • issue/automatic_updates-3271078
  • issue/automatic_updates-3271371
  • issue/automatic_updates-3267646
  • issue/automatic_updates-3272060
  • issue/automatic_updates-3265031
  • issue/automatic_updates-3253591
  • issue/automatic_updates-3272520
  • issue/automatic_updates-3272061
  • issue/automatic_updates-3272785
  • issue/automatic_updates-3273011
  • issue/automatic_updates-3273008
  • issue/automatic_updates-3273364
  • issue/automatic_updates-3273407
  • issue/automatic_updates-3271235
  • issue/automatic_updates-3273006
  • issue/automatic_updates-3271240
  • issue/automatic_updates-3271468
  • issue/automatic_updates-3272326
  • issue/automatic_updates-3273693
  • issue/automatic_updates-3264849
  • issue/automatic_updates-3273807
  • issue/automatic_updates-3273017
  • issue/automatic_updates-3274269
  • issue/automatic_updates-3274273
  • issue/automatic_updates-3274292
  • issue/automatic_updates-3273812
  • issue/automatic_updates-3274323
  • issue/automatic_updates-3274633
  • issue/automatic_updates-3274858
  • issue/automatic_updates-3274830
  • issue/automatic_updates-3274892
  • issue/automatic_updates-3275075
  • issue/automatic_updates-3275256
  • issue/automatic_updates-3275282
  • issue/automatic_updates-3275320
  • issue/automatic_updates-3275323
  • issue/automatic_updates-3275324
  • issue/automatic_updates-3275317
  • issue/automatic_updates-3275313
  • issue/automatic_updates-3275357
  • issue/automatic_updates-3275474
  • issue/automatic_updates-3275311
  • issue/automatic_updates-3275546
  • issue/automatic_updates-3275508
  • issue/automatic_updates-3275810
  • issue/automatic_updates-3275860
  • issue/automatic_updates-3275865
  • issue/automatic_updates-3275886
  • issue/automatic_updates-3275887
  • issue/automatic_updates-3276031
  • issue/automatic_updates-3276041
  • issue/automatic_updates-3276072
  • issue/automatic_updates-3276159
  • issue/automatic_updates-3276255
  • issue/automatic_updates-3275825
  • issue/automatic_updates-3276661
  • issue/automatic_updates-3275369
  • issue/automatic_updates-3277014
  • issue/automatic_updates-3277035
  • issue/automatic_updates-3272813
  • issue/automatic_updates-3277211
  • issue/automatic_updates-3277229
  • issue/automatic_updates-3275316
  • issue/automatic_updates-3274047
  • issue/automatic_updates-3277815
  • issue/automatic_updates-3276662
  • issue/automatic_updates-3277235
  • issue/automatic_updates-3278411
  • issue/automatic_updates-3278435
  • issue/automatic_updates-3279229
  • issue/automatic_updates-3277007
  • issue/automatic_updates-3284346
  • issue/automatic_updates-3239759
  • issue/automatic_updates-3284495
  • issue/automatic_updates-3284530
  • issue/automatic_updates-3282677
  • issue/automatic_updates-3281379
  • issue/automatic_updates-3285408
  • issue/automatic_updates-3285631
  • issue/automatic_updates-3285669
  • issue/automatic_updates-3273014
  • issue/automatic_updates-3273369
  • issue/automatic_updates-3285491
  • issue/automatic_updates-3285898
  • issue/automatic_updates-3287251
  • issue/automatic_updates-3291147
  • issue/automatic_updates-3286650
  • issue/automatic_updates-3291770
  • issue/automatic_updates-3280403
  • issue/automatic_updates-3291959
  • issue/automatic_updates-3287398
  • issue/automatic_updates-3285145
  • issue/automatic_updates-3292027
  • issue/automatic_updates-3278445
  • issue/automatic_updates-3292933
  • issue/automatic_updates-3292958
  • issue/automatic_updates-3293157
  • issue/automatic_updates-3292956
  • issue/automatic_updates-3293146
  • issue/automatic_updates-3293381
  • issue/automatic_updates-3293449
  • issue/automatic_updates-3293427
  • issue/automatic_updates-3293422
  • issue/automatic_updates-3293685
  • issue/automatic_updates-3291730
  • issue/automatic_updates-3293866
  • issue/automatic_updates-3294338
  • issue/automatic_updates-3293656
  • issue/automatic_updates-3294600
  • issue/automatic_updates-3294335
  • issue/automatic_updates-3295013
  • issue/automatic_updates-3284936
  • issue/automatic_updates-3295596
  • issue/automatic_updates-3295758
  • issue/automatic_updates-3295791
  • issue/automatic_updates-3295830
  • issue/automatic_updates-3295874
  • issue/automatic_updates-3295897
  • issue/automatic_updates-3296074
  • issue/automatic_updates-3295965
  • issue/automatic_updates-3296181
  • issue/automatic_updates-3296065
  • issue/automatic_updates-3296178
  • issue/automatic_updates-3296261
  • issue/automatic_updates-3293148
  • issue/automatic_updates-3303953
  • issue/automatic_updates-3304367
  • issue/automatic_updates-3304640
  • issue/automatic_updates-3304836
  • issue/automatic_updates-3304142
  • issue/automatic_updates-3298349
  • issue/automatic_updates-3298444
  • issue/automatic_updates-3298510
  • issue/automatic_updates-3298431
  • issue/automatic_updates-3298863
  • issue/automatic_updates-3298877
  • issue/automatic_updates-3298904
  • issue/automatic_updates-3298951
  • issue/automatic_updates-3299101
  • issue/automatic_updates-3299417
  • issue/automatic_updates-3293417
  • issue/automatic_updates-3299612
  • issue/automatic_updates-3299093
  • issue/automatic_updates-3299087
  • issue/automatic_updates-3300006
  • issue/automatic_updates-3300036
  • issue/automatic_updates-3293150
  • issue/automatic_updates-3303807
  • issue/automatic_updates-3303929
  • issue/automatic_updates-3304417
  • issue/automatic_updates-3303727
  • issue/automatic_updates-3305527
  • issue/automatic_updates-3301844
  • issue/automatic_updates-3302527
  • issue/automatic_updates-3302673
  • issue/automatic_updates-3302897
  • issue/automatic_updates-3303143
  • issue/automatic_updates-3303168
  • issue/automatic_updates-3303174
  • issue/automatic_updates-3303185
  • issue/automatic_updates-3303200
  • issue/automatic_updates-3303113
  • issue/automatic_updates-3304036
  • issue/automatic_updates-3304165
  • issue/automatic_updates-3304583
  • issue/automatic_updates-3303902
  • issue/automatic_updates-3304651
  • issue/automatic_updates-3305312
  • issue/automatic_updates-3305612
  • issue/automatic_updates-3305568
  • issue/automatic_updates-3305773
  • issue/automatic_updates-3305874
  • issue/automatic_updates-3310901
  • issue/automatic_updates-3310929
  • issue/automatic_updates-3310936
  • issue/automatic_updates-3310972
  • issue/automatic_updates-3311001
  • issue/automatic_updates-3311020
  • issue/automatic_updates-3305240
  • issue/automatic_updates-3305994
  • issue/automatic_updates-3305564
  • issue/automatic_updates-3305998
  • issue/automatic_updates-3306600
  • issue/automatic_updates-3306631
  • issue/automatic_updates-3307086
  • issue/automatic_updates-3307103
  • issue/automatic_updates-3307168
  • issue/automatic_updates-3306163
  • issue/automatic_updates-3304617
  • issue/automatic_updates-3307163
  • issue/automatic_updates-3307398
  • issue/automatic_updates-3307478
  • issue/automatic_updates-3307369
  • issue/automatic_updates-3308404
  • issue/automatic_updates-3307611
  • issue/automatic_updates-3308372
  • issue/automatic_updates-3308686
  • issue/automatic_updates-3308886
  • issue/automatic_updates-3309220
  • issue/automatic_updates-3309270
  • issue/automatic_updates-3308711
  • issue/automatic_updates-3309486
  • issue/automatic_updates-3305167
  • issue/automatic_updates-3309676
  • issue/automatic_updates-3309025
  • issue/automatic_updates-3309891
  • issue/automatic_updates-3308365
  • issue/automatic_updates-3310000
  • issue/automatic_updates-3309205
  • issue/automatic_updates-3248975
  • issue/automatic_updates-3310702
  • issue/automatic_updates-3272313
  • issue/automatic_updates-3310990
  • issue/automatic_updates-3310997
  • issue/automatic_updates-3311200
  • issue/automatic_updates-3310696
  • issue/automatic_updates-3311265
  • issue/automatic_updates-3303167
  • issue/automatic_updates-3310946
  • issue/automatic_updates-3308828
  • issue/automatic_updates-3310666
  • issue/automatic_updates-3109082
  • issue/automatic_updates-3311534
  • issue/automatic_updates-3311436
  • issue/automatic_updates-3308843
  • issue/automatic_updates-3303900
  • issue/automatic_updates-3312085
  • issue/automatic_updates-3312420
  • issue/automatic_updates-3312373
  • issue/automatic_updates-3312421
  • issue/automatic_updates-3312619
  • issue/automatic_updates-3312779
  • issue/automatic_updates-3275991
  • issue/automatic_updates-3312938
  • issue/automatic_updates-3312937
  • issue/automatic_updates-3312960
  • issue/automatic_updates-3312669
  • issue/automatic_updates-3312981
  • issue/automatic_updates-3313319
  • issue/automatic_updates-3313346
  • issue/automatic_updates-3310914
  • issue/automatic_updates-3317220
  • issue/automatic_updates-3317232
  • issue/automatic_updates-3317278
  • issue/automatic_updates-3317409
  • issue/automatic_updates-3317267
  • issue/automatic_updates-3317599
  • issue/automatic_updates-3317988
  • issue/automatic_updates-3318313
  • issue/automatic_updates-3313630
  • issue/automatic_updates-3313717
  • issue/automatic_updates-3313947
  • issue/automatic_updates-3313507
  • issue/automatic_updates-3276645
  • issue/automatic_updates-3313349
  • issue/automatic_updates-3314137
  • issue/automatic_updates-3314143
  • issue/automatic_updates-3304365
  • issue/automatic_updates-3317796
  • issue/automatic_updates-3317996
  • issue/automatic_updates-3316484
  • issue/automatic_updates-3313414
  • issue/automatic_updates-3314764
  • issue/automatic_updates-3314771
  • issue/automatic_updates-3314787
  • issue/automatic_updates-3314805
  • issue/automatic_updates-3314734
  • issue/automatic_updates-3298889
  • issue/automatic_updates-3314803
  • issue/automatic_updates-3315139
  • issue/automatic_updates-3314946
  • issue/automatic_updates-3315449
  • issue/automatic_updates-3315798
  • issue/automatic_updates-3315834
  • issue/automatic_updates-3309602
  • issue/automatic_updates-3316115
  • issue/automatic_updates-3316131
  • issue/automatic_updates-3316293
  • issue/automatic_updates-3316318
  • issue/automatic_updates-3310729
  • issue/automatic_updates-3315700
  • issue/automatic_updates-3316668
  • issue/automatic_updates-3316721
  • issue/automatic_updates-3306283
  • issue/automatic_updates-3316611
  • issue/automatic_updates-3316895
  • issue/automatic_updates-3317385
  • issue/automatic_updates-3318625
  • issue/automatic_updates-3318770
  • issue/automatic_updates-3318846
  • issue/automatic_updates-3318927
  • issue/automatic_updates-3318933
  • issue/automatic_updates-3319044
  • issue/automatic_updates-3319045
  • issue/automatic_updates-3325716
  • issue/automatic_updates-3324421
  • issue/automatic_updates-3320486
  • issue/automatic_updates-3320558
  • issue/automatic_updates-3321206
  • issue/automatic_updates-3326934
  • issue/automatic_updates-3320755
  • issue/automatic_updates-3328765
  • issue/automatic_updates-3325654
  • issue/automatic_updates-3325869
  • issue/automatic_updates-3277034
  • issue/automatic_updates-3328516
  • issue/automatic_updates-3322546
  • issue/automatic_updates-3320487
  • issue/automatic_updates-3320792
  • issue/automatic_updates-3320815
  • issue/automatic_updates-3320638
  • issue/automatic_updates-3321256
  • issue/automatic_updates-3321684
  • issue/automatic_updates-3325522
  • issue/automatic_updates-3326334
  • issue/automatic_updates-3328234
  • issue/automatic_updates-3328740
  • issue/automatic_updates-3316932
  • issue/automatic_updates-3321386
  • issue/automatic_updates-3321933
  • issue/automatic_updates-3321282
  • issue/automatic_updates-3326801
  • issue/automatic_updates-3327753
  • issue/automatic_updates-3328742
  • issue/automatic_updates-3322313
  • issue/automatic_updates-3322203
  • issue/automatic_updates-3322150
  • issue/automatic_updates-3322404
  • issue/automatic_updates-3321236
  • issue/automatic_updates-3321994
  • issue/automatic_updates-3322589
  • issue/automatic_updates-3321904
  • issue/automatic_updates-3316855
  • issue/automatic_updates-3322931
  • issue/automatic_updates-3322913
  • issue/automatic_updates-3323037
  • issue/automatic_updates-3322918
  • issue/automatic_updates-3323211
  • issue/automatic_updates-3323565
  • issue/automatic_updates-3320824
  • issue/automatic_updates-3320836
  • issue/automatic_updates-3329002
  • issue/automatic_updates-3321971
  • issue/automatic_updates-3299094
  • issue/automatic_updates-3248544
  • issue/automatic_updates-3330139
  • issue/automatic_updates-3330365
  • issue/automatic_updates-3330712
  • issue/automatic_updates-3318065
  • issue/automatic_updates-3331310
  • issue/automatic_updates-3322917
  • issue/automatic_updates-3330140
  • issue/automatic_updates-3323003
  • issue/automatic_updates-3331355
  • issue/automatic_updates-3334054
  • issue/automatic_updates-3323706
  • issue/automatic_updates-3331168
  • issue/automatic_updates-3343430
  • issue/automatic_updates-3344562
  • issue/automatic_updates-3345039
  • issue/automatic_updates-3344039
  • issue/automatic_updates-3345313
  • issue/automatic_updates-3331471
  • issue/automatic_updates-3334994
  • issue/automatic_updates-3327229
  • issue/automatic_updates-3343889
  • issue/automatic_updates-3344124
  • issue/automatic_updates-3344689
  • issue/automatic_updates-3316368
  • issue/automatic_updates-3345767
  • issue/automatic_updates-3317815
  • issue/automatic_updates-3328600
  • issue/automatic_updates-3332256
  • issue/automatic_updates-3335766
  • issue/automatic_updates-3335802
  • issue/automatic_updates-3335908
  • issue/automatic_updates-3336243
  • issue/automatic_updates-3336247
  • issue/automatic_updates-3336255
  • issue/automatic_updates-3336259
  • issue/automatic_updates-3337062
  • issue/automatic_updates-3337068
  • issue/automatic_updates-3311229
  • issue/automatic_updates-3337697
  • issue/automatic_updates-3343768
  • issue/automatic_updates-3344127
  • issue/automatic_updates-3344595
  • issue/automatic_updates-3345763
  • issue/automatic_updates-3345765
  • issue/automatic_updates-3345771
  • issue/automatic_updates-3337760
  • issue/automatic_updates-3337049
  • issue/automatic_updates-3342430
  • issue/automatic_updates-3319507
  • issue/automatic_updates-3344583
  • issue/automatic_updates-3345764
  • issue/automatic_updates-3345768
  • issue/automatic_updates-3338667
  • issue/automatic_updates-3339016
  • issue/automatic_updates-3343827
  • issue/automatic_updates-3344556
  • issue/automatic_updates-3338666
  • issue/automatic_updates-3345649
  • issue/automatic_updates-3339657
  • issue/automatic_updates-3339719
  • issue/automatic_updates-3338789
  • issue/automatic_updates-3340022
  • issue/automatic_updates-3340284
  • issue/automatic_updates-3340638
  • issue/automatic_updates-3316617
  • issue/automatic_updates-3341224
  • issue/automatic_updates-3337953
  • issue/automatic_updates-3339714
  • issue/automatic_updates-3341708
  • issue/automatic_updates-3341841
  • issue/automatic_updates-3326486
  • issue/automatic_updates-3321474
  • issue/automatic_updates-3341974
  • issue/automatic_updates-3342120
  • issue/automatic_updates-3342227
  • issue/automatic_updates-3323461
  • issue/automatic_updates-3342137
  • issue/automatic_updates-3342460
  • issue/automatic_updates-3342364
  • issue/automatic_updates-3345028
  • issue/automatic_updates-3345549
  • issue/automatic_updates-3345881
  • issue/automatic_updates-3345762
  • issue/automatic_updates-3342726
  • issue/automatic_updates-3337667
  • issue/automatic_updates-3343463
  • issue/automatic_updates-3345766
  • issue/automatic_updates-3345754
  • issue/automatic_updates-3345633
  • issue/automatic_updates-3345772
  • issue/automatic_updates-3345769
  • issue/automatic_updates-3345761
  • issue/automatic_updates-3345755
  • issue/automatic_updates-3345760
  • issue/automatic_updates-3345757
  • issue/automatic_updates-3346520
  • issue/automatic_updates-3346545
  • issue/automatic_updates-3337054
  • issue/automatic_updates-3346628
  • issue/automatic_updates-3346717
  • issue/automatic_updates-3346594
  • issue/automatic_updates-3346659
  • issue/automatic_updates-3347031
  • issue/automatic_updates-3346547
  • issue/automatic_updates-3347164
  • issue/automatic_updates-3318306
  • issue/automatic_updates-3345646
  • issue/automatic_updates-3347165
  • issue/automatic_updates-3347959
  • issue/automatic_updates-3347267
  • issue/automatic_updates-3338346
  • issue/automatic_updates-3348122
  • issue/automatic_updates-3348129
  • issue/automatic_updates-3348162
  • issue/automatic_updates-3348276
  • issue/automatic_updates-3348441
  • issue/automatic_updates-3351604
  • issue/automatic_updates-3316843
  • issue/automatic_updates-3351908
  • issue/automatic_updates-3352731
  • issue/automatic_updates-3352898
  • issue/automatic_updates-3348866
  • issue/automatic_updates-3342817
  • issue/automatic_updates-3348159
  • issue/automatic_updates-3349142
  • issue/automatic_updates-3349966
  • issue/automatic_updates-3350909
  • issue/automatic_updates-3351594
  • issue/automatic_updates-3351883
  • issue/automatic_updates-3351925
  • issue/automatic_updates-3352198
  • issue/automatic_updates-3334552
  • issue/automatic_updates-3342790
  • issue/automatic_updates-3345222
  • issue/automatic_updates-3351212
  • issue/automatic_updates-3351093
  • issue/automatic_updates-3351247
  • issue/automatic_updates-3351962
  • issue/automatic_updates-3345641
  • issue/automatic_updates-3338940
  • issue/automatic_updates-3343721
  • issue/automatic_updates-3351069
  • issue/automatic_updates-3353219
  • issue/automatic_updates-3159920
  • issue/automatic_updates-3352355
  • issue/automatic_updates-3341469
  • issue/automatic_updates-3354099
  • issue/automatic_updates-3339659
  • issue/automatic_updates-3354312
  • issue/automatic_updates-3351895
  • issue/automatic_updates-3354249
  • issue/automatic_updates-3353270
  • issue/automatic_updates-3354003
  • issue/automatic_updates-3355074
  • issue/automatic_updates-3355094
  • issue/automatic_updates-3355105
  • issue/automatic_updates-3355162
  • issue/automatic_updates-3355446
  • issue/automatic_updates-3355045
  • issue/automatic_updates-3355558
  • issue/automatic_updates-3355553
  • issue/automatic_updates-3354594
  • issue/automatic_updates-3355609
  • issue/automatic_updates-3354325
  • issue/automatic_updates-3356395
  • issue/automatic_updates-3356638
  • issue/automatic_updates-3356640
  • issue/automatic_updates-3354701
  • issue/automatic_updates-3355463
  • issue/automatic_updates-3356804
  • issue/automatic_updates-3357721
  • issue/automatic_updates-3357578
  • issue/automatic_updates-3357657
  • issue/automatic_updates-3304108
  • issue/automatic_updates-3357941
  • issue/automatic_updates-3358012
  • issue/automatic_updates-3345535
  • issue/automatic_updates-3354827
  • issue/automatic_updates-3358570
  • issue/automatic_updates-3358878
  • issue/automatic_updates-3355628
  • issue/automatic_updates-3358504
  • issue/automatic_updates-3357969
  • issue/automatic_updates-3359609
  • issue/automatic_updates-3359727
  • issue/automatic_updates-3359825
  • issue/automatic_updates-3359820
  • issue/automatic_updates-3360548
  • issue/automatic_updates-3357480
  • issue/automatic_updates-3360656
  • issue/automatic_updates-3360763
  • issue/automatic_updates-3360655
  • issue/automatic_updates-3355618
  • issue/automatic_updates-3349351
  • issue/automatic_updates-3362110
  • issue/automatic_updates-3362143
  • issue/automatic_updates-3362589
  • issue/automatic_updates-3349004
  • issue/automatic_updates-3362507
  • issue/automatic_updates-3362746
  • issue/automatic_updates-3362978
  • issue/automatic_updates-3363259
  • issue/automatic_updates-3363725
  • issue/automatic_updates-3363926
  • issue/automatic_updates-3363937
  • issue/automatic_updates-3364514
  • issue/automatic_updates-3284443
  • issue/automatic_updates-3363938
  • issue/automatic_updates-3364731
  • issue/automatic_updates-3364748
  • issue/automatic_updates-3364735
  • issue/automatic_updates-3364725
  • issue/automatic_updates-3359670
  • issue/automatic_updates-3365133
  • issue/automatic_updates-3365151
  • issue/automatic_updates-3365177
  • issue/automatic_updates-3364958
  • issue/automatic_updates-3365390
  • issue/automatic_updates-3365414
  • issue/automatic_updates-3346644
  • issue/automatic_updates-3366267
  • issue/automatic_updates-3366289
  • issue/automatic_updates-3366499
  • issue/automatic_updates-3365437
  • issue/automatic_updates-3354914
  • issue/automatic_updates-3253828
  • issue/automatic_updates-3345484
  • issue/automatic_updates-3352846
  • issue/automatic_updates-3368741
  • issue/automatic_updates-3406008
  • issue/automatic_updates-3406122
  • issue/automatic_updates-3370197
  • issue/automatic_updates-3366271
  • issue/automatic_updates-3364135
  • issue/automatic_updates-3370603
  • issue/automatic_updates-3400146
  • issue/automatic_updates-3406010
  • issue/automatic_updates-3404429
  • issue/automatic_updates-3371212
  • issue/automatic_updates-3371076
  • issue/automatic_updates-3372673
  • issue/automatic_updates-3368808
  • issue/automatic_updates-3374175
  • issue/automatic_updates-3374739
  • issue/automatic_updates-3374753
  • issue/automatic_updates-3375679
  • issue/automatic_updates-3377237
  • issue/automatic_updates-3377245
  • issue/automatic_updates-3378774
  • issue/automatic_updates-3378793
  • issue/automatic_updates-3360485
  • issue/automatic_updates-3380698
  • issue/automatic_updates-3375940
  • issue/automatic_updates-3381294
  • issue/automatic_updates-3381484
  • issue/automatic_updates-3382942
  • issue/automatic_updates-3383462
  • issue/automatic_updates-3383451
  • issue/automatic_updates-3384359
  • issue/automatic_updates-3384637
  • issue/automatic_updates-3375640
  • issue/automatic_updates-3386135
  • issue/automatic_updates-3386533
  • issue/automatic_updates-3387610
  • issue/automatic_updates-3387637
  • issue/automatic_updates-3387656
  • issue/automatic_updates-3389157
  • issue/automatic_updates-3388965
  • issue/automatic_updates-3387379
  • issue/automatic_updates-3390493
  • issue/automatic_updates-3308235
  • issue/automatic_updates-3391715
  • issue/automatic_updates-3392246
  • issue/automatic_updates-3393633
  • issue/automatic_updates-3379344
  • issue/automatic_updates-3394413
  • issue/automatic_updates-3394705
  • issue/automatic_updates-3394936
  • issue/automatic_updates-3363497
  • issue/automatic_updates-3395782
  • issue/automatic_updates-3341406
  • issue/automatic_updates-3311472
  • issue/automatic_updates-3397228
  • issue/automatic_updates-3352654
  • issue/automatic_updates-3398782
  • issue/automatic_updates-3399147
  • issue/automatic_updates-3399155
  • issue/automatic_updates-3406812
  • issue/automatic_updates-3408483
  • issue/automatic_updates-3408488
  • issue/automatic_updates-3408560
  • issue/automatic_updates-3437633
  • issue/automatic_updates-3408835
  • issue/automatic_updates-3408937
  • issue/automatic_updates-3409491
  • issue/automatic_updates-3409519
  • issue/automatic_updates-3377458
  • issue/automatic_updates-3437951
  • issue/automatic_updates-3409774
  • issue/automatic_updates-3410047
  • issue/automatic_updates-3411110
  • issue/automatic_updates-3411241
  • issue/automatic_updates-3411276
  • issue/automatic_updates-3411392
  • issue/automatic_updates-3411240
  • issue/automatic_updates-3412630
  • issue/automatic_updates-3413866
  • issue/automatic_updates-3414168
  • issue/automatic_updates-3415291
  • issue/automatic_updates-3415389
  • issue/automatic_updates-3415403
  • issue/automatic_updates-3416768
  • issue/automatic_updates-3417905
  • issue/automatic_updates-3420188
  • issue/automatic_updates-3421641
  • issue/automatic_updates-3424290
  • issue/automatic_updates-3426229
  • issue/automatic_updates-3426666
  • issue/automatic_updates-3426716
  • issue/automatic_updates-3428199
  • issue/automatic_updates-3436741
  • issue/automatic_updates-3441923
  • issue/automatic_updates-3428651
  • issue/automatic_updates-3441799
  • issue/automatic_updates-3443249
  • issue/automatic_updates-3428922
  • issue/automatic_updates-3441817
  • issue/automatic_updates-3429248
  • issue/automatic_updates-3440646
  • issue/automatic_updates-3437877
  • issue/automatic_updates-3445149
  • issue/automatic_updates-3429268
  • issue/automatic_updates-3442153
  • issue/automatic_updates-3438156
  • issue/automatic_updates-3436993
  • issue/automatic_updates-3437704
  • issue/automatic_updates-3432496
  • issue/automatic_updates-3440006
  • issue/automatic_updates-3435893
  • issue/automatic_updates-3441577
  • issue/automatic_updates-3437023
  • issue/automatic_updates-3432391
  • issue/automatic_updates-3432447
  • issue/automatic_updates-3432472
  • issue/automatic_updates-3432489
  • issue/automatic_updates-3432476
  • issue/automatic_updates-3435918
  • issue/automatic_updates-3439067
  • issue/automatic_updates-3437409
  • issue/automatic_updates-3449093
  • issue/automatic_updates-3449480
  • issue/automatic_updates-3449519
  • issue/automatic_updates-3449631
  • issue/automatic_updates-3449636
  • issue/automatic_updates-3449689
  • issue/automatic_updates-3449693
  • issue/automatic_updates-3450884
  • issue/automatic_updates-3452870
  • issue/automatic_updates-3453030
  • issue/automatic_updates-3455161
  • issue/automatic_updates-3459557
  • issue/automatic_updates-3462138
  • issue/automatic_updates-3462168
  • issue/automatic_updates-3462883
  • issue/automatic_updates-3463662
  • issue/automatic_updates-3463813
  • issue/automatic_updates-3446371
  • issue/automatic_updates-3465155
  • issue/automatic_updates-3340355
  • issue/automatic_updates-3467749
  • issue/automatic_updates-3473410
  • issue/automatic_updates-3441926
  • issue/automatic_updates-3474603
  • issue/automatic_updates-3484802
  • issue/automatic_updates-3498586
  • issue/automatic_updates-3499481
  • issue/automatic_updates-3498018
  • issue/automatic_updates-3506632
  • issue/automatic_updates-3511959
  • issue/automatic_updates-3511943
981 results
Show changes
Commits on Source (85)
Showing
with 645 additions and 111 deletions
################
# DrupalCI GitLabCI template
#
# Gitlab-ci.yml to replicate DrupalCI testing for Contrib
#
# With thanks to:
# * The GitLab Acceleration Initiative participants
# * DrupalSpoons
################
################
# Guidelines
#
# This template is designed to give any Contrib maintainer everything they need to test, without requiring modification. It is also designed to keep up to date with Core Development automatically through the use of include files that can be centrally maintained.
#
# However, you can modify this template if you have additional needs for your project.
################
################
# Includes
#
# Additional configuration can be provided through includes.
# One advantage of include files is that if they are updated upstream, the changes affect all pipelines using that include.
#
# Includes can be overridden by re-declaring anything provided in an include, here in gitlab-ci.yml
# https://docs.gitlab.com/ee/ci/yaml/includes.html#override-included-configuration-values
################
include:
################
# DrupalCI includes:
# As long as you include this, any future includes added by the Drupal Association will be accessible to your pipelines automatically.
# View these include files at https://git.drupalcode.org/project/gitlab_templates/
################
- project: $_GITLAB_TEMPLATES_REPO
# "ref" value can be:
# - Recommended (default) - `ref: $_GITLAB_TEMPLATES_REF` - The Drupal Association will update this value to the recommended tag for contrib.
# - Latest - `ref: main` - Get the latest additions and bug fixes as they are merged into the templates.
# - Minor or Major latests - `ref: 1.x-latest` or `ref: 1.0.x-latest` - Get the latest additions within a minor (mostly bugfixes) or major (bugs and new features).
# - Fixed tag - `ref: 1.0.1` - Set the value to a known tag. This will not get any updates.
# If you change the default value of ref, you should set the _CURL_TEMPLATES_REF variable in the variables section to be the same as set here.
ref: $_GITLAB_TEMPLATES_REF
file:
- '/includes/include.drupalci.main.yml'
# EXPERIMENTAL: For Drupal 7, remove the above line and uncomment the below.
# - '/includes/include.drupalci.main-d7.yml'
- '/includes/include.drupalci.variables.yml'
- '/includes/include.drupalci.workflows.yml'
################
# Pipeline configuration variables
#
# These are the variables provided to the Run Pipeline form that a user may want to override.
#
# Docs at https://git.drupalcode.org/project/gitlab_templates/-/blob/1.0.x/includes/include.drupalci.variables.yml
################
variables:
_PHPUNIT_CONCURRENT: '1'
_PHPUNIT_TESTGROUPS: ''
# Always test against the previous minor version of core.
OPT_IN_TEST_PREVIOUS_MINOR: '1'
# @todo Remove this line when https://drupal.org/i/3414093 is fixed.
CI_DEBUG_SERVICES: "true"
_TARGET_DB_TYPE: "mariadb"
_TARGET_DB_VERSION: "10.6"
# Always show environment variables, to help in debugging CI problems.
_SHOW_ENVIRONMENT_VARIABLES: '1'
###################################################################################
#
# *
# /(
# ((((,
# /(((((((
# ((((((((((*
# ,(((((((((((((((
# ,(((((((((((((((((((
# ((((((((((((((((((((((((*
# *(((((((((((((((((((((((((((((
# ((((((((((((((((((((((((((((((((((*
# *(((((((((((((((((( .((((((((((((((((((
# ((((((((((((((((((. /(((((((((((((((((*
# /((((((((((((((((( .(((((((((((((((((,
# ,(((((((((((((((((( ((((((((((((((((((
# .(((((((((((((((((((( .(((((((((((((((((
# ((((((((((((((((((((((( ((((((((((((((((/
# (((((((((((((((((((((((((((/ ,(((((((((((((((*
# .((((((((((((((/ /(((((((((((((. ,(((((((((((((((
# *(((((((((((((( ,(((((((((((((/ *((((((((((((((.
# ((((((((((((((, /(((((((((((((. ((((((((((((((,
# (((((((((((((/ ,(((((((((((((* ,(((((((((((((,
# *((((((((((((( .((((((((((((((( ,(((((((((((((
# ((((((((((((/ /((((((((((((((((((. ,((((((((((((/
# ((((((((((((( *(((((((((((((((((((((((* *((((((((((((
# ((((((((((((( ,(((((((((((((..((((((((((((( *((((((((((((
# ((((((((((((, /((((((((((((* /((((((((((((/ ((((((((((((
# ((((((((((((( /((((((((((((/ (((((((((((((* ((((((((((((
# (((((((((((((/ /(((((((((((( ,((((((((((((, *((((((((((((
# (((((((((((((( *(((((((((((/ *((((((((((((. ((((((((((((/
# *((((((((((((((((((((((((((, /(((((((((((((((((((((((((
# ((((((((((((((((((((((((( ((((((((((((((((((((((((,
# .(((((((((((((((((((((((/ ,(((((((((((((((((((((((
# ((((((((((((((((((((((/ ,(((((((((((((((((((((/
# *((((((((((((((((((((( (((((((((((((((((((((,
# ,(((((((((((((((((((((, ((((((((((((((((((((/
# ,(((((((((((((((((((((* /((((((((((((((((((((
# ((((((((((((((((((((((, ,/((((((((((((((((((((,
# ,(((((((((((((((((((((((((((((((((((((((((((((((((((
# .(((((((((((((((((((((((((((((((((((((((((((((
# .((((((((((((((((((((((((((((((((((((,.
# .,(((((((((((((((((((((((((.
#
###################################################################################
.extra-variables: &extra-variables
- MODULE_DIR=$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME
# Strip the `-dev` suffix out of $_TARGET_CORE to reveal the name of the Drupal core branch.
- CORE_BRANCH=`echo $_TARGET_CORE | sed -e "s/-dev$//"`
composer:
extends: .composer-base
before_script:
# In this case, we want to archive everything.
- rm .gitattributes
- composer archive --file=module
after_script:
- *extra-variables
- rm -r -f $MODULE_DIR
- mkdir -p $MODULE_DIR
- tar -x -f module.tar -C $MODULE_DIR
- rm module.tar
- git clone https://git.drupalcode.org/project/drupal.git --depth 1 --branch $CORE_BRANCH /tmp/drupal-core
- cp -R /tmp/drupal-core/composer .
# Copy to web as well as \Drupal\Composer\Composer will expect it be there.
- cp -R /tmp/drupal-core/composer web
composer (previous minor):
before_script:
- !reference [composer, before_script]
after_script:
- !reference [composer, after_script]
composer (previous minor):
before_script:
- !reference [composer, before_script]
after_script:
- !reference [composer, after_script]
phpcs:
before_script:
# Use core's PHPCS configuration.
- cp $_WEB_ROOT/core/phpcs.xml.dist .
phpstan:
before_script:
- *extra-variables
# Ensure our PHPStan configuration has the correct include path to core's PHPStan configuration.
- sed -i "s#%rootDir%/../../../#%rootDir%/../../../$_WEB_ROOT/#" $MODULE_DIR/phpstan.neon
phpunit:
parallel:
matrix:
- MODULE:
- automatic_updates_extensions
- automatic_updates
- package_manager
TEST_TYPE:
- Unit
- Kernel
- Functional
- FunctionalJavascript
- Build
rules:
# Automatic Updates Extensions has no unit or functional JavaScript tests.
- if: $MODULE == "automatic_updates_extensions" && ($TEST_TYPE == "Unit" || $TEST_TYPE == "FunctionalJavascript")
when: never
# Package Manager has no functional JavaScript tests.
- if: $MODULE == "package_manager" && $TEST_TYPE == "FunctionalJavascript"
when: never
- when: on_success
variables:
_PHPUNIT_EXTRA: '--types PHPUnit-$TEST_TYPE --module $MODULE'
phpunit (previous minor):
rules:
- !reference [phpunit, rules]
...@@ -11,7 +11,7 @@ Follow and read more on the [Automatic Updates Initiative overview and roadmap]( ...@@ -11,7 +11,7 @@ Follow and read more on the [Automatic Updates Initiative overview and roadmap](
Automatic Updates includes a sub-module, Automatic Updates Extensions, which supports updating contributed modules and themes. Automatic Updates includes a sub-module, Automatic Updates Extensions, which supports updating contributed modules and themes.
⚠️ ☢️️ **Automatic Updates Extensions is still experimental and under heavy development.** We encourage you to test it in your local development environment, or another low-stakes testing situation, but it is emphatically NOT ready for use in a production environment. ☢️ ⚠️ ⚠️ ☢️️ Depending on the contributed module or theme, updates to these projects could make the site inoperable. If possible, it is highly recommended that you test these updates in a development environment first.☢️ ⚠️
### More info ### More info
......
name: 'Automatic Updates' name: 'Automatic Updates'
type: module type: module
description: 'Automatically updates Drupal core.' description: 'Automatically updates Drupal core.'
core_version_requirement: ^10 core_version_requirement: ^10.1
dependencies: dependencies:
- drupal:package_manager - drupal:package_manager
- drupal:update - drupal:update
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
declare(strict_types = 1); declare(strict_types = 1);
use Drupal\automatic_updates\CronUpdateStage; use Drupal\automatic_updates\CronUpdateRunner;
use Drupal\automatic_updates\UpdateStage;
use Drupal\automatic_updates\Validation\StatusCheckRequirements; use Drupal\automatic_updates\Validation\StatusCheckRequirements;
use Drupal\system\SystemManager; use Drupal\system\SystemManager;
...@@ -15,7 +16,7 @@ use Drupal\system\SystemManager; ...@@ -15,7 +16,7 @@ use Drupal\system\SystemManager;
* Implements hook_uninstall(). * Implements hook_uninstall().
*/ */
function automatic_updates_uninstall() { function automatic_updates_uninstall() {
\Drupal::service('automatic_updates.update_stage')->destroy(TRUE); \Drupal::service(UpdateStage::class)->destroy(TRUE);
} }
/** /**
...@@ -30,7 +31,7 @@ function automatic_updates_requirements($phase) { ...@@ -30,7 +31,7 @@ function automatic_updates_requirements($phase) {
// Check that site has cron updates enabled or not. // Check that site has cron updates enabled or not.
// @todo Remove in https://www.drupal.org/project/automatic_updates/issues/3284443 // @todo Remove in https://www.drupal.org/project/automatic_updates/issues/3284443
if (\Drupal::configFactory()->get('automatic_updates.settings')->get('unattended.level') !== CronUpdateStage::DISABLED) { if (\Drupal::configFactory()->get('automatic_updates.settings')->get('unattended.level') !== CronUpdateRunner::DISABLED) {
$requirements['automatic_updates_cron'] = [ $requirements['automatic_updates_cron'] = [
'title' => t('Cron installs updates automatically'), 'title' => t('Cron installs updates automatically'),
'severity' => SystemManager::REQUIREMENT_WARNING, 'severity' => SystemManager::REQUIREMENT_WARNING,
......
...@@ -8,12 +8,16 @@ ...@@ -8,12 +8,16 @@
declare(strict_types = 1); declare(strict_types = 1);
use Drupal\automatic_updates\BatchProcessor; use Drupal\automatic_updates\BatchProcessor;
use Drupal\automatic_updates\CronUpdateStage; use Drupal\automatic_updates\CronUpdateRunner;
use Drupal\automatic_updates\ReleaseChooser;
use Drupal\automatic_updates\UpdateStage;
use Drupal\automatic_updates\Validation\StatusChecker;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\automatic_updates\Validation\AdminStatusCheckMessages; use Drupal\automatic_updates\Validation\AdminStatusCheckMessages;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\package_manager\ComposerInspector; use Drupal\package_manager\ComposerInspector;
use Drupal\Core\Utility\Error;
use Drupal\system\Controller\DbUpdateController; use Drupal\system\Controller\DbUpdateController;
/** /**
...@@ -108,7 +112,7 @@ function automatic_updates_mail(string $key, array &$message, array $params): vo ...@@ -108,7 +112,7 @@ function automatic_updates_mail(string $key, array &$message, array $params): vo
// If this email was related to an unattended update, explicitly state that // If this email was related to an unattended update, explicitly state that
// this isn't supported yet. // this isn't supported yet.
if (str_starts_with($key, 'cron_')) { if (str_starts_with($key, 'cron_')) {
$message['body'][] = t('This e-mail was sent by the Automatic Updates module. Unattended updates are not yet fully supported.', [], $options); $message['body'][] = t('This email was sent by the Automatic Updates module. Unattended updates are not yet fully supported.', [], $options);
$message['body'][] = t('If you are using this feature in production, it is strongly recommended for you to visit your site and ensure that everything still looks good.', [], $options); $message['body'][] = t('If you are using this feature in production, it is strongly recommended for you to visit your site and ensure that everything still looks good.', [], $options);
} }
} }
...@@ -116,7 +120,23 @@ function automatic_updates_mail(string $key, array &$message, array $params): vo ...@@ -116,7 +120,23 @@ function automatic_updates_mail(string $key, array &$message, array $params): vo
/** /**
* Implements hook_page_top(). * Implements hook_page_top().
*/ */
function automatic_updates_page_top() { function automatic_updates_page_top(array &$page_top) {
// Ensure error messages will be displayed on the batch page.
// @todo Remove this work around when https://drupal.org/i/3406612 is fixed.
if (\Drupal::routeMatch()->getRouteName() === 'system.batch_page.html') {
// Directly render a status message placeholder without any messages.
// Messages are not intended to be show on the batch page, but in the event
// an error in a AJAX callback the messages will be displayed.
$page_top['messages'] = [
'#theme' => 'status_messages',
'#message_list' => [],
'#status_headings' => [
'status' => t('Status message'),
'error' => t('Error message'),
'warning' => t('Warning message'),
],
];
}
/** @var \Drupal\automatic_updates\Validation\AdminStatusCheckMessages $status_check_messages */ /** @var \Drupal\automatic_updates\Validation\AdminStatusCheckMessages $status_check_messages */
$status_check_messages = \Drupal::classResolver(AdminStatusCheckMessages::class); $status_check_messages = \Drupal::classResolver(AdminStatusCheckMessages::class);
$status_check_messages->displayAdminPageMessages(); $status_check_messages->displayAdminPageMessages();
...@@ -157,14 +177,14 @@ function automatic_updates_modules_installed($modules) { ...@@ -157,14 +177,14 @@ function automatic_updates_modules_installed($modules) {
// Run the status checkers if needed when any modules are installed in // Run the status checkers if needed when any modules are installed in
// case they provide status checkers. // case they provide status checkers.
/** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */ /** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */
$status_checker = \Drupal::service('automatic_updates.status_checker'); $status_checker = \Drupal::service(StatusChecker::class);
$status_checker->run(); $status_checker->run();
/** @var \Drupal\automatic_updates\CronUpdateStage $stage */ /** @var \Drupal\automatic_updates\CronUpdateRunner $runner */
$stage = \Drupal::service('automatic_updates.cron_update_stage'); $runner = \Drupal::service(CronUpdateRunner::class);
// If cron updates are disabled status check messages will not be displayed on // If cron updates are disabled status check messages will not be displayed on
// admin pages. Therefore, after installing the module the user will not be // admin pages. Therefore, after installing the module the user will not be
// alerted to any problems until they access the status report page. // alerted to any problems until they access the status report page.
if ($stage->getMode() === CronUpdateStage::DISABLED) { if ($runner->getMode() === CronUpdateRunner::DISABLED) {
/** @var \Drupal\automatic_updates\Validation\AdminStatusCheckMessages $status_check_messages */ /** @var \Drupal\automatic_updates\Validation\AdminStatusCheckMessages $status_check_messages */
$status_check_messages = \Drupal::classResolver(AdminStatusCheckMessages::class); $status_check_messages = \Drupal::classResolver(AdminStatusCheckMessages::class);
$status_check_messages->displayResultSummary(); $status_check_messages->displayResultSummary();
...@@ -178,7 +198,7 @@ function automatic_updates_modules_uninstalled() { ...@@ -178,7 +198,7 @@ function automatic_updates_modules_uninstalled() {
// Run the status checkers if needed when any modules are uninstalled in // Run the status checkers if needed when any modules are uninstalled in
// case they provided status checkers. // case they provided status checkers.
/** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */ /** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */
$status_checker = \Drupal::service('automatic_updates.status_checker'); $status_checker = \Drupal::service(StatusChecker::class);
$status_checker->run(); $status_checker->run();
} }
...@@ -205,9 +225,9 @@ function automatic_updates_form_update_settings_alter(array &$form): void { ...@@ -205,9 +225,9 @@ function automatic_updates_form_update_settings_alter(array &$form): void {
'#type' => 'radios', '#type' => 'radios',
'#title' => t('Unattended background updates'), '#title' => t('Unattended background updates'),
'#options' => [ '#options' => [
CronUpdateStage::DISABLED => t('Disabled'), CronUpdateRunner::DISABLED => t('Disabled'),
CronUpdateStage::SECURITY => t('Security updates only'), CronUpdateRunner::SECURITY => t('Security updates only'),
CronUpdateStage::ALL => t('All patch releases'), CronUpdateRunner::ALL => t('All patch releases'),
], ],
'#default_value' => $config->get('unattended.level'), '#default_value' => $config->get('unattended.level'),
'#description' => t('When background updates are applied, your site will be briefly put into maintenance mode.'), '#description' => t('When background updates are applied, your site will be briefly put into maintenance mode.'),
...@@ -223,7 +243,7 @@ function automatic_updates_form_update_settings_alter(array &$form): void { ...@@ -223,7 +243,7 @@ function automatic_updates_form_update_settings_alter(array &$form): void {
'#states' => [ '#states' => [
'invisible' => [ 'invisible' => [
'input[name="unattended_level"]' => [ 'input[name="unattended_level"]' => [
'value' => CronUpdateStage::DISABLED, 'value' => CronUpdateRunner::DISABLED,
], ],
], ],
], ],
...@@ -258,10 +278,10 @@ function automatic_updates_preprocess_update_project_status(array &$variables) { ...@@ -258,10 +278,10 @@ function automatic_updates_preprocess_update_project_status(array &$variables) {
if ($project['name'] !== 'drupal') { if ($project['name'] !== 'drupal') {
return; return;
} }
$stage = \Drupal::service('automatic_updates.update_stage'); $stage = \Drupal::service(UpdateStage::class);
$supported_target_versions = []; $supported_target_versions = [];
/** @var \Drupal\automatic_updates\ReleaseChooser $recommender */ /** @var \Drupal\automatic_updates\ReleaseChooser $recommender */
$recommender = \Drupal::service('automatic_updates.release_chooser'); $recommender = \Drupal::service(ReleaseChooser::class);
try { try {
if ($installed_minor_release = $recommender->getLatestInInstalledMinor($stage)) { if ($installed_minor_release = $recommender->getLatestInInstalledMinor($stage)) {
$supported_target_versions[] = $installed_minor_release->getVersion(); $supported_target_versions[] = $installed_minor_release->getVersion();
...@@ -273,7 +293,7 @@ function automatic_updates_preprocess_update_project_status(array &$variables) { ...@@ -273,7 +293,7 @@ function automatic_updates_preprocess_update_project_status(array &$variables) {
catch (RuntimeException $exception) { catch (RuntimeException $exception) {
// If for some reason we are not able to get the update recommendations // If for some reason we are not able to get the update recommendations
// do not alter the report. // do not alter the report.
watchdog_exception('automatic_updates', $exception); Error::logException(\Drupal::logger('automatic_updates'), $exception);
return; return;
} }
$variables['#attached']['library'][] = 'automatic_updates/update_status'; $variables['#attached']['library'][] = 'automatic_updates/update_status';
......
...@@ -2,64 +2,42 @@ services: ...@@ -2,64 +2,42 @@ services:
_defaults: _defaults:
autowire: true autowire: true
automatic_updates.route_subscriber: Drupal\automatic_updates\Routing\RouteSubscriber:
class: Drupal\automatic_updates\Routing\RouteSubscriber
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
automatic_updates.status_checker: Drupal\automatic_updates\Validation\StatusChecker:
class: Drupal\automatic_updates\Validation\StatusChecker
arguments: arguments:
# @todo Remove this when https://drupal.org/i/3325557 lands. # @todo Remove this when https://drupal.org/i/3325557 lands.
$key_value_expirable_factory: '@keyvalue.expirable' $key_value_expirable_factory: '@keyvalue.expirable'
$resultsTimeToLive: 24 $resultsTimeToLive: 24
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
Drupal\automatic_updates\Validation\StatusChecker: '@automatic_updates.status_checker' Drupal\automatic_updates\StatusCheckMailer: ~
automatic_updates.status_check_mailer: Drupal\automatic_updates\UpdateStage:
class: Drupal\automatic_updates\StatusCheckMailer
Drupal\automatic_updates\StatusCheckMailer: '@automatic_updates.status_check_mailer'
automatic_updates.update_stage:
class: Drupal\automatic_updates\UpdateStage
calls: calls:
- ['setLogger', ['@logger.channel.automatic_updates']] - ['setLogger', ['@logger.channel.automatic_updates']]
Drupal\automatic_updates\UpdateStage: '@automatic_updates.update_stage' Drupal\automatic_updates\CronUpdateRunner:
automatic_updates.cron_update_stage:
class: Drupal\automatic_updates\CronUpdateStage
calls: calls:
- ['setLogger', ['@logger.channel.automatic_updates']] - ['setLogger', ['@logger.channel.automatic_updates']]
arguments:
$inner: '@automatic_updates.cron_update_stage.inner'
decorates: 'cron' decorates: 'cron'
Drupal\automatic_updates\CronUpdateStage: '@automatic_updates.cron_update_stage' Drupal\automatic_updates\Validator\RequestedUpdateValidator:
automatic_updates.requested_update_validator:
class: Drupal\automatic_updates\Validator\RequestedUpdateValidator
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
automatic_updates.staged_projects_validator: Drupal\automatic_updates\Validator\StagedProjectsValidator:
class: Drupal\automatic_updates\Validator\StagedProjectsValidator
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
Drupal\automatic_updates\Validator\StagedProjectsValidator: '@automatic_updates.staged_projects_validator' Drupal\automatic_updates\ReleaseChooser: ~
automatic_updates.release_chooser: Drupal\automatic_updates\Validator\CronFrequencyValidator:
class: Drupal\automatic_updates\ReleaseChooser
arguments:
- '@automatic_updates.validator.version_policy'
Drupal\automatic_updates\ReleaseChooser: '@automatic_updates.release_chooser'
automatic_updates.cron_frequency_validator:
class: Drupal\automatic_updates\Validator\CronFrequencyValidator
arguments: arguments:
$lock: '@lock' $lock: '@lock'
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
automatic_updates.validator.staged_database_updates: Drupal\automatic_updates\Validator\StagedDatabaseUpdateValidator:
class: Drupal\automatic_updates\Validator\StagedDatabaseUpdateValidator
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
automatic_updates.validator.version_policy: Drupal\automatic_updates\Validator\VersionPolicyValidator:
class: Drupal\automatic_updates\Validator\VersionPolicyValidator
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
Drupal\automatic_updates\Validator\VersionPolicyValidator: '@automatic_updates.validator.version_policy'
Drupal\automatic_updates\Validator\WindowsValidator: Drupal\automatic_updates\Validator\WindowsValidator:
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
...@@ -75,4 +53,9 @@ services: ...@@ -75,4 +53,9 @@ services:
Drupal\automatic_updates\MaintenanceModeAwareCommitter: Drupal\automatic_updates\MaintenanceModeAwareCommitter:
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
Drupal\automatic_updates\CommandExecutor: {} Drupal\automatic_updates\CommandExecutor:
arguments:
$appRoot: '%app.root%'
Drupal\automatic_updates\Validator\ConsoleUserValidator:
tags:
- { name: event_subscriber }
name: 'Automatic Updates Extensions' name: 'Automatic Updates Extensions'
type: module type: module
description: 'Allows updates to themes and modules' description: 'Allows updates to themes and modules'
core_version_requirement: ^10 core_version_requirement: ^10.1
lifecycle: experimental
dependencies: dependencies:
- drupal:automatic_updates - drupal:automatic_updates
...@@ -2,10 +2,13 @@ services: ...@@ -2,10 +2,13 @@ services:
_defaults: _defaults:
autowire: true autowire: true
automatic_updates_extensions.update_stage: Drupal\automatic_updates_extensions\ExtensionUpdateStage: ~
class: Drupal\automatic_updates_extensions\ExtensionUpdateStage Drupal\automatic_updates_extensions\Validator\UpdateReleaseValidator:
Drupal\automatic_updates_extensions\ExtensionUpdateStage: '@automatic_updates_extensions.update_stage' tags:
automatic_updates_extensions.validator.target_release: - { name: event_subscriber }
class: Drupal\automatic_updates_extensions\Validator\UpdateReleaseValidator Drupal\automatic_updates_extensions\Validator\ForbidCoreChangesValidator:
tags:
- { name: event_subscriber }
Drupal\automatic_updates_extensions\Validator\RequestedUpdateValidator:
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
...@@ -30,7 +30,7 @@ final class BatchProcessor { ...@@ -30,7 +30,7 @@ final class BatchProcessor {
* The update stage service. * The update stage service.
*/ */
private static function getStage(): ExtensionUpdateStage { private static function getStage(): ExtensionUpdateStage {
return \Drupal::service('automatic_updates_extensions.update_stage'); return \Drupal::service(ExtensionUpdateStage::class);
} }
/** /**
...@@ -84,7 +84,11 @@ final class BatchProcessor { ...@@ -84,7 +84,11 @@ final class BatchProcessor {
static::getStage()->claim($stage_id)->stage(); static::getStage()->claim($stage_id)->stage();
} }
catch (\Throwable $e) { catch (\Throwable $e) {
static::clean($stage_id, $context); // If the stage was not already destroyed because of this exception
// destroy it.
if (!static::getStage()->isAvailable()) {
static::clean($stage_id, $context);
}
static::handleException($e, $context); static::handleException($e, $context);
} }
} }
......
...@@ -5,7 +5,7 @@ declare(strict_types = 1); ...@@ -5,7 +5,7 @@ declare(strict_types = 1);
namespace Drupal\automatic_updates_extensions; namespace Drupal\automatic_updates_extensions;
use Drupal\Component\Datetime\TimeInterface; use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TempStore\SharedTempStoreFactory; use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\package_manager\ComposerInspector; use Drupal\package_manager\ComposerInspector;
...@@ -26,7 +26,12 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; ...@@ -26,7 +26,12 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
* This class is an internal part of the module's update handling and * This class is an internal part of the module's update handling and
* should not be used by external code. * should not be used by external code.
*/ */
class ExtensionUpdateStage extends StageBase { final class ExtensionUpdateStage extends StageBase {
/**
* {@inheritdoc}
*/
protected string $type = 'automatic_updates_extensions:attended';
/** /**
* Constructs a new ExtensionUpdateStage object. * Constructs a new ExtensionUpdateStage object.
...@@ -41,8 +46,8 @@ class ExtensionUpdateStage extends StageBase { ...@@ -41,8 +46,8 @@ class ExtensionUpdateStage extends StageBase {
* The stager service. * The stager service.
* @param \PhpTuf\ComposerStager\API\Core\CommitterInterface $committer * @param \PhpTuf\ComposerStager\API\Core\CommitterInterface $committer
* The committer service. * The committer service.
* @param \Drupal\Core\File\FileSystemInterface $fileSystem * @param \Drupal\Core\Queue\QueueFactory $queueFactory
* The file system service. * The queue factory.
* @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $eventDispatcher * @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $eventDispatcher
* The event dispatcher service. * The event dispatcher service.
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempStoreFactory * @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempStoreFactory
...@@ -60,14 +65,14 @@ class ExtensionUpdateStage extends StageBase { ...@@ -60,14 +65,14 @@ class ExtensionUpdateStage extends StageBase {
BeginnerInterface $beginner, BeginnerInterface $beginner,
StagerInterface $stager, StagerInterface $stager,
CommitterInterface $committer, CommitterInterface $committer,
FileSystemInterface $fileSystem, QueueFactory $queueFactory,
EventDispatcherInterface $eventDispatcher, EventDispatcherInterface $eventDispatcher,
SharedTempStoreFactory $tempStoreFactory, SharedTempStoreFactory $tempStoreFactory,
TimeInterface $time, TimeInterface $time,
PathFactoryInterface $pathFactory, PathFactoryInterface $pathFactory,
FailureMarker $failureMarker, FailureMarker $failureMarker,
) { ) {
parent::__construct($pathLocator, $beginner, $stager, $committer, $fileSystem, $eventDispatcher, $tempStoreFactory, $time, $pathFactory, $failureMarker); parent::__construct($pathLocator, $beginner, $stager, $committer, $queueFactory, $eventDispatcher, $tempStoreFactory, $time, $pathFactory, $failureMarker);
} }
/** /**
......
...@@ -7,6 +7,7 @@ namespace Drupal\automatic_updates_extensions\Form; ...@@ -7,6 +7,7 @@ namespace Drupal\automatic_updates_extensions\Form;
use Drupal\automatic_updates\Form\UpdateFormBase; use Drupal\automatic_updates\Form\UpdateFormBase;
use Drupal\package_manager\ComposerInspector; use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\Exception\StageFailureMarkerException; use Drupal\package_manager\Exception\StageFailureMarkerException;
use Drupal\package_manager\InstalledPackage;
use Drupal\package_manager\PathLocator; use Drupal\package_manager\PathLocator;
use Drupal\package_manager\ProjectInfo; use Drupal\package_manager\ProjectInfo;
use Drupal\package_manager\ValidationResult; use Drupal\package_manager\ValidationResult;
...@@ -30,7 +31,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; ...@@ -30,7 +31,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
* Defines a form to commit staged updates. * Defines a form to commit staged updates.
* *
* @internal * @internal
* Form classes are internal. * Form classes are internal and should not be used by external code.
*/ */
final class UpdateReady extends UpdateFormBase { final class UpdateReady extends UpdateFormBase {
...@@ -79,14 +80,14 @@ final class UpdateReady extends UpdateFormBase { ...@@ -79,14 +80,14 @@ final class UpdateReady extends UpdateFormBase {
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
$container->get('automatic_updates_extensions.update_stage'), $container->get(ExtensionUpdateStage::class),
$container->get('messenger'), $container->get('messenger'),
$container->get('state'), $container->get('state'),
$container->get('extension.list.module'), $container->get('extension.list.module'),
$container->get('renderer'), $container->get('renderer'),
$container->get('event_dispatcher'), $container->get('event_dispatcher'),
$container->get('package_manager.composer_inspector'), $container->get(ComposerInspector::class),
$container->get('package_manager.path_locator') $container->get(PathLocator::class),
); );
} }
...@@ -133,7 +134,11 @@ final class UpdateReady extends UpdateFormBase { ...@@ -133,7 +134,11 @@ final class UpdateReady extends UpdateFormBase {
$form['package_updates'] = $this->showUpdates(); $form['package_updates'] = $this->showUpdates();
$form['backup'] = [ $form['backup'] = [
'#prefix' => '<strong>', '#prefix' => '<strong>',
'#markup' => $this->t('Back up your database and site before you continue. <a href=":backup_url">Learn how</a>.', [':backup_url' => 'https://www.drupal.org/node/22281']), '#type' => 'checkbox',
'#title' => $this->t('Warning: Updating contributed modules or themes may leave your site inoperable or looking wrong.'),
'#description' => $this->t('Back up your database and site before you continue. <a href=":backup_url">Learn how</a>. Each contributed module or theme may follow different standards for backwards compatibility, may or may not have tests, and may add or remove features in any release. For these reasons, it is highly recommended that you test this update in a development environment first.', [':backup_url' => 'https://www.drupal.org/node/22281']),
'#required' => TRUE,
'#default_value' => FALSE,
'#suffix' => '</strong>', '#suffix' => '</strong>',
]; ];
$form['maintenance_mode'] = [ $form['maintenance_mode'] = [
...@@ -230,7 +235,7 @@ final class UpdateReady extends UpdateFormBase { ...@@ -230,7 +235,7 @@ final class UpdateReady extends UpdateFormBase {
continue; continue;
} }
$updated_project_info[$name] = [ $updated_project_info[$name] = [
'title' => $this->getProjectTitle($updated_package->name), 'title' => $this->getProjectTitleFromPackage($updated_package),
'installed_version' => $installed_packages[$updated_package->name]->version, 'installed_version' => $installed_packages[$updated_package->name]->version,
'updated_version' => $updated_package->version, 'updated_version' => $updated_package->version,
]; ];
...@@ -262,21 +267,25 @@ final class UpdateReady extends UpdateFormBase { ...@@ -262,21 +267,25 @@ final class UpdateReady extends UpdateFormBase {
/** /**
* Gets the human-readable project title for a Composer package. * Gets the human-readable project title for a Composer package.
* *
* @param string $package_name * @param \Drupal\package_manager\InstalledPackage $package
* Package name. * The installed package.
* *
* @return string * @return string
* The human-readable title of the project. * The human-readable title of the project. If no project information is
* available, the package name is returned.
*/ */
private function getProjectTitle(string $package_name): string { private function getProjectTitleFromPackage(InstalledPackage $package): string {
$project_name = str_replace('drupal/', '', $package_name); $project_name = $package->getProjectName();
if (!$project_name) {
return $package->name;
}
$project_info = new ProjectInfo($project_name); $project_info = new ProjectInfo($project_name);
$project_data = $project_info->getProjectInfo(); $project_data = $project_info->getProjectInfo();
if ($project_data) { if ($project_data) {
return $project_data['title']; return $project_data['title'];
} }
else { else {
return $project_name; return $package->name;
} }
} }
......
...@@ -20,6 +20,7 @@ use Drupal\package_manager\PathLocator; ...@@ -20,6 +20,7 @@ use Drupal\package_manager\PathLocator;
use Drupal\package_manager\ProjectInfo; use Drupal\package_manager\ProjectInfo;
use Drupal\package_manager\ValidationResult; use Drupal\package_manager\ValidationResult;
use Drupal\system\SystemManager; use Drupal\system\SystemManager;
use Drupal\update\ProjectRelease;
use Drupal\update\UpdateManagerInterface; use Drupal\update\UpdateManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
...@@ -28,7 +29,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; ...@@ -28,7 +29,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
* A form for selecting extension updates. * A form for selecting extension updates.
* *
* @internal * @internal
* Form classes are internal. * Form classes are internal and should not be used by external code.
*/ */
final class UpdaterForm extends UpdateFormBase { final class UpdaterForm extends UpdateFormBase {
...@@ -37,13 +38,13 @@ final class UpdaterForm extends UpdateFormBase { ...@@ -37,13 +38,13 @@ final class UpdaterForm extends UpdateFormBase {
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
$container->get('automatic_updates_extensions.update_stage'), $container->get(ExtensionUpdateStage::class),
$container->get('event_dispatcher'), $container->get('event_dispatcher'),
$container->get('renderer'), $container->get('renderer'),
$container->get('state'), $container->get('state'),
$container->get('package_manager.failure_marker'), $container->get(FailureMarker::class),
$container->get('package_manager.composer_inspector'), $container->get(ComposerInspector::class),
$container->get('package_manager.path_locator') $container->get(PathLocator::class),
); );
} }
...@@ -110,10 +111,16 @@ final class UpdaterForm extends UpdateFormBase { ...@@ -110,10 +111,16 @@ final class UpdaterForm extends UpdateFormBase {
default: default:
$status_message = ''; $status_message = '';
} }
$project_release = ProjectRelease::createFromArray($update_project['releases'][$update_project['recommended']]);
$options[$project_name] = [ $options[$project_name] = [
$update_project['title'] . $status_message, $update_project['title'] . $status_message,
$update_project['existing_version'], $update_project['existing_version'],
$update_project['recommended'], $this->t(
'@version (<a href=":url">Release notes</a>)',
[
'@version' => $project_release->getVersion(),
':url' => $project_release->getReleaseUrl(),
]),
]; ];
$recommended_versions[$project_name] = $update_project['recommended']; $recommended_versions[$project_name] = $update_project['recommended'];
} }
...@@ -236,13 +243,12 @@ final class UpdaterForm extends UpdateFormBase { ...@@ -236,13 +243,12 @@ final class UpdaterForm extends UpdateFormBase {
$all_projects_data = update_calculate_project_data($available_updates); $all_projects_data = update_calculate_project_data($available_updates);
$outdated_modules = []; $outdated_modules = [];
$installed_packages = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot()) $installed_packages = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot());
->getArrayCopy();
$non_supported_update_statuses = []; $non_supported_update_statuses = [];
foreach ($all_projects_data as $project_name => $project_data) { foreach ($all_projects_data as $project_name => $project_data) {
if (in_array($project_data['project_type'], $supported_project_types, TRUE)) { if (in_array($project_data['project_type'], $supported_project_types, TRUE)) {
if ($project_data['status'] !== UpdateManagerInterface::CURRENT) { if ($project_data['status'] !== UpdateManagerInterface::CURRENT) {
if (!array_key_exists("drupal/$project_name", $installed_packages)) { if ($installed_packages->getPackageByDrupalProjectName($project_name) === NULL) {
$non_supported_update_statuses[] = $project_data['status']; $non_supported_update_statuses[] = $project_data['status'];
continue; continue;
} }
......
<?php
declare(strict_types=1);
namespace Drupal\automatic_updates_extensions\Validator;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\Event\PreApplyEvent;
use Drupal\package_manager\Event\StatusCheckEvent;
use Drupal\package_manager\InstalledPackagesList;
use Drupal\package_manager\PathLocator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Validates that no changes were made to Drupal Core packages.
*
* @internal
* This is an internal part of Automatic Updates and may be changed or removed
* at any time without warning. External code should not interact with this
* class.
*/
final class ForbidCoreChangesValidator implements EventSubscriberInterface {
use StringTranslationTrait;
public function __construct(
private readonly PathLocator $pathLocator,
private readonly ComposerInspector $composerInspector,
) {}
/**
* Validates the staged packages.
*
* @param \Drupal\package_manager\Event\StatusCheckEvent|\Drupal\package_manager\Event\PreApplyEvent $event
* The event object.
*/
public function validateStagedCorePackages(StatusCheckEvent|PreApplyEvent $event): void {
$stage = $event->stage;
// We only want to do this check if the stage belongs to Automatic Updates
// Extensions.
if ($stage->getType() !== 'automatic_updates_extensions:attended' || !$stage->stageDirectoryExists()) {
return;
}
$active_core_packages = $this->getInstalledCorePackages($this->pathLocator->getProjectRoot());
$stage_core_packages = $this->getInstalledCorePackages($stage->getStageDirectory());
$new_packages = $stage_core_packages->getPackagesNotIn($active_core_packages);
$removed_packages = $active_core_packages->getPackagesNotIn($stage_core_packages);
$changed_packages = $active_core_packages->getPackagesWithDifferentVersionsIn($stage_core_packages);
$error_messages = [];
foreach ($new_packages as $new_package) {
$error_messages[] = $this->t("'@name' installed.", ['@name' => $new_package->name]);
}
foreach ($removed_packages as $removed_package) {
$error_messages[] = $this->t("'@name' removed.", ['@name' => $removed_package->name]);
}
foreach ($changed_packages as $name => $updated_package) {
$error_messages[] = $this->t(
"'@name' version changed from @active_version to @staged_version.",
[
'@name' => $updated_package->name,
'@staged_version' => $stage_core_packages[$name]->version,
'@active_version' => $updated_package->version,
]
);
}
if ($error_messages) {
$event->addError($error_messages, $this->t(
'Updating Drupal Core while updating extensions is currently not supported. Use <a href=":url">this form</a> to update Drupal core. The following changes were made to the Drupal core packages:',
[':url' => Url::fromRoute('update.report_update')->toString()]
));
}
}
/**
* Gets all the installed core packages for a given project root.
*
* This method differs from
* \Drupal\package_manager\ComposerInspector::getInstalledPackagesList in that
* it ensures that the 'drupal/core' is included in the list if present.
*
* @param string $composer_root
* The path to the composer root.
*
* @return \Drupal\package_manager\InstalledPackagesList
* The installed core packages.
*/
private function getInstalledCorePackages(string $composer_root): InstalledPackagesList {
$installed_package_list = $this->composerInspector->getInstalledPackagesList($composer_root);
$core_packages = $installed_package_list->getCorePackages();
if (isset($installed_package_list['drupal/core']) && !isset($core_packages['drupal/core'])) {
$core_packages = new InstalledPackagesList(array_merge($core_packages->getArrayCopy(), ['drupal/core' => $installed_package_list['drupal/core']]));
}
return $core_packages;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
$events[StatusCheckEvent::class][] = ['validateStagedCorePackages'];
$events[PreApplyEvent::class][] = ['validateStagedCorePackages'];
return $events;
}
}
<?php
declare(strict_types=1);
namespace Drupal\automatic_updates_extensions\Validator;
use Composer\Semver\Semver;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\Event\PreApplyEvent;
use Drupal\package_manager\Event\StatusCheckEvent;
use Drupal\package_manager\PathLocator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Validates that requested packages have been updated.
*
* @internal
* This is an internal part of Automatic Updates and may be changed or removed
* at any time without warning. External code should not interact with this
* class.
*/
final class RequestedUpdateValidator implements EventSubscriberInterface {
use StringTranslationTrait;
/**
* Constructs a RequestedUpdateValidator object.
*
* @param \Drupal\package_manager\ComposerInspector $composerInspector
* The Composer inspector service.
* @param \Drupal\package_manager\PathLocator $pathLocator
* The path locator service.
*/
public function __construct(
private readonly ComposerInspector $composerInspector,
private readonly PathLocator $pathLocator,
) {}
/**
* Validates that requested packages have been updated to the right version.
*
* @param \Drupal\package_manager\Event\PreApplyEvent|\Drupal\package_manager\Event\StatusCheckEvent $event
* The pre-apply event.
*/
public function checkRequestedStagedVersion(PreApplyEvent|StatusCheckEvent $event): void {
$stage = $event->stage;
if ($stage->getType() !== 'automatic_updates_extensions:attended' || !$stage->stageDirectoryExists()) {
return;
}
$requested_package_versions = $stage->getPackageVersions();
$active = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot());
$staged = $this->composerInspector->getInstalledPackagesList($event->stage->getStageDirectory());
$changed_stage_packages = $staged->getPackagesWithDifferentVersionsIn($active)->getArrayCopy();
if (empty($changed_stage_packages)) {
$event->addError([$this->t('No updates detected in the staging area.')]);
return;
}
// Check for all changed the packages if they are updated to the requested
// version.
foreach (['production', 'dev'] as $package_type) {
foreach ($requested_package_versions[$package_type] as $requested_package_name => $requested_version) {
if (array_key_exists($requested_package_name, $changed_stage_packages)) {
$staged_version = $changed_stage_packages[$requested_package_name]->version;
if (!Semver::satisfies($staged_version, $requested_version)) {
$event->addError([
$this->t(
"The requested update to '@requested_package_name' to version '@requested_version' does not match the actual staged update to '@staged_version'.",
[
'@requested_package_name' => $requested_package_name,
'@requested_version' => $requested_version,
'@staged_version' => $staged_version,
]
),
]);
}
}
else {
$event->addError([
$this->t(
"The requested update to '@requested_package_name' to version '@requested_version' was not performed.",
[
'@requested_package_name' => $requested_package_name,
'@requested_version' => $requested_version,
]
),
]);
}
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
$events[StatusCheckEvent::class][] = ['checkRequestedStagedVersion'];
$events[PreApplyEvent::class][] = ['checkRequestedStagedVersion'];
return $events;
}
}
...@@ -7,7 +7,6 @@ namespace Drupal\automatic_updates_extensions\Validator; ...@@ -7,7 +7,6 @@ namespace Drupal\automatic_updates_extensions\Validator;
use Drupal\package_manager\ComposerInspector; use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\PathLocator; use Drupal\package_manager\PathLocator;
use Drupal\package_manager\ProjectInfo; use Drupal\package_manager\ProjectInfo;
use Drupal\automatic_updates_extensions\ExtensionUpdateStage;
use Drupal\package_manager\LegacyVersionUtility; use Drupal\package_manager\LegacyVersionUtility;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\package_manager\Event\PreCreateEvent; use Drupal\package_manager\Event\PreCreateEvent;
...@@ -89,7 +88,7 @@ final class UpdateReleaseValidator implements EventSubscriberInterface { ...@@ -89,7 +88,7 @@ final class UpdateReleaseValidator implements EventSubscriberInterface {
public function checkRelease(PreCreateEvent $event): void { public function checkRelease(PreCreateEvent $event): void {
$stage = $event->stage; $stage = $event->stage;
// This check only works with Automatic Updates Extensions. // This check only works with Automatic Updates Extensions.
if (!$stage instanceof ExtensionUpdateStage) { if ($stage->getType() !== 'automatic_updates_extensions:attended') {
return; return;
} }
......
...@@ -35,7 +35,7 @@ Contains metadata about the following (fake) releases of automatic_updates_exten ...@@ -35,7 +35,7 @@ Contains metadata about the following (fake) releases of automatic_updates_exten
<version>3.0.0</version> <version>3.0.0</version>
<tag>3.0.0</tag> <tag>3.0.0</tag>
<status>published</status> <status>published</status>
<release_link>http://example.com/automatic_updates_extensions_test_theme/releases/3.0.0</release_link> <release_link>http://example.com/automatic_updates_extensions_test_theme-3-0-0-release</release_link>
<download_link>http://example.com/automatic_updates_extensions_test_theme-3.0.0.tar.gz</download_link> <download_link>http://example.com/automatic_updates_extensions_test_theme-3.0.0.tar.gz</download_link>
<date>1597793786</date> <date>1597793786</date>
<files> <files>
...@@ -62,7 +62,7 @@ Contains metadata about the following (fake) releases of automatic_updates_exten ...@@ -62,7 +62,7 @@ Contains metadata about the following (fake) releases of automatic_updates_exten
<version>8.x-2.1</version> <version>8.x-2.1</version>
<tag>8.x-2.1</tag> <tag>8.x-2.1</tag>
<status>published</status> <status>published</status>
<release_link>http://example.com/automatic_updates_extensions_test_theme/releases/8.x-2.1</release_link> <release_link>http://example.com/automatic_updates_extensions_test_theme-8-x-2-1-release</release_link>
<download_link>http://example.com/automatic_updates_extensions_test_theme-8.x-2.1.tar.gz</download_link> <download_link>http://example.com/automatic_updates_extensions_test_theme-8.x-2.1.tar.gz</download_link>
<date>1597793786</date> <date>1597793786</date>
<files> <files>
...@@ -95,7 +95,7 @@ Contains metadata about the following (fake) releases of automatic_updates_exten ...@@ -95,7 +95,7 @@ Contains metadata about the following (fake) releases of automatic_updates_exten
<version>8.x-2.0</version> <version>8.x-2.0</version>
<tag>8.x-2.0</tag> <tag>8.x-2.0</tag>
<status>published</status> <status>published</status>
<release_link>http://example.com/automatic_updates_extensions_test_theme/releases/8.x-2.0</release_link> <release_link>http://example.com/automatic_updates_extensions_test_theme-8-x-2-0-release</release_link>
<download_link>http://example.com/automatic_updates_extensions_test_theme-8.x-2.0.tar.gz</download_link> <download_link>http://example.com/automatic_updates_extensions_test_theme-8.x-2.0.tar.gz</download_link>
<date>1597793786</date> <date>1597793786</date>
<files> <files>
......
...@@ -4,6 +4,8 @@ declare(strict_types = 1); ...@@ -4,6 +4,8 @@ declare(strict_types = 1);
namespace Drupal\automatic_updates_extensions_test_api; namespace Drupal\automatic_updates_extensions_test_api;
use Drupal\automatic_updates_extensions\ExtensionUpdateStage;
use Drupal\package_manager\PathLocator;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Drupal\package_manager_test_api\ApiController as PackageManagerApiController; use Drupal\package_manager_test_api\ApiController as PackageManagerApiController;
...@@ -23,8 +25,8 @@ class ApiController extends PackageManagerApiController { ...@@ -23,8 +25,8 @@ class ApiController extends PackageManagerApiController {
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
$container->get('automatic_updates_extensions.update_stage'), $container->get(ExtensionUpdateStage::class),
$container->get('package_manager.path_locator') $container->get(PathLocator::class),
); );
} }
......
...@@ -14,7 +14,7 @@ use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem; ...@@ -14,7 +14,7 @@ use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
* @group automatic_updates_extensions * @group automatic_updates_extensions
* @internal * @internal
*/ */
class ModuleUpdateTest extends UpdateTestBase { final class ModuleUpdateTest extends UpdateTestBase {
use FormTestTrait; use FormTestTrait;
...@@ -42,7 +42,7 @@ END; ...@@ -42,7 +42,7 @@ END;
$this->writeSettings($code); $this->writeSettings($code);
$alpha_repo_path = $this->copyFixtureToTempDirectory(__DIR__ . '/../../../../package_manager/tests/fixtures/build_test_projects/alpha/1.0.0'); $alpha_repo_path = $this->copyFixtureToTempDirectory(__DIR__ . '/../../../../package_manager/tests/fixtures/build_test_projects/alpha/1.0.0');
$this->addRepository('alpha', $alpha_repo_path); $this->addRepository('alpha', $alpha_repo_path);
$this->runComposer('COMPOSER_MIRROR_PATH_REPOS=1 composer require drupal/alpha --update-with-all-dependencies', 'project'); $this->runComposer('composer require drupal/alpha --update-with-all-dependencies', 'project');
$this->assertModuleVersion('alpha', '1.0.0'); $this->assertModuleVersion('alpha', '1.0.0');
$fs = new SymfonyFilesystem(); $fs = new SymfonyFilesystem();
$fs->mirror($this->copyFixtureToTempDirectory(__DIR__ . '/../../fixtures/new_module'), $this->getWorkspaceDirectory() . '/project/web/modules'); $fs->mirror($this->copyFixtureToTempDirectory(__DIR__ . '/../../fixtures/new_module'), $this->getWorkspaceDirectory() . '/project/web/modules');
...@@ -54,6 +54,11 @@ END; ...@@ -54,6 +54,11 @@ END;
// Change the module's upstream version. // Change the module's upstream version.
static::copyFixtureFilesTo(__DIR__ . '/../../../../package_manager/tests/fixtures/build_test_projects/alpha/1.1.0', $alpha_repo_path); static::copyFixtureFilesTo(__DIR__ . '/../../../../package_manager/tests/fixtures/build_test_projects/alpha/1.1.0', $alpha_repo_path);
// Ensure that none of the above changes have caused any status check or
// other errors on the status report.
$this->checkForUpdates();
$this->assertStatusReportChecksSuccessful();
} }
/** /**
...@@ -76,24 +81,22 @@ END; ...@@ -76,24 +81,22 @@ END;
$this->assertStringContainsString('The project new_module is not a Drupal project known to Composer and cannot be updated.', $page_text); $this->assertStringContainsString('The project new_module is not a Drupal project known to Composer and cannot be updated.', $page_text);
$this->assertStringContainsString('new_module', $page_text); $this->assertStringContainsString('new_module', $page_text);
// Use the API endpoint to create a stage and update the 'alpha' module to // Use the API endpoint to create a stage and update the 'alpha' module to
// 1.1.0. We ask the API to return the contents of the module's // 1.1.0.
// composer.json file, so we can assert that they were updated to the $this->makePackageManagerTestApiRequest(
// version we expect.
// @see \Drupal\automatic_updates_extensions_test_api\ApiController::run()
$file_contents = $this->getPackageManagerTestApiResponse(
'/automatic-updates-extensions-test-api', '/automatic-updates-extensions-test-api',
[ [
'projects' => [ 'projects' => [
'alpha' => '1.1.0', 'alpha' => '1.1.0',
], ],
'files_to_return' => [
'web/modules/contrib/alpha/composer.json',
],
] ]
); );
$module_composer_json = json_decode($file_contents['web/modules/contrib/alpha/composer.json']); $updated_composer_json = $this->getWebRoot() . 'modules/contrib/alpha/composer.json';
$this->assertSame('1.1.0', $module_composer_json?->version); // Assert the module was updated.
$this->assertFileEquals(
__DIR__ . '/../../../../package_manager/tests/fixtures/build_test_projects/alpha/1.1.0/composer.json',
$updated_composer_json,
);
$this->assertRequestedChangesWereLogged(['Update drupal/alpha from 1.0.0 to 1.1.0']); $this->assertRequestedChangesWereLogged(['Update drupal/alpha from 1.0.0 to 1.1.0']);
$this->assertAppliedChangesWereLogged(['Updated drupal/alpha from 1.0.0 to 1.1.0']); $this->assertAppliedChangesWereLogged(['Updated drupal/alpha from 1.0.0 to 1.1.0']);
} }
...@@ -129,6 +132,7 @@ END; ...@@ -129,6 +132,7 @@ END;
$page->pressButton('Update'); $page->pressButton('Update');
$this->waitForBatchJob(); $this->waitForBatchJob();
$assert_session->pageTextContains('Ready to update'); $assert_session->pageTextContains('Ready to update');
$page->checkField('backup');
$page->pressButton('Continue'); $page->pressButton('Continue');
$this->waitForBatchJob(); $this->waitForBatchJob();
$assert_session->pageTextContains('Update complete!'); $assert_session->pageTextContains('Update complete!');
......
<?php
declare(strict_types=1);
namespace Drupal\Tests\automatic_updates_extensions\Functional;
use Drupal\package_manager_bypass\LoggingBeginner;
use Drupal\package_manager_bypass\LoggingCommitter;
use Drupal\package_manager_bypass\NoOpStager;
use PhpTuf\ComposerStager\API\Exception\InvalidArgumentException;
use PhpTuf\ComposerStager\API\Exception\LogicException;
/**
* @covers \Drupal\automatic_updates_extensions\Form\UpdaterForm
* @group automatic_updates_extensions
* @internal
*/
class ComposerStagerOperationFailureTest extends UpdaterFormTestBase {
/**
* Tests Composer operation failure is handled properly.
*
* @param string $exception_class
* The exception class.
* @param string $service_class
* The Composer Stager service which should throw an exception.
*
* @dataProvider providerComposerOperationFailure
*/
public function testComposerOperationFailure(string $exception_class, string $service_class): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->setReleaseMetadata(__DIR__ . '/../../../../package_manager/tests/fixtures/release-history/drupal.9.8.2.xml');
$this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/semver_test.1.1.xml');
$this->setProjectInstalledVersion(['semver_test' => '8.1.0']);
$this->checkForUpdates();
// Navigate to the update form.
$this->drupalGet('/admin/reports/updates');
$this->clickLink('Update Extensions');
$this->assertTableShowsUpdates(
'Semver Test',
'8.1.0',
'8.1.1',
);
$this->getStageFixtureManipulator()->setVersion('drupal/semver_test_package_name', '8.1.1');
$this->assertUpdatesCount(1);
$page->checkField('projects[semver_test]');
// Make the specified Composer Stager operation class throw an exception.
$message = $this->createComposeStagerMessage("Failure from inside $service_class");
$exception = new $exception_class($message);
call_user_func([$service_class, 'setException'], $exception);
// Start the update.
$page->pressButton('Update');
$this->checkForMetaRefresh();
// We can't continue the update after an error in the committer.
if ($service_class === LoggingCommitter::class) {
$this->acceptWarningAndUpdate();
$this->clickLink('the error page');
$assert_session->statusCodeEquals(200);
$assert_session->statusMessageContains('Automatic updates failed to apply, and the site is in an indeterminate state. Consider restoring the code and database from a backup.');
return;
}
$this->clickLink('the error page');
$assert_session->statusMessageContains($exception->getMessage());
// Make the same Composer Stager operation class NOT throw an exception.
call_user_func([$service_class, 'setException'], NULL);
// Stage should be automatically deleted when an error occurs.
$assert_session->buttonNotExists('Delete existing update');
// This ensures that we can still update after the exception no longer
// exists.
$page->checkField('projects[semver_test]');
$this->getStageFixtureManipulator()->setVersion('drupal/semver_test_package_name', '8.1.1');
$page->pressButton('Update');
$this->checkForMetaRefresh();
$this->acceptWarningAndUpdate();
$assert_session->statusMessageContains('Update complete!');
}
/**
* Data provider for testComposerOperationFailure().
*
* @return string[][]
* The test cases.
*/
public function providerComposerOperationFailure(): array {
return [
'LogicException from Beginner' => [LogicException::class, LoggingBeginner::class],
'LogicException from Stager' => [LogicException::class, NoOpStager::class],
'InvalidArgumentException from Stager' => [InvalidArgumentException::class, NoOpStager::class],
'LogicException from Committer' => [LogicException::class, LoggingCommitter::class],
];
}
}
...@@ -9,7 +9,7 @@ namespace Drupal\Tests\automatic_updates_extensions\Functional; ...@@ -9,7 +9,7 @@ namespace Drupal\Tests\automatic_updates_extensions\Functional;
* @group automatic_updates_extensions * @group automatic_updates_extensions
* @internal * @internal
*/ */
class DisplayUpdatesTest extends UpdaterFormTestBase { final class DisplayUpdatesTest extends UpdaterFormTestBase {
/** /**
* Data provider for testDisplayUpdates(). * Data provider for testDisplayUpdates().
...@@ -67,7 +67,7 @@ class DisplayUpdatesTest extends UpdaterFormTestBase { ...@@ -67,7 +67,7 @@ class DisplayUpdatesTest extends UpdaterFormTestBase {
$page->checkField('projects[semver_test]'); $page->checkField('projects[semver_test]');
$this->getStageFixtureManipulator() $this->getStageFixtureManipulator()
->setVersion('drupal/aaa_update_test', '2.1.0') ->setVersion('drupal/aaa_update_test', '2.1.0')
->setVersion('drupal/semver_test', '8.1.1'); ->setVersion('drupal/semver_test_package_name', '8.1.1');
$page->pressButton('Update'); $page->pressButton('Update');
$this->checkForMetaRefresh(); $this->checkForMetaRefresh();
$this->assertUpdateStagedTimes(1); $this->assertUpdateStagedTimes(1);
......