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 (47)
Showing
with 374 additions and 300 deletions
/dictionary.txt export-ignore
/scripts export-ignore
......@@ -5,7 +5,7 @@
* Contains install and update functions for Automatic Updates.
*/
use Drupal\automatic_updates\Validation\ReadinessRequirements;
use Drupal\automatic_updates\Validation\StatusCheckRequirements;
/**
* Implements hook_uninstall().
......@@ -20,8 +20,19 @@ function automatic_updates_uninstall() {
function automatic_updates_requirements($phase) {
if ($phase === 'runtime') {
// Check that site is ready to perform automatic updates.
/** @var \Drupal\automatic_updates\Validation\ReadinessRequirements $readiness_requirement */
$readiness_requirement = \Drupal::classResolver(ReadinessRequirements::class);
return $readiness_requirement->getRequirements();
/** @var \Drupal\automatic_updates\Validation\StatusCheckRequirements $status_check_requirement */
$status_check_requirement = \Drupal::classResolver(StatusCheckRequirements::class);
return $status_check_requirement->getRequirements();
}
}
/**
* Stores cached readiness check results under a new key.
*/
function automatic_updates_update_9001(): void {
/** @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $key_value */
$key_value = \Drupal::service('keyvalue.expirable')
->get('automatic_updates');
$key_value->rename('readiness_validation_last_run', 'status_check_last_run');
$key_value->rename('readiness_check_timestamp', 'status_check_timestamp');
}
......@@ -6,30 +6,44 @@
*/
use Drupal\automatic_updates\BatchProcessor;
use Drupal\automatic_updates\CronUpdater;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\automatic_updates\Validation\AdminReadinessMessages;
use Drupal\Core\Form\FormStateInterface;
use Drupal\automatic_updates\Validation\AdminStatusCheckMessages;
use Drupal\Core\Url;
use Drupal\system\Controller\DbUpdateController;
use Drupal\package_manager\Validator\ComposerExecutableValidator;
/**
* Implements hook_help().
*/
function automatic_updates_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.auto_updates':
case 'help.page.automatic_updates':
$output = '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Automatic Updates lets you update Drupal core.') . '</p>';
$output .= '<p>';
$output .= t('Automatic Updates will keep Drupal secure and up-to-date by automatically installing new patch-level updates, if available, when cron runs. It also provides a user interface to check if any updates are available and install them. You can <a href=":configure-form">configure Automatic Updates</a> to install all patch-level updates, only security updates, or no updates at all, during cron. By default, only security updates are installed during cron; this requires that you <a href=":update-form">install non-security updates through the user interface</a>.', [
':configure-form' => Url::fromRoute('update.settings')->toString(),
':update-form' => Url::fromRoute('automatic_updates.report_update')->toString(),
':update-form' => Url::fromRoute('update.report_update')->toString(),
]);
$output .= '</p>';
$output .= '<p>' . t('Additionally, Automatic Updates periodically runs checks to ensure that updates can be installed, and will warn site administrators if problems are detected.') . '</p>';
$output .= '<h3>' . t('Requirements') . '</h3>';
$output .= '<p>' . t('Automatic Updates requires a Composer executable whose version satisfies <code>@version</code>, and PHP must have permission to run it. The path to the executable may be set in the <code>package_manager.settings:executables.composer</code> config setting, or it will be automatically detected.', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION_CONSTRAINT]) . '</p>';
$output .= '<p id="cron-alternate-port">' . t('If your site is running on the built-in PHP web server, unattended (i.e., cron) updates may not work without one of the following workarounds:') . '</p>';
$output .= '<ul>';
$output .= '<li>' . t('Use a multithreaded web server, such as Apache, NGINX, or on Windows, IIS.') . '</li>';
$output .= '<li>' . t('Run another instance of the built-in PHP web server on a different port and configure automatic updates accordingly: <code>$config["automatic_updates.settings"]["cron_port"] = $alternate_port_number;</code>') . '</li>';
$output .= '</ul>';
$output .= '<p>' . t('For more information, see the <a href=":automatic-updates-documentation">online documentation for the Automatic Updates module</a>.', [':automatic-updates-documentation' => 'https://www.drupal.org/docs/8/update/automatic-updates']) . '</p>';
$output .= '<h3 id="minor-update">' . t('Updating to another minor version of Drupal') . '</h3>';
$output .= '<p>';
$output .= t('Automatic Updates supports updating from one minor version of Drupal core to another; for example, from Drupal 9.4.8 to Drupal 9.5.0. This is only allowed when updating via <a href=":url">the user interface</a>. Unattended background updates can only update <em>within</em> the currently installed minor version (for example, Drupal 9.4.6 to 9.4.8).', [
':url' => Url::fromRoute('update.report_update')->toString(),
]);
$output .= '</p>';
$output .= '<p>' . t('This is because updating from one minor version of Drupal to another is riskier than staying within the current minor version. New minor versions of Drupal introduce changes that can, in some situations, be incompatible with installed modules and themes.') . '</p>';
$output .= '<p>' . t('Therefore, if you want to use Automatic Updates to update to another minor version of Drupal, it is strongly recommended to do a test update first, ideally on an isolated development copy of your site, before updating your production site.') . '</p>';
return $output;
}
}
......@@ -42,24 +56,55 @@ function automatic_updates_mail(string $key, array &$message, array $params): vo
$options = [
'langcode' => $message['langcode'],
];
switch ($key) {
case 'cron_successful':
$message['subject'] = t("Drupal core was successfully updated", [], $options);
$message['body'][] = t('Congratulations!', [], $options);
$message['body'][] = t('Drupal core was automatically updated from @previous_version to @updated_version.', [
'@previous_version' => $params['previous_version'],
'@updated_version' => $params['updated_version'],
], $options);
break;
if ($key === 'cron_successful') {
$message['subject'] = t("Drupal core was successfully updated", [], $options);
$message['body'][] = t('Congratulations!', [], $options);
$message['body'][] = t('Drupal core was automatically updated from @previous_version to @updated_version.', [
'@previous_version' => $params['previous_version'],
'@updated_version' => $params['updated_version'],
], $options);
}
elseif (str_starts_with($key, 'cron_failed')) {
$message['subject'] = t("Drupal core update failed", [], $options);
case 'cron_failed':
$message['subject'] = t("Drupal core update failed", [], $options);
$message['body'][] = t('Drupal core failed to update automatically from @previous_version to @target_version. The following error was logged:', [
'@previous_version' => $params['previous_version'],
'@target_version' => $params['target_version'],
// If this is considered urgent, prefix the subject line with a call to
// action.
if ($params['urgent']) {
$message['subject'] = t('URGENT: @subject', [
'@subject' => $message['subject'],
], $options);
$message['body'][] = $params['error_message'];
break;
}
$message['body'][] = t('Drupal core failed to update automatically from @previous_version to @target_version. The following error was logged:', [
'@previous_version' => $params['previous_version'],
'@target_version' => $params['target_version'],
], $options);
$message['body'][] = $params['error_message'];
// If the problem was not due to a failed apply, provide a link for the site
// owner to do the update.
if ($key !== 'cron_failed_apply') {
$url = Url::fromRoute('update.report_update')
->setAbsolute()
->toString();
if ($key === 'cron_failed_insecure') {
$message['body'][] = t('Your site is running an insecure version of Drupal and should be updated as soon as possible. Visit @url to perform the update.', ['@url' => $url], $options);
}
else {
$message['body'][] = t('No immediate action is needed, but it is recommended that you visit @url to perform the update, or at least check that everything still looks good.', ['@url' => $url], $options);
}
}
}
elseif ($key === 'status_check_failed') {
$message['subject'] = t('Automatic updates readiness checks failed', [], $options);
$url = Url::fromRoute('system.status')
->setAbsolute()
->toString();
$message['body'][] = t('Your site has failed some readiness checks for automatic updates and may not be able to receive automatic updates until further action is taken. Please visit @url for more information.', [
'@url' => $url,
], $options);
}
// If this email was related to an unattended update, explicitly state that
......@@ -74,9 +119,9 @@ function automatic_updates_mail(string $key, array &$message, array $params): vo
* Implements hook_page_top().
*/
function automatic_updates_page_top() {
/** @var \Drupal\automatic_updates\Validation\AdminReadinessMessages $readiness_messages */
$readiness_messages = \Drupal::classResolver(AdminReadinessMessages::class);
$readiness_messages->displayAdminPageMessages();
/** @var \Drupal\automatic_updates\Validation\AdminStatusCheckMessages $status_check_messages */
$status_check_messages = \Drupal::classResolver(AdminStatusCheckMessages::class);
$status_check_messages->displayAdminPageMessages();
// @todo Rely on the route option after https://www.drupal.org/i/3236497 is
// committed.
......@@ -109,7 +154,6 @@ function automatic_updates_module_implements_alter(&$implementations, $hook) {
unset($implementations['update']);
}
if ($hook === 'cron') {
// Whatever mofo.
$hook = $implementations['automatic_updates'];
unset($implementations['automatic_updates']);
$implementations['automatic_updates'] = $hook;
......@@ -120,85 +164,47 @@ function automatic_updates_module_implements_alter(&$implementations, $hook) {
* Implements hook_cron().
*/
function automatic_updates_cron() {
\Drupal::service('automatic_updates.cron_updater')->handleCron();
/** @var \Drupal\automatic_updates\CronUpdater $updater */
$updater = \Drupal::service('automatic_updates.cron_updater');
$updater->handleCron();
/** @var \Drupal\automatic_updates\Validation\ReadinessValidationManager $checker_manager */
$checker_manager = \Drupal::service('automatic_updates.readiness_validation_manager');
$last_results = $checker_manager->getResults();
$last_run_time = $checker_manager->getLastRunTime();
// Do not run readiness checks more than once an hour unless there are no
// results available.
/** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */
$status_checker = \Drupal::service('automatic_updates.status_checker');
$last_results = $status_checker->getResults();
$last_run_time = $status_checker->getLastRunTime();
// Do not run status checks more than once an hour unless there are no results
// available.
if ($last_results === NULL || !$last_run_time || \Drupal::time()->getRequestTime() - $last_run_time > 3600) {
$checker_manager->run();
$status_checker->run();
}
// Only try to send failure notifications if unattended updates are enabled.
if ($updater->getMode() !== CronUpdater::DISABLED) {
\Drupal::service('automatic_updates.status_check_mailer')
->sendFailureNotifications($last_results, $status_checker->getResults());
}
}
/**
* Implements hook_modules_installed().
*/
function automatic_updates_modules_installed() {
// Run the readiness checkers if needed when any modules are installed in
// case they provide readiness checker services.
/** @var \Drupal\automatic_updates\Validation\ReadinessValidationManager $checker_manager */
$checker_manager = \Drupal::service('automatic_updates.readiness_validation_manager');
$checker_manager->run();
// Run the status checkers if needed when any modules are installed in
// case they provide status checkers.
/** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */
$status_checker = \Drupal::service('automatic_updates.status_checker');
$status_checker->run();
}
/**
* Implements hook_modules_uninstalled().
*/
function automatic_updates_modules_uninstalled() {
// Run the readiness checkers if needed when any modules are uninstalled in
// case they provided readiness checker services.
/** @var \Drupal\automatic_updates\Validation\ReadinessValidationManager $checker_manager */
$checker_manager = \Drupal::service('automatic_updates.readiness_validation_manager');
$checker_manager->run();
}
/**
* Implements hook_form_FORM_ID_alter() for 'update_manager_update_form'.
*/
function automatic_updates_form_update_manager_update_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Remove current message that core updates are not supported with a link to
// use this module's form. The local task to 'update_manager_update_form' is
// replaced by our own from but this original form would still accessible via
// by its original URL.
if (isset($form['manual_updates']['#rows']['drupal']['data']['title'])) {
$current_route = \Drupal::routeMatch()->getRouteName();
if ($current_route === 'update.module_update') {
$redirect_route = 'automatic_updates.module_update';
}
elseif ($current_route === 'update.report_update') {
$redirect_route = 'automatic_updates.report_update';
}
if (!empty($redirect_route)) {
$core_updates_message = t(
'<h2>Core updates required</h2>Drupal core updates are supported by the enabled <a href="@url">Automatic Updates module</a>',
['@url' => Url::fromRoute($redirect_route)->toString()]
);
$form['manual_updates']['#prefix'] = $core_updates_message;
}
}
}
/**
* Implements hook_local_tasks_alter().
*/
function automatic_updates_local_tasks_alter(array &$local_tasks) {
// The Update module's update form only allows updating modules and themes
// via archive files, which could produce unexpected results on a site using
// our Composer-based updater.
$new_routes = [
'update.report_update' => 'automatic_updates.report_update',
'update.module_update' => 'automatic_updates.module_update',
'update.theme_update' => 'automatic_updates.theme_update',
];
foreach ($new_routes as $local_task_id => $new_route) {
if (!empty($local_tasks[$local_task_id])) {
$local_tasks[$local_task_id]['route_name'] = $new_route;
}
}
// Run the status checkers if needed when any modules are uninstalled in
// case they provided status checkers.
/** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */
$status_checker = \Drupal::service('automatic_updates.status_checker');
$status_checker->run();
}
/**
......@@ -248,7 +254,7 @@ function automatic_updates_preprocess_update_project_status(array &$variables) {
'#markup' => t(
'@label <a href=":update-form">Update now</a>', [
'@label' => $status['label'],
':update-form' => Url::fromRoute('automatic_updates.report_update')->toString(),
':update-form' => Url::fromRoute('update.report_update')->toString(),
]),
];
}
......@@ -259,7 +265,7 @@ function automatic_updates_preprocess_update_project_status(array &$variables) {
foreach ($variables['versions'] as &$themed_version) {
$version_info = &$themed_version['#version'];
if ($supported_target_versions && in_array($version_info['version'], $supported_target_versions, TRUE)) {
$version_info['download_link'] = Url::fromRoute('automatic_updates.report_update')->setAbsolute()->toString();
$version_info['download_link'] = Url::fromRoute('update.report_update')->setAbsolute()->toString();
}
else {
// If this version will not be displayed as an option on this module's
......
<?php
/**
* @file
* Contains post-update hooks for Automatic Updates.
*/
use Drupal\automatic_updates\StatusCheckMailer;
/**
* Creates the automatic_updates.settings:status_check_mail config.
*/
function automatic_updates_post_update_create_status_check_mail_config(): void {
\Drupal::configFactory()
->getEditable('automatic_updates.settings')
->set('status_check_mail', StatusCheckMailer::ERRORS_ONLY)
->save();
}
automatic_updates.update_readiness:
path: '/admin/automatic_updates/readiness'
automatic_updates.status_check:
path: '/admin/automatic_updates/status'
defaults:
_controller: '\Drupal\automatic_updates\Controller\ReadinessCheckerController::run'
_controller: '\Drupal\automatic_updates\Controller\StatusCheckController::run'
_title: 'Update readiness checking'
requirements:
_permission: 'administer software updates'
options:
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
automatic_updates.confirmation_page:
path: '/admin/automatic-update-ready/{stage_id}'
defaults:
......@@ -17,7 +17,7 @@ automatic_updates.confirmation_page:
_permission: 'administer software updates'
options:
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
automatic_updates.finish:
path: '/automatic-update/finish'
defaults:
......@@ -26,45 +26,43 @@ automatic_updates.finish:
_permission: 'administer software updates'
options:
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
automatic_updates.cron.post_apply:
path: '/automatic-update/cron/post-apply/{stage_id}/{installed_version}/{target_version}/{key}'
defaults:
_controller: 'automatic_updates.cron_updater:handlePostApply'
requirements:
_access_system_cron: 'TRUE'
# Links to our updater form appear in three different sets of local tasks. To ensure the breadcrumbs and paths are
# consistent with the other local tasks in each set, we need two separate routes to the same form.
# These routes are deprecated and will be removed in the next major version of
# Automatic Updates. They redirect to existing routes from the core Update
# module, which are overridden by Automatic Updates.
# @see \Drupal\automatic_updates\Routing\RouteSubscriber::alterRoutes()
automatic_updates.report_update:
path: '/admin/reports/updates/automatic-update'
defaults:
_form: '\Drupal\automatic_updates\Form\UpdaterForm'
_title: 'Update'
_controller: '\Drupal\automatic_updates\Controller\UpdateController::redirectDeprecatedRoute'
requirements:
_permission: 'administer software updates'
options:
_admin_route: TRUE
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_access: 'TRUE'
automatic_updates.module_update:
path: '/admin/modules/automatic-update'
defaults:
_form: '\Drupal\automatic_updates\Form\UpdaterForm'
_title: 'Update'
_controller: '\Drupal\automatic_updates\Controller\UpdateController::redirectDeprecatedRoute'
requirements:
_permission: 'administer software updates'
options:
_admin_route: TRUE
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_access: 'TRUE'
automatic_updates.theme_update:
path: '/admin/theme/automatic-update'
defaults:
_form: '\Drupal\automatic_updates\Form\UpdaterForm'
_title: 'Update'
_controller: '\Drupal\automatic_updates\Controller\UpdateController::redirectDeprecatedRoute'
requirements:
_access: 'TRUE'
automatic_updates.update_readiness:
path: '/admin/automatic_updates/readiness'
defaults:
_controller: '\Drupal\automatic_updates\Controller\StatusCheckController::runReadiness'
_title: 'Update readiness checking'
requirements:
_permission: 'administer software updates'
options:
_admin_route: TRUE
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
......@@ -3,8 +3,8 @@ services:
class: Drupal\automatic_updates\Routing\RouteSubscriber
tags:
- { name: event_subscriber }
automatic_updates.readiness_validation_manager:
class: Drupal\automatic_updates\Validation\ReadinessValidationManager
automatic_updates.status_checker:
class: Drupal\automatic_updates\Validation\StatusChecker
arguments:
- '@keyvalue.expirable'
- '@datetime.time'
......@@ -14,6 +14,17 @@ services:
- 24
tags:
- { name: event_subscriber }
automatic_updates.status_check_mailer:
class: Drupal\automatic_updates\StatusCheckMailer
arguments:
- '@config.factory'
- '@plugin.manager.mail'
- '@language_manager'
automatic_updates.readiness_validation_manager:
class: Drupal\automatic_updates\Validation\ReadinessValidationManager
arguments:
- '@automatic_updates.status_checker'
deprecated: The "%service_id%" service is deprecated in automatic_updates:8.x-2.5 and is removed from automatic_updates:3.0.0. Use the automatic_updates.status_checker service instead. See https://www.drupal.org/node/3316086.
automatic_updates.updater:
class: Drupal\automatic_updates\Updater
arguments:
......@@ -36,7 +47,7 @@ services:
- '@automatic_updates.release_chooser'
- '@logger.factory'
- '@plugin.manager.mail'
- '@language_manager'
- '@automatic_updates.status_check_mailer'
- '@state'
- '@config.factory'
- '@package_manager.path_locator'
......@@ -61,60 +72,6 @@ services:
class: Drupal\automatic_updates\ReleaseChooser
arguments:
- '@automatic_updates.validator.version_policy'
automatic_updates.composer_executable_validator:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.composer_executable'
tags:
- { name: event_subscriber }
automatic_updates.settings_validator:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.settings'
tags:
- { name: event_subscriber }
automatic_updates.validator.composer_settings:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.composer_settings'
tags:
- { name: event_subscriber }
automatic_updates.disk_space_validator:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.disk_space'
tags:
- { name: event_subscriber }
automatic_updates.pending_updates_validator:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.pending_updates'
tags:
- { name: event_subscriber }
automatic_updates.validator.file_system_permissions:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.file_system'
tags:
- { name: event_subscriber }
automatic_updates.validator.multisite:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.multisite'
tags:
- { name: event_subscriber }
automatic_updates.validator.symlink:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.symlink'
tags:
- { name: event_subscriber }
automatic_updates.validator.patches:
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '@package_manager.validator.patches'
tags:
- { name: event_subscriber }
automatic_updates.cron_frequency_validator:
class: Drupal\automatic_updates\Validator\CronFrequencyValidator
arguments:
......@@ -135,6 +92,8 @@ services:
- { name: event_subscriber }
automatic_updates.validator.xdebug:
class: Drupal\automatic_updates\Validator\XdebugValidator
arguments:
- '@package_manager.validator.xdebug'
tags:
- { name: event_subscriber }
automatic_updates.validator.version_policy:
......@@ -145,6 +104,8 @@ services:
- { name: event_subscriber }
automatic_updates.config_subscriber:
class: Drupal\automatic_updates\EventSubscriber\ConfigSubscriber
arguments:
- '@automatic_updates.status_checker'
tags:
- { name: event_subscriber }
automatic_updates.validator.scaffold_file_permissions:
......@@ -158,6 +119,7 @@ services:
arguments:
- '@request_stack'
- '@config.factory'
- '@module_handler'
tags:
- { name: event_subscriber }
logger.channel.automatic_updates:
......
......@@ -7,7 +7,7 @@ automatic_updates_extensions.report_update:
_permission: 'administer software updates'
options:
_admin_route: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
automatic_updates_extensions.module_update:
path: '/admin/modules/automatic-update-extensions'
......@@ -19,7 +19,7 @@ automatic_updates_extensions.module_update:
options:
_admin_route: TRUE
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
automatic_updates_extension.theme_update:
path: '/admin/appearance/automatic-update-extensions'
......@@ -31,7 +31,7 @@ automatic_updates_extension.theme_update:
options:
_admin_route: TRUE
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
automatic_updates_extension.confirmation_page:
path: '/admin/automatic-update-extensions-ready/{stage_id}'
......@@ -43,4 +43,4 @@ automatic_updates_extension.confirmation_page:
options:
_admin_route: TRUE
_maintenance_access: TRUE
_automatic_updates_readiness_messages: skip
_automatic_updates_status_messages: skip
......@@ -117,6 +117,15 @@ final class BatchProcessor {
public static function commit(string $stage_id, array &$context): void {
try {
static::getUpdater()->claim($stage_id)->apply();
// The batch system does not allow any single request to run for longer
// than a second, so this will force the next operation to be done in a
// new request. This helps keep the running code in as consistent a state
// as possible.
// @see \Drupal\package_manager\Stage::apply()
// @see \Drupal\package_manager\Stage::postApply()
// @todo See if there's a better way to ensure the post-apply tasks run
// in a new request in https://www.drupal.org/i/3293150.
sleep(1);
}
catch (\Throwable $e) {
static::handleException($e, $context);
......
......@@ -108,7 +108,7 @@ class ExtensionUpdater extends Stage {
parent::dispatch($event, $on_error);
}
catch (StageValidationException $e) {
throw new UpdateException($e->getResults(), $e->getMessage() ?: "Unable to complete the update because of errors.", $e->getCode(), $e);
throw new UpdateException($e->getResults(), $e->getMessage(), $e->getCode(), $e);
}
}
......
......@@ -2,15 +2,15 @@
namespace Drupal\automatic_updates_extensions\Form;
use Drupal\automatic_updates\Form\UpdateFormBase;
use Drupal\package_manager\Exception\ApplyFailedException;
use Drupal\package_manager\ProjectInfo;
use Drupal\package_manager\Validator\StagedDBUpdateValidator;
use Drupal\package_manager\ValidationResult;
use Drupal\automatic_updates_extensions\BatchProcessor;
use Drupal\automatic_updates\BatchProcessor as AutoUpdatesBatchProcessor;
use Drupal\automatic_updates_extensions\ExtensionUpdater;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Messenger\MessengerInterface;
......@@ -18,7 +18,9 @@ use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\package_manager\Exception\StageException;
use Drupal\package_manager\Exception\StageOwnershipException;
use Drupal\system\SystemManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Defines a form to commit staged updates.
......@@ -26,7 +28,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* @internal
* Form classes are internal.
*/
final class UpdateReady extends FormBase {
final class UpdateReady extends UpdateFormBase {
/**
* The updater service.
......@@ -50,18 +52,18 @@ final class UpdateReady extends FormBase {
protected $moduleList;
/**
* The staged database update validator service.
* The renderer service.
*
* @var \Drupal\package_manager\Validator\StagedDBUpdateValidator
* @var \Drupal\Core\Render\RendererInterface
*/
protected $stagedDatabaseUpdateValidator;
protected $renderer;
/**
* The renderer service.
* The event dispatcher.
*
* @var \Drupal\Core\Render\RendererInterface
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $renderer;
protected $eventDispatcher;
/**
* Constructs a new UpdateReady object.
......@@ -74,18 +76,18 @@ final class UpdateReady extends FormBase {
* The state service.
* @param \Drupal\Core\Extension\ModuleExtensionList $module_list
* The module list service.
* @param \Drupal\package_manager\Validator\StagedDBUpdateValidator $staged_database_update_validator
* The staged database update validator service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* Event dispatcher service.
*/
public function __construct(ExtensionUpdater $updater, MessengerInterface $messenger, StateInterface $state, ModuleExtensionList $module_list, StagedDBUpdateValidator $staged_database_update_validator, RendererInterface $renderer) {
public function __construct(ExtensionUpdater $updater, MessengerInterface $messenger, StateInterface $state, ModuleExtensionList $module_list, RendererInterface $renderer, EventDispatcherInterface $event_dispatcher) {
$this->updater = $updater;
$this->setMessenger($messenger);
$this->state = $state;
$this->moduleList = $module_list;
$this->stagedDatabaseUpdateValidator = $staged_database_update_validator;
$this->renderer = $renderer;
$this->eventDispatcher = $event_dispatcher;
}
/**
......@@ -104,8 +106,8 @@ final class UpdateReady extends FormBase {
$container->get('messenger'),
$container->get('state'),
$container->get('extension.list.module'),
$container->get('package_manager.validator.staged_database_updates'),
$container->get('renderer')
$container->get('renderer'),
$container->get('event_dispatcher')
);
}
......@@ -127,23 +129,6 @@ final class UpdateReady extends FormBase {
$messages = [];
// If there are any installed extension with database updates in the staging
// area, warn the user that they might be sent to update.php once the staged
// changes have been applied.
$pending_updates = $this->stagedDatabaseUpdateValidator->getExtensionsWithDatabaseUpdates($this->updater);
if ($pending_updates) {
natcasesort($pending_updates);
$message_item_list = [
'#theme' => 'item_list',
'#prefix' => '<p>' . $this->t('Possible database updates were detected in the following extensions; you may be redirected to the database update page in order to complete the update process.') . '</p>',
'#items' => $pending_updates,
'#context' => [
'list_style' => 'automatic-updates-extensions__pending-database-updates',
],
];
$messages[MessengerInterface::TYPE_WARNING][] = $this->renderer->renderRoot($message_item_list);
}
// Don't set any messages if the form has been submitted, because we don't
// want them to be set during form submit.
if (!$form_state->getUserInput()) {
......@@ -177,6 +162,18 @@ final class UpdateReady extends FormBase {
'#type' => 'checkbox',
'#default_value' => TRUE,
];
// Don't run the status checks once the form has been submitted.
if (!$form_state->getUserInput()) {
$results = $this->runStatusCheck($this->updater, $this->eventDispatcher);
// This will have no effect if $results is empty.
$this->displayResults($results, $this->renderer);
// If any errors occurred, return the form early so the user cannot
// continue.
if (ValidationResult::getOverallSeverity($results) === SystemManager::REQUIREMENT_ERROR) {
return $form;
}
}
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Continue'),
......
......@@ -2,12 +2,10 @@
namespace Drupal\automatic_updates_extensions\Form;
use Drupal\automatic_updates\Event\ReadinessCheckEvent;
use Drupal\automatic_updates\Validation\ReadinessTrait;
use Drupal\automatic_updates\Form\UpdateFormBase;
use Drupal\automatic_updates_extensions\BatchProcessor;
use Drupal\automatic_updates_extensions\ExtensionUpdater;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Messenger\MessengerInterface;
......@@ -16,6 +14,7 @@ use Drupal\Core\Url;
use Drupal\package_manager\Exception\ApplyFailedException;
use Drupal\package_manager\FailureMarker;
use Drupal\package_manager\ProjectInfo;
use Drupal\package_manager\ValidationResult;
use Drupal\system\SystemManager;
use Drupal\update\UpdateManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -27,9 +26,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
* @internal
* Form classes are internal.
*/
final class UpdaterForm extends FormBase {
use ReadinessTrait;
final class UpdaterForm extends UpdateFormBase {
/**
* The extension updater service.
......@@ -165,12 +162,10 @@ final class UpdaterForm extends FormBase {
$results = [];
}
else {
$event = new ReadinessCheckEvent($this->extensionUpdater);
$this->eventDispatcher->dispatch($event);
$results = $event->getResults();
$results = $this->runStatusCheck($this->extensionUpdater, $this->eventDispatcher, TRUE);
}
$this->displayResults($results, $this->messenger(), $this->renderer);
$security_level = $this->getOverallSeverity($results);
$this->displayResults($results, $this->renderer);
$security_level = ValidationResult::getOverallSeverity($results);
if ($update_projects && $security_level !== SystemManager::REQUIREMENT_ERROR) {
$form['actions'] = $this->actions($form_state);
......
......@@ -103,7 +103,7 @@ final class UpdateReleaseValidator implements EventSubscriberInterface {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
public static function getSubscribedEvents(): array {
return [
PreCreateEvent::class => 'checkRelease',
];
......
......@@ -4,3 +4,4 @@ type: module
package: Testing
dependencies:
- automatic_updates:automatic_updates_extensions
- automatic_updates:package_manager_test_api
......@@ -4,3 +4,9 @@ automatic_updates_extensions_test_api:
_controller: 'Drupal\automatic_updates_extensions_test_api\ApiController::run'
requirements:
_access: 'TRUE'
automatic_updates_extensions_test_api.finish:
path: '/automatic-updates-extensions-test-api/finish/{id}'
defaults:
_controller: 'Drupal\automatic_updates_extensions_test_api\ApiController::finish'
requirements:
_access: 'TRUE'
......@@ -2,45 +2,19 @@
namespace Drupal\automatic_updates_extensions_test_api;
use Drupal\automatic_updates_extensions\ExtensionUpdater;
use Drupal\Core\Controller\ControllerBase;
use Drupal\package_manager\PathLocator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\package_manager_test_api\ApiController as PackageManagerApiController;
/**
* Provides API endpoints to interact with a staging area in functional tests.
*/
class ApiController extends ControllerBase {
/**
* The extension updater.
*
* @var \Drupal\automatic_updates_extensions\ExtensionUpdater
*/
private $extensionUpdater;
class ApiController extends PackageManagerApiController {
/**
* The path locator service.
*
* @var \Drupal\package_manager\PathLocator
*/
private $pathLocator;
/**
* Constructs an ApiController object.
*
* @param \Drupal\automatic_updates_extensions\ExtensionUpdater $extension_updater
* The updater.
* @param \Drupal\package_manager\PathLocator $path_locator
* The path locator service.
* {@inheritdoc}
*/
public function __construct(ExtensionUpdater $extension_updater, PathLocator $path_locator) {
$this->extensionUpdater = $extension_updater;
$this->pathLocator = $path_locator;
}
protected $finishedRoute = 'automatic_updates_extensions_test_api.finish';
/**
* {@inheritdoc}
......@@ -53,36 +27,13 @@ class ApiController extends ControllerBase {
}
/**
* Runs a complete stage life cycle.
*
* Creates a staging area, requires packages into it, applies changes to the
* active directory, and destroys the stage.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request. The runtime and dev dependencies are expected to be in
* either the query string or request body, under the 'runtime' and 'dev'
* keys, respectively. There may also be a 'files_to_return' key, which
* contains an array of file paths, relative to the project root, whose
* contents should be returned in the response.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
* A JSON response containing an associative array of the contents of the
* files listed in the 'files_to_return' request key. The array will be
* keyed by path, relative to the project root.
* {@inheritdoc}
*/
public function run(Request $request): JsonResponse {
$this->extensionUpdater->begin($request->get('projects', []));
$this->extensionUpdater->stage();
$this->extensionUpdater->apply();
$this->extensionUpdater->postApply();
$this->extensionUpdater->destroy();
$dir = $this->pathLocator->getProjectRoot();
$file_contents = [];
foreach ($request->get('files_to_return', []) as $path) {
$file_contents[$path] = file_get_contents($dir . '/' . $path);
}
return new JsonResponse($file_contents);
protected function createAndApplyStage(Request $request): string {
$id = $this->stage->begin($request->get('projects', []));
$this->stage->stage();
$this->stage->apply();
return $id;
}
}
......@@ -21,7 +21,7 @@ class ModuleUpdateTest extends UpdateTestBase {
protected function createTestProject(string $template): void {
parent::createTestProject($template);
$this->setReleaseMetadata([
'drupal' => __DIR__ . '/../../../../tests/fixtures/release-history/drupal.9.8.1-security.xml',
'drupal' => __DIR__ . '/../../../../package_manager/tests/fixtures/release-history/drupal.9.8.1-security.xml',
'alpha' => __DIR__ . '/../../fixtures/release-history/alpha.1.1.0.xml',
'new_module' => __DIR__ . '/../../fixtures/release-history/new_module.1.1.0.xml',
]);
......
......@@ -2,13 +2,14 @@
namespace Drupal\Tests\automatic_updates_extensions\Functional;
use Drupal\automatic_updates\Event\ReadinessCheckEvent;
use Drupal\automatic_updates_test\EventSubscriber\TestSubscriber1;
use Drupal\package_manager_test_validation\StagedDatabaseUpdateValidator;
use Drupal\package_manager\Event\PreApplyEvent;
use Drupal\package_manager\Event\StatusCheckEvent;
use Drupal\package_manager\ValidationResult;
use Drupal\package_manager_bypass\Committer;
use Drupal\package_manager_bypass\Stager;
use Drupal\package_manager_test_validation\EventSubscriber\TestSubscriber;
use Drupal\Tests\automatic_updates\Functional\AutomaticUpdatesFunctionalTestBase;
use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait;
use Drupal\Tests\automatic_updates_extensions\Traits\FormTestTrait;
......@@ -192,11 +193,7 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
// Ensure that a list of pending database updates is visible, along with a
// short explanation, in the warning messages.
$warning_messages = $assert_session->elementExists('xpath', '//div[@data-drupal-messages]//div[@aria-label="Warning message"]');
$this->assertStringContainsString('Possible database updates were detected in the following extensions; you may be redirected to the database update page in order to complete the update process.', $warning_messages->getText());
$pending_updates = $warning_messages->findAll('css', 'ul.item-list__automatic-updates-extensions__pending-database-updates li');
$this->assertCount(2, $pending_updates);
$this->assertSame('Automatic Updates Theme With Updates', $pending_updates[0]->getText());
$this->assertSame('System', $pending_updates[1]->getText());
$this->assertStringContainsString('Possible database updates have been detected in the following extensions.<ul><li>System</li><li>Automatic Updates Theme With Updates</li></ul>', $warning_messages->getHtml());
$page->pressButton('Continue');
$this->checkForMetaRefresh();
......@@ -207,6 +204,14 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
$assert_session->pageTextContainsOnce('Update complete!');
// Confirm the site was returned to the original maintenance mode state.
$this->assertSame($state->get('system.maintenance_mode'), $maintenance_mode_on);
// Confirm that the apply and post-apply operations happened in
// separate requests.
// @see \Drupal\automatic_updates_test\EventSubscriber\RequestTimeRecorder
$pre_apply_time = $state->get('Drupal\package_manager\Event\PreApplyEvent time');
$post_apply_time = $state->get('Drupal\package_manager\Event\PostApplyEvent time');
$this->assertNotEmpty($pre_apply_time);
$this->assertNotEmpty($post_apply_time);
$this->assertNotSame($pre_apply_time, $post_apply_time);
}
/**
......@@ -426,7 +431,7 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
$this->assertUpdatesCount(1);
$message = t("You've not experienced Shakespeare until you have read him in the original Klingon.");
$error = ValidationResult::createError([$message]);
TestSubscriber1::setTestResult([$error], ReadinessCheckEvent::class);
TestSubscriber1::setTestResult([$error], StatusCheckEvent::class);
$this->getSession()->reload();
$assert->pageTextContains($message);
$assert->pageTextContains(static::$errorsExplanation);
......@@ -444,15 +449,69 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
$this->checkForUpdates();
$message = t("Warning! Updating this module may cause an error.");
$warning = ValidationResult::createWarning([$message]);
TestSubscriber1::setTestResult([$warning], ReadinessCheckEvent::class);
TestSubscriber1::setTestResult([$warning], StatusCheckEvent::class);
// Navigate to the automatic updates form.
$this->drupalGet('/admin/reports/updates');
$this->clickLink('Update Extensions');
$this->assertTableShowsUpdates('Semver Test', '8.1.0', '8.1.1');
$this->assertUpdatesCount(1);
$assert->pageTextContains(static::$warningsExplanation);
$this->checkForMetaRefresh();
$assert->pageTextNotContains(static::$errorsExplanation);
$assert->elementExists('css', '#edit-projects-semver-test')->check();
$assert->checkboxChecked('edit-projects-semver-test');
$assert->pageTextContains(static::$warningsExplanation);
$assert->buttonExists('Update');
// Add warnings from StatusCheckEvent.
$summary_status_check_event = t('Some summary');
$messages_status_check_event = [
"The only thing we're allowed to do is to",
"believe that we won't regret the choice",
"we made.",
];
$warning_status_check_event = ValidationResult::createWarning($messages_status_check_event, $summary_status_check_event);
TestSubscriber::setTestResult([$warning_status_check_event], StatusCheckEvent::class);
$this->getSession()->getPage()->pressButton('Update');
$this->checkForMetaRefresh();
$assert->buttonExists('Continue');
$assert->pageTextContains($summary_status_check_event);
foreach ($messages_status_check_event as $message) {
$assert->pageTextContains($message);
}
}
/**
* Tests that messages from StatusCheckEvent are shown on the confirmation form.
*/
public function testStatusErrorMessages(): void {
$this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/semver_test.1.1.xml');
$assert = $this->assertSession();
$this->setProjectInstalledVersion(['semver_test' => '8.1.0']);
$this->checkForUpdates();
$this->drupalGet('admin/reports/updates/automatic-update-extensions');
$this->assertTableShowsUpdates('Semver Test', '8.1.0', '8.1.1');
$this->assertUpdatesCount(1);
$this->getSession()->reload();
$assert->elementExists('css', '#edit-projects-semver-test')->check();
$assert->checkboxChecked('edit-projects-semver-test');
$assert->buttonExists('Update');
$messages = [
"The only thing we're allowed to do is to",
"believe that we won't regret the choice",
"we made.",
];
$summary = t('Some summary');
$error = ValidationResult::createError($messages, $summary);
TestSubscriber::setTestResult([$error], StatusCheckEvent::class);
$this->getSession()->getPage()->pressButton('Update');
$this->checkForMetaRefresh();
$assert->pageTextContains(static::$errorsExplanation);
$assert->pageTextNotContains(static::$warningsExplanation);
$assert->pageTextContains($summary);
foreach ($messages as $message) {
$assert->pageTextContains($message);
}
$assert->buttonNotExists('Continue');
}
/**
......
......@@ -2,7 +2,12 @@
namespace Drupal\Tests\automatic_updates_extensions\Kernel;
use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase;
use Drupal\automatic_updates\Exception\UpdateException;
use Drupal\automatic_updates_test\EventSubscriber\TestSubscriber1;
use Drupal\package_manager\Event\PreApplyEvent;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\Event\PreRequireEvent;
use Drupal\package_manager\ValidationResult;
use Drupal\Tests\user\Traits\UserCreationTrait;
/**
......@@ -10,7 +15,7 @@ use Drupal\Tests\user\Traits\UserCreationTrait;
*
* @group automatic_updates_extensions
*/
class ExtensionUpdaterTest extends AutomaticUpdatesKernelTestBase {
class ExtensionUpdaterTest extends AutomaticUpdatesExtensionsKernelTestBase {
use UserCreationTrait;
......@@ -146,4 +151,51 @@ class ExtensionUpdaterTest extends AutomaticUpdatesKernelTestBase {
]);
}
/**
* Tests UpdateException handling.
*
* @param string $event_class
* The stage life cycle event which should raise an error.
*
* @dataProvider providerUpdateException
*/
public function testUpdateException(string $event_class): void {
$this->createVirtualProject(__DIR__ . '/../../fixtures/fake-site');
$extension_updater = $this->container->get('automatic_updates_extensions.updater');
$results = [
ValidationResult::createError(['An error of some sorts.']),
];
TestSubscriber1::setTestResult($results, $event_class);
try {
$extension_updater->begin(['my_module' => '9.8.1']);
$extension_updater->stage();
$extension_updater->apply();
$this->fail('Expected an exception, but none was raised.');
}
catch (UpdateException $e) {
$this->assertStringStartsWith('An error of some sorts.', $e->getMessage());
$this->assertInstanceOf($event_class, $e->event);
}
}
/**
* Data provider for testUpdateException().
*
* @return string[][]
* The test cases.
*/
public function providerUpdateException(): array {
return [
'pre-create exception' => [
PreCreateEvent::class,
],
'pre-require exception' => [
PreRequireEvent::class,
],
'pre-apply exception' => [
PreApplyEvent::class,
],
];
}
}
......@@ -13,7 +13,7 @@
"require": {
"ext-json": "*",
"drupal/core": "^9.3",
"php-tuf/composer-stager": "^1.1",
"php-tuf/composer-stager": "^1.2",
"composer/composer": "^2.2.12 || ^2.3.5",
"composer-runtime-api": "^2.1",
"symfony/config": "^4.4 || ^6.1",
......@@ -31,11 +31,18 @@
"test": [
"Composer\\Config::disableProcessTimeout",
"scripts/phpunit.sh"
]
],
"core-convert": "Drupal\\automatic_updates\\CoreCovert\\Converter::doConvert"
},
"scripts-descriptions": {
"phpcbf": "Automatically fixes standards violations where possible.",
"phpcs": "Checks code for standards compliance.",
"test": "Runs PHPUnit tests."
}
"test": "Runs PHPUnit tests.",
"core-convert": "Converts this module to a core merge request. Excepts 2 arguments. 1) The core clone directory. 2) The core merge request branch."
},
"autoload": {
"psr-4": {
"Drupal\\automatic_updates\\CoreCovert\\": "scripts/src"
}
}
}
cron: security
allow_core_minor_updates: false
status_check_mail: errors_only