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 (133)
Showing
with 238 additions and 535 deletions
{
"dictionaries": ["drupal","companies", "fonts", "html", "php", "softwareTerms", "automatic_updates"],
"dictionaryDefinitions": [
{ "name": "automatic_updates", "path": "./dictionary.txt"}
],
"ignorePaths": [
"README.md"
]
}
......@@ -7,7 +7,7 @@ A simple setup is enough for most users to start contributing to Automatic Updat
Assuming you meet the [system requirements](#system-requirements), simply run the following command <sup>[[1]](#footnote-1), [[2]](#footnote-2)</sup> from the directory you would like to install your development environment under <sup>[[3]](#footnote-3)</sup>. It will prompt for confirmation before beginning.
```shell
/bin/bash -c "$(curl -fsSL https://git.drupalcode.org/project/automatic_updates/-/raw/8.x-2.x/scripts/setup_local_dev.sh)"
/bin/bash -c "$(curl -fsSL https://git.drupalcode.org/project/automatic_updates/-/raw/3.0.x/scripts/setup_local_dev.sh)"
```
That's it. The success message will display next steps.
......@@ -26,7 +26,7 @@ That's it. The success message will display next steps.
### System requirements
* A *nix-based operating system, such as Linux or macOS.
* PHP 7.4 or later.
* Drupal 10 or later.
* Composer 2 or later. (Automatic Updates is not compatible with Composer 1.)
* Git must be installed.
......@@ -39,25 +39,27 @@ That's it. The success message will display next steps.
Several details of your setup can be customized via environment variables. Set these before running [the installation command above](#local-development-environment-setup).
```shell
DRUPAL_CORE_BRANCH="9.5.x" # The branch of Drupal core that will be installed.
DRUPAL_CORE_BRANCH="10.0.x" # The branch of Drupal core that will be installed.
DRUPAL_CORE_SHALLOW_CLONE="TRUE" # Whether or not to do a "shallow clone" of Drupal core. (Defaults to TRUE.) See note below.
AUTOMATIC_UPDATES_BRANCH="8.x-2.x" # The branch of the Automatic Updates module that will be installed.
AUTOMATIC_UPDATES_BRANCH="3.0.x" # The branch of the Automatic Updates module that will be installed.
SITE_DIRECTORY="auto_updates_dev" # The path to the directory where the dev environment will be installed.
SITE_HOST=".test" # The path for Drupal's TRUSTED_HOST_PATTERN.
```
Note: A shallow Git clone is much smaller and therefore faster, but it removes the ability to do debugging operations such as `git bisect` or `git blame`. To recover these abilities, [you can convert your repository to a full clone after the fact](https://stackoverflow.com/questions/6802145/how-to-convert-a-git-shallow-clone-to-a-full-clone):
// cSpell:disable
```shell
cd auto-updates-dev
git fetch --unshallow
```
// cSpell:enable
### Alternative setup options
You can download the setup script first to review its contents or modify it before running it:
```shell
curl --output setup_local_dev.sh https://git.drupalcode.org/project/automatic_updates/-/raw/8.x-2.x/scripts/setup_local_dev.sh
curl --output setup_local_dev.sh https://git.drupalcode.org/project/automatic_updates/-/raw/3.0.x/scripts/setup_local_dev.sh
./scripts/setup_local_dev.sh
```
......@@ -80,7 +82,7 @@ To set up your environment manually, use the setup script as a reference.
---
<a name="footnote-1"><sup>1</sup></a> When running a script downloaded from the Web, it is always wise to read its contents first. Ours ([`setup_local_dev.sh`](https://git.drupalcode.org/project/automatic_updates/-/raw/8.x-2.x/scripts/setup_local_dev.sh)) is documented with code comments to help with that. For a more cautious approach, see [Alternative setup options](#alternative-setup-options) above.
<a name="footnote-1"><sup>1</sup></a> When running a script downloaded from the Web, it is always wise to read its contents first. Ours ([`setup_local_dev.sh`](https://git.drupalcode.org/project/automatic_updates/-/raw/3.0.x/scripts/setup_local_dev.sh)) is documented with code comments to help with that. For a more cautious approach, see [Alternative setup options](#alternative-setup-options) above.
<a name="footnote-2"><sup>2</sup></a> Curl options explained:
[`-f, --fail`](https://curl.se/docs/manpage.html#-f),
......
name: 'Automatic Updates'
type: module
description: 'Automatically updates Drupal core.'
core_version_requirement: ^9.3 || ^10
core_version_requirement: ^9.7 || ^10
dependencies:
- drupal:package_manager
- drupal:update
......@@ -7,7 +7,7 @@
declare(strict_types = 1);
use Drupal\automatic_updates\CronUpdater;
use Drupal\automatic_updates\CronUpdateStage;
use Drupal\automatic_updates\Validation\StatusCheckRequirements;
use Drupal\system\SystemManager;
......@@ -15,7 +15,7 @@ use Drupal\system\SystemManager;
* Implements hook_uninstall().
*/
function automatic_updates_uninstall() {
\Drupal::service('automatic_updates.updater')->destroy(TRUE);
\Drupal::service('automatic_updates.update_stage')->destroy(TRUE);
}
/**
......@@ -30,7 +30,7 @@ function automatic_updates_requirements($phase) {
// Check that site has cron updates enabled or not.
// @todo Remove in https://www.drupal.org/project/automatic_updates/issues/3284443
if (\Drupal::configFactory()->get('automatic_updates.settings')->get('cron') !== CronUpdater::DISABLED) {
if (\Drupal::configFactory()->get('automatic_updates.settings')->get('cron') !== CronUpdateStage::DISABLED) {
$requirements['automatic_updates_cron'] = [
'title' => t('Cron installs updates automatically'),
'severity' => SystemManager::REQUIREMENT_WARNING,
......@@ -42,29 +42,13 @@ function automatic_updates_requirements($phase) {
}
}
/**
* 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');
}
// BEGIN: DELETE FROM CORE MERGE REQUEST
/**
* Sets cron setting to \Drupal\automatic_updates\CronUpdater::DISABLED.
*
* This is necessary until TUF support is available on drupal.org. This used to
* be hardcoded, but that caused complex race conditions in tests. Hence, it is
* now just configured.
*
* @see automatic_updates_requirements()
* @see https://www.drupal.org/project/automatic_updates/issues/3284443
* Implements hook_update_last_removed().
*/
function automatic_updates_update_9002(): void {
/** @var \Drupal\Core\Config\Config $config */
$config = \Drupal::service('config.factory')->getEditable('automatic_updates.settings');
$config->set('cron', CronUpdater::DISABLED)->save();
function automatic_updates_update_last_removed(): int {
return 9002;
}
// END: DELETE FROM CORE MERGE REQUEST
......@@ -8,12 +8,12 @@
declare(strict_types = 1);
use Drupal\automatic_updates\BatchProcessor;
use Drupal\automatic_updates\CronUpdater;
use Drupal\automatic_updates\CronUpdateStage;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\automatic_updates\Validation\AdminStatusCheckMessages;
use Drupal\Core\Url;
use Drupal\package_manager\ComposerInspector;
use Drupal\system\Controller\DbUpdateController;
use Drupal\package_manager\Validator\ComposerExecutableValidator;
/**
* Implements hook_help().
......@@ -31,7 +31,7 @@ function automatic_updates_help($route_name, RouteMatchInterface $route_match) {
$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>' . 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' => ComposerInspector::SUPPORTED_VERSION]) . '</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>';
......@@ -127,10 +127,7 @@ function automatic_updates_page_top() {
// @todo Rely on the route option after https://www.drupal.org/i/3236497 is
// committed.
// @todo Remove 'system.batch_page.html' after
// https://www.drupal.org/i/3238311 is committed.
$skip_routes = [
'system.batch_page.html',
'automatic_updates.confirmation_page',
'automatic_updates.report_update',
'automatic_updates.module_update',
......@@ -166,15 +163,15 @@ function automatic_updates_module_implements_alter(&$implementations, $hook) {
* Implements hook_cron().
*/
function automatic_updates_cron() {
// @todo Refactor this after https://www.drupal.org/project/drupal/issues/2969056
// @todo Refactor this after https://www.drupal.org/project/drupal/issues/2538292
// @todo Remove this after https://www.drupal.org/project/drupal/issues/3318964
if (defined('MAINTENANCE_MODE') || stripos($_SERVER['PHP_SELF'], 'update.php') !== FALSE) {
return;
}
/** @var \Drupal\automatic_updates\CronUpdater $updater */
$updater = \Drupal::service('automatic_updates.cron_updater');
$updater->handleCron();
/** @var \Drupal\automatic_updates\CronUpdateStage $stage */
$stage = \Drupal::service('automatic_updates.cron_update_stage');
$stage->handleCron();
/** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */
$status_checker = \Drupal::service('automatic_updates.status_checker');
......@@ -187,7 +184,7 @@ function automatic_updates_cron() {
}
// Only try to send failure notifications if unattended updates are enabled.
if ($updater->getMode() !== CronUpdater::DISABLED) {
if ($stage->getMode() !== CronUpdateStage::DISABLED) {
\Drupal::service('automatic_updates.status_check_mailer')
->sendFailureNotifications($last_results, $status_checker->getResults());
}
......@@ -202,12 +199,12 @@ function automatic_updates_modules_installed($modules) {
/** @var \Drupal\automatic_updates\Validation\StatusChecker $status_checker */
$status_checker = \Drupal::service('automatic_updates.status_checker');
$status_checker->run();
/** @var \Drupal\automatic_updates\CronUpdater $cron_updater */
$cron_updater = \Drupal::service('automatic_updates.cron_updater');
/** @var \Drupal\automatic_updates\CronUpdateStage $stage */
$stage = \Drupal::service('automatic_updates.cron_update_stage');
// 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
// alerted to any problems until they access the status report page.
if ($cron_updater->getMode() === CronUpdater::DISABLED) {
if ($stage->getMode() === CronUpdateStage::DISABLED) {
/** @var \Drupal\automatic_updates\Validation\AdminStatusCheckMessages $status_check_messages */
$status_check_messages = \Drupal::classResolver(AdminStatusCheckMessages::class);
$status_check_messages->displayResultSummary();
......@@ -246,15 +243,15 @@ function automatic_updates_preprocess_update_project_status(array &$variables) {
if ($project['name'] !== 'drupal') {
return;
}
$updater = \Drupal::service('automatic_updates.updater');
$stage = \Drupal::service('automatic_updates.update_stage');
$supported_target_versions = [];
/** @var \Drupal\automatic_updates\ReleaseChooser $recommender */
$recommender = \Drupal::service('automatic_updates.release_chooser');
try {
if ($installed_minor_release = $recommender->getLatestInInstalledMinor($updater)) {
if ($installed_minor_release = $recommender->getLatestInInstalledMinor($stage)) {
$supported_target_versions[] = $installed_minor_release->getVersion();
}
if ($next_minor_release = $recommender->getLatestInNextMinor($updater)) {
if ($next_minor_release = $recommender->getLatestInNextMinor($stage)) {
$supported_target_versions[] = $next_minor_release->getVersion();
}
}
......
......@@ -3,18 +3,17 @@
/**
* @file
* Contains post-update hooks for Automatic Updates.
*
* DELETE THIS FILE FROM CORE MERGE REQUEST.
*/
declare(strict_types = 1);
use Drupal\automatic_updates\StatusCheckMailer;
/**
* Creates the automatic_updates.settings:status_check_mail config.
* Implements hook_removed_post_updates().
*/
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();
function automatic_updates_removed_post_updates(): array {
return [
'automatic_updates_post_update_create_status_check_mail_config' => '3.0.0',
];
}
......@@ -30,39 +30,6 @@ automatic_updates.finish:
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'
_controller: 'automatic_updates.cron_update_stage:handlePostApply'
requirements:
_access_system_cron: 'TRUE'
# 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:
_controller: '\Drupal\automatic_updates\Controller\UpdateController::redirectDeprecatedRoute'
requirements:
_access: 'TRUE'
automatic_updates.module_update:
path: '/admin/modules/automatic-update'
defaults:
_controller: '\Drupal\automatic_updates\Controller\UpdateController::redirectDeprecatedRoute'
requirements:
_access: 'TRUE'
automatic_updates.theme_update:
path: '/admin/theme/automatic-update'
defaults:
_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:
_maintenance_access: TRUE
_automatic_updates_status_messages: skip
services:
_defaults:
autowire: true
automatic_updates.route_subscriber:
class: Drupal\automatic_updates\Routing\RouteSubscriber
tags:
......@@ -6,121 +9,61 @@ services:
automatic_updates.status_checker:
class: Drupal\automatic_updates\Validation\StatusChecker
arguments:
- '@keyvalue.expirable'
- '@datetime.time'
- '@event_dispatcher'
- '@automatic_updates.updater'
- '@automatic_updates.cron_updater'
- 24
# @todo Remove this when https://drupal.org/i/3325557 lands.
$key_value_expirable_factory: '@keyvalue.expirable'
$resultsTimeToLive: 24
tags:
- { name: event_subscriber }
Drupal\automatic_updates\Validation\StatusChecker: '@automatic_updates.status_checker'
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:
- '@config.factory'
- '@package_manager.path_locator'
- '@package_manager.beginner'
- '@package_manager.stager'
- '@package_manager.committer'
- '@file_system'
- '@event_dispatcher'
- '@tempstore.shared'
- '@datetime.time'
- '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface'
- '@package_manager.failure_marker'
Drupal\automatic_updates\StatusCheckMailer: '@automatic_updates.status_check_mailer'
automatic_updates.update_stage:
class: Drupal\automatic_updates\UpdateStage
calls:
- ['setLogger', ['@logger.channel.automatic_updates']]
automatic_updates.cron_updater:
class: Drupal\automatic_updates\CronUpdater
arguments:
- '@automatic_updates.release_chooser'
- '@logger.factory'
- '@plugin.manager.mail'
- '@automatic_updates.status_check_mailer'
- '@state'
- '@config.factory'
- '@package_manager.path_locator'
- '@package_manager.beginner'
- '@package_manager.stager'
- '@package_manager.committer'
- '@file_system'
- '@event_dispatcher'
- '@tempstore.shared'
- '@datetime.time'
- '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface'
- '@package_manager.failure_marker'
Drupal\automatic_updates\UpdateStage: '@automatic_updates.update_stage'
automatic_updates.cron_update_stage:
class: Drupal\automatic_updates\CronUpdateStage
calls:
- ['setLogger', ['@logger.channel.automatic_updates']]
Drupal\automatic_updates\CronUpdateStage: '@automatic_updates.cron_update_stage'
automatic_updates.requested_update_validator:
class: Drupal\automatic_updates\Validator\RequestedUpdateValidator
arguments:
- '@string_translation'
tags:
- { name: event_subscriber }
automatic_updates.staged_projects_validator:
class: Drupal\automatic_updates\Validator\StagedProjectsValidator
arguments:
- '@string_translation'
tags:
- { name: event_subscriber }
Drupal\automatic_updates\Validator\StagedProjectsValidator: '@automatic_updates.staged_projects_validator'
automatic_updates.release_chooser:
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:
- '@config.factory'
- '@module_handler'
- '@state'
- '@datetime.time'
- '@string_translation'
- '@automatic_updates.cron_updater'
- '@lock'
$lock: '@lock'
tags:
- { name: event_subscriber }
automatic_updates.validator.staged_database_updates:
class: Drupal\automatic_updates\Validator\StagedDatabaseUpdateValidator
arguments:
- '@package_manager.validator.staged_database_updates'
- '@string_translation'
tags:
- { name: event_subscriber }
automatic_updates.validator.version_policy:
class: Drupal\automatic_updates\Validator\VersionPolicyValidator
arguments:
- '@class_resolver'
tags:
- { name: event_subscriber }
automatic_updates.config_subscriber:
class: Drupal\automatic_updates\EventSubscriber\ConfigSubscriber
arguments:
- '@automatic_updates.status_checker'
tags:
- { name: event_subscriber }
Drupal\automatic_updates\Validator\VersionPolicyValidator: '@automatic_updates.validator.version_policy'
automatic_updates.validator.scaffold_file_permissions:
class: Drupal\automatic_updates\Validator\ScaffoldFilePermissionsValidator
arguments:
- '@package_manager.path_locator'
tags:
- { name: event_subscriber }
Drupal\automatic_updates\Validator\ScaffoldFilePermissionsValidator: '@automatic_updates.validator.scaffold_file_permissions'
automatic_updates.validator.cron_server:
class: Drupal\automatic_updates\Validator\CronServerValidator
arguments:
- '@request_stack'
- '@config.factory'
- '@module_handler'
tags:
- { name: event_subscriber }
logger.channel.automatic_updates:
......
name: 'Automatic Updates Extensions'
type: module
description: 'Allows updates to themes and modules'
core_version_requirement: ^9.3 || ^10
core_version_requirement: ^9.7 || ^10
lifecycle: experimental
dependencies:
- drupal:automatic_updates
services:
automatic_updates_extensions.updater:
class: Drupal\automatic_updates_extensions\ExtensionUpdater
arguments:
- '@config.factory'
- '@package_manager.path_locator'
- '@package_manager.beginner'
- '@package_manager.stager'
- '@package_manager.committer'
- '@file_system'
- '@event_dispatcher'
- '@tempstore.shared'
- '@datetime.time'
- '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface'
- '@package_manager.failure_marker'
_defaults:
autowire: true
automatic_updates_extensions.update_stage:
class: Drupal\automatic_updates_extensions\ExtensionUpdateStage
Drupal\automatic_updates_extensions\ExtensionUpdateStage: '@automatic_updates_extensions.update_stage'
automatic_updates_extensions.validator.target_release:
class: Drupal\automatic_updates_extensions\Validator\UpdateReleaseValidator
tags:
......
......@@ -5,7 +5,6 @@ declare(strict_types = 1);
namespace Drupal\automatic_updates_extensions;
use Drupal\Core\Url;
use Drupal\package_manager\Exception\StageValidationException;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
......@@ -25,13 +24,13 @@ final class BatchProcessor {
public const STAGE_ID_SESSION_KEY = '_automatic_updates_extensions_stage_id';
/**
* Gets the updater service.
* Gets the update stage service.
*
* @return \Drupal\automatic_updates_extensions\ExtensionUpdater
* The updater service.
* @return \Drupal\automatic_updates_extensions\ExtensionUpdateStage
* The update stage service.
*/
protected static function getUpdater(): ExtensionUpdater {
return \Drupal::service('automatic_updates_extensions.updater');
protected static function getStage(): ExtensionUpdateStage {
return \Drupal::service('automatic_updates_extensions.update_stage');
}
/**
......@@ -47,39 +46,23 @@ final class BatchProcessor {
* have been recorded.
*/
protected static function handleException(\Throwable $error, array &$context): void {
$error_messages = [
$error->getMessage(),
];
if ($error instanceof StageValidationException) {
foreach ($error->getResults() as $result) {
$messages = $result->getMessages();
if (count($messages) > 1) {
array_unshift($messages, $result->getSummary());
}
$error_messages = array_merge($error_messages, $messages);
}
}
foreach ($error_messages as $error_message) {
$context['results']['errors'][] = $error_message;
}
$context['results']['errors'][] = $error->getMessage();
throw $error;
}
/**
* Calls the updater's begin() method.
* Calls the update stage's begin() method.
*
* @param string[] $project_versions
* The project versions to be staged in the update, keyed by package name.
* @param array $context
* The current context of the batch job.
*
* @see \Drupal\automatic_updates_extensions\ExtensionUpdater::begin()
* @see \Drupal\automatic_updates_extensions\ExtensionUpdateStage::begin()
*/
public static function begin(array $project_versions, array &$context): void {
try {
$stage_id = static::getUpdater()->begin($project_versions);
$stage_id = static::getStage()->begin($project_versions);
\Drupal::service('session')->set(static::STAGE_ID_SESSION_KEY, $stage_id);
}
catch (\Throwable $e) {
......@@ -88,17 +71,17 @@ final class BatchProcessor {
}
/**
* Calls the updater's stageVersions() method.
* Calls the update stage's stage() method.
*
* @param array $context
* The current context of the batch job.
*
* @see \Drupal\automatic_updates\Updater::stage()
* @see \Drupal\automatic_updates\UpdateStage::stage()
*/
public static function stage(array &$context): void {
$stage_id = \Drupal::service('session')->get(static::STAGE_ID_SESSION_KEY);
try {
$stage_id = \Drupal::service('session')->get(static::STAGE_ID_SESSION_KEY);
static::getUpdater()->claim($stage_id)->stage();
static::getStage()->claim($stage_id)->stage();
}
catch (\Throwable $e) {
static::clean($stage_id, $context);
......@@ -107,18 +90,18 @@ final class BatchProcessor {
}
/**
* Calls the updater's commit() method.
* Calls the update stage's apply() method.
*
* @param string $stage_id
* The stage ID.
* @param array $context
* The current context of the batch job.
*
* @see \Drupal\automatic_updates\Updater::apply()
* @see \Drupal\automatic_updates_extensions\ExtensionUpdateStage::apply()
*/
public static function commit(string $stage_id, array &$context): void {
try {
static::getUpdater()->claim($stage_id)->apply();
static::getStage()->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
......@@ -135,18 +118,18 @@ final class BatchProcessor {
}
/**
* Calls the updater's postApply() method.
* Calls the update stage's postApply() method.
*
* @param string $stage_id
* The stage ID.
* @param array $context
* The current context of the batch job.
*
* @see \Drupal\automatic_updates\Updater::postApply()
* @see \Drupal\automatic_updates\UpdateStage::postApply()
*/
public static function postApply(string $stage_id, array &$context): void {
try {
static::getUpdater()->claim($stage_id)->postApply();
static::getStage()->claim($stage_id)->postApply();
}
catch (\Throwable $e) {
static::handleException($e, $context);
......@@ -154,18 +137,18 @@ final class BatchProcessor {
}
/**
* Calls the updater's clean() method.
* Calls the update stage's destroy() method.
*
* @param string $stage_id
* The stage ID.
* @param array $context
* The current context of the batch job.
*
* @see \Drupal\automatic_updates\Updater::clean()
* @see \Drupal\automatic_updates_extensions\ExtensionUpdateStage::destroy()
*/
public static function clean(string $stage_id, array &$context): void {
try {
static::getUpdater()->claim($stage_id)->destroy();
static::getStage()->claim($stage_id)->destroy();
}
catch (\Throwable $e) {
static::handleException($e, $context);
......
......@@ -4,20 +4,15 @@ declare(strict_types = 1);
namespace Drupal\automatic_updates_extensions;
use Drupal\automatic_updates\Exception\UpdateException;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\package_manager\Exception\ApplyFailedException;
use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\FailureMarker;
use Drupal\package_manager\LegacyVersionUtility;
use Drupal\package_manager\Event\StageEvent;
use Drupal\package_manager\Exception\StageValidationException;
use Drupal\package_manager\PathLocator;
use Drupal\package_manager\Stage;
use Drupal\package_manager\UnusedConfigFactory;
use Drupal\package_manager\StageBase;
use PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface;
use PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface;
use PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface;
......@@ -31,15 +26,48 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
* This class is an internal part of the module's update handling and
* should not be used by external code.
*/
class ExtensionUpdater extends Stage {
class ExtensionUpdateStage extends StageBase {
/**
* {@inheritdoc}
* Constructs a new ExtensionUpdateStage object.
*
* @todo Remove this in https://www.drupal.org/i/3303167
* @param \Drupal\package_manager\ComposerInspector $composerInspector
* The Composer inspector service.
* @param \Drupal\package_manager\PathLocator $pathLocator
* The path locator service.
* @param \PhpTuf\ComposerStager\Domain\Core\Beginner\BeginnerInterface $beginner
* The beginner service.
* @param \PhpTuf\ComposerStager\Domain\Core\Stager\StagerInterface $stager
* The stager service.
* @param \PhpTuf\ComposerStager\Domain\Core\Committer\CommitterInterface $committer
* The committer service.
* @param \Drupal\Core\File\FileSystemInterface $fileSystem
* The file system service.
* @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $eventDispatcher
* The event dispatcher service.
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $tempStoreFactory
* The shared tempstore factory.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
* @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $pathFactory
* The path factory service.
* @param \Drupal\package_manager\FailureMarker $failureMarker
* The failure marker service.
*/
public function __construct(ConfigFactoryInterface $config_factory, PathLocator $path_locator, BeginnerInterface $beginner, StagerInterface $stager, CommitterInterface $committer, FileSystemInterface $file_system, EventDispatcherInterface $event_dispatcher, SharedTempStoreFactory $temp_store_factory, TimeInterface $time, PathFactoryInterface $path_factory = NULL, FailureMarker $failure_marker = NULL) {
parent::__construct(new UnusedConfigFactory(), $path_locator, $beginner, $stager, $committer, $file_system, $event_dispatcher, $temp_store_factory, $time, $path_factory, $failure_marker);
public function __construct(
protected readonly ComposerInspector $composerInspector,
PathLocator $pathLocator,
BeginnerInterface $beginner,
StagerInterface $stager,
CommitterInterface $committer,
FileSystemInterface $fileSystem,
EventDispatcherInterface $eventDispatcher,
SharedTempStoreFactory $tempStoreFactory,
TimeInterface $time,
PathFactoryInterface $pathFactory,
FailureMarker $failureMarker,
) {
parent::__construct($pathLocator, $beginner, $stager, $committer, $fileSystem, $eventDispatcher, $tempStoreFactory, $time, $pathFactory, $failureMarker);
}
/**
......@@ -58,29 +86,27 @@ class ExtensionUpdater extends Stage {
if (empty($project_versions)) {
throw new \InvalidArgumentException("No projects to begin the update");
}
$composer = $this->getActiveComposer();
$package_versions = [
'production' => [],
'dev' => [],
];
$require_dev = $composer->getComposer()
->getPackage()
->getDevRequires();
$installed_packages = $composer->getInstalledPackages();
$project_root = $this->pathLocator->getProjectRoot();
$info = $this->composerInspector->getRootPackageInfo($project_root);
$installed_packages = $this->composerInspector->getInstalledPackagesList($project_root);
foreach ($project_versions as $project_name => $version) {
$package = $composer->getPackageForProject($project_name);
$package = $installed_packages->getPackageByDrupalProjectName($project_name);
if (empty($package)) {
throw new \InvalidArgumentException("The project $project_name is not a Drupal project known to Composer and cannot be updated.");
}
// We don't support updating install profiles.
if ($installed_packages[$package]->getType() === 'drupal-profile') {
if ($package->type === 'drupal-profile') {
throw new \InvalidArgumentException("The project $project_name cannot be updated because updating install profiles is not supported.");
}
$group = array_key_exists($package, $require_dev) ? 'dev' : 'production';
$package_versions[$group][$package] = LegacyVersionUtility::convertToSemanticVersion($version);
$group = isset($info['devRequires'][$package->name]) ? 'dev' : 'production';
$package_versions[$group][$package->name] = LegacyVersionUtility::convertToSemanticVersion($version);
}
// Ensure that package versions are available to pre-create event
......@@ -123,30 +149,6 @@ class ExtensionUpdater extends Stage {
$this->require($versions['production'], $versions['dev']);
}
/**
* {@inheritdoc}
*/
protected function dispatch(StageEvent $event, callable $on_error = NULL): void {
try {
parent::dispatch($event, $on_error);
}
catch (StageValidationException $e) {
throw new UpdateException($e->getResults(), $e->getMessage(), $e->getCode(), $e);
}
}
/**
* {@inheritdoc}
*/
public function apply(?int $timeout = 600): void {
try {
parent::apply($timeout);
}
catch (ApplyFailedException $exception) {
throw new UpdateException([], 'The update operation failed to apply. The update may have been partially applied. It is recommended that the site be restored from a code backup.', $exception->getCode(), $exception);
}
}
/**
* {@inheritdoc}
*/
......
......@@ -5,12 +5,14 @@ declare(strict_types = 1);
namespace Drupal\automatic_updates_extensions\Form;
use Drupal\automatic_updates\Form\UpdateFormBase;
use Drupal\package_manager\Exception\ApplyFailedException;
use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\Exception\StageFailureMarkerException;
use Drupal\package_manager\PathLocator;
use Drupal\package_manager\ProjectInfo;
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\automatic_updates_extensions\ExtensionUpdateStage;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Form\FormStateInterface;
......@@ -32,64 +34,37 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*/
final class UpdateReady extends UpdateFormBase {
/**
* The updater service.
*
* @var \Drupal\automatic_updates_extensions\ExtensionUpdater
*/
protected $updater;
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The module list service.
*
* @var \Drupal\Core\Extension\ModuleExtensionList
*/
protected $moduleList;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* The event dispatcher.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* Constructs a new UpdateReady object.
*
* @param \Drupal\automatic_updates_extensions\ExtensionUpdater $updater
* The updater service.
* @param \Drupal\automatic_updates_extensions\ExtensionUpdateStage $stage
* The update stage service.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service.
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Drupal\Core\Extension\ModuleExtensionList $module_list
* @param \Drupal\Core\Extension\ModuleExtensionList $moduleList
* The module list service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
* Event dispatcher service.
* @param \Drupal\package_manager\ComposerInspector $composerInspector
* The Composer inspector service.
* @param \Drupal\package_manager\PathLocator $pathLocator
* The path locator service.
*/
public function __construct(ExtensionUpdater $updater, MessengerInterface $messenger, StateInterface $state, ModuleExtensionList $module_list, RendererInterface $renderer, EventDispatcherInterface $event_dispatcher) {
$this->updater = $updater;
public function __construct(
private readonly ExtensionUpdateStage $stage,
MessengerInterface $messenger,
private readonly StateInterface $state,
private readonly ModuleExtensionList $moduleList,
private readonly RendererInterface $renderer,
private readonly EventDispatcherInterface $eventDispatcher,
private readonly ComposerInspector $composerInspector,
private readonly PathLocator $pathLocator,
) {
$this->setMessenger($messenger);
$this->state = $state;
$this->moduleList = $module_list;
$this->renderer = $renderer;
$this->eventDispatcher = $event_dispatcher;
}
/**
......@@ -104,12 +79,14 @@ final class UpdateReady extends UpdateFormBase {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('automatic_updates_extensions.updater'),
$container->get('automatic_updates_extensions.update_stage'),
$container->get('messenger'),
$container->get('state'),
$container->get('extension.list.module'),
$container->get('renderer'),
$container->get('event_dispatcher')
$container->get('event_dispatcher'),
$container->get('package_manager.composer_inspector'),
$container->get('package_manager.path_locator')
);
}
......@@ -118,13 +95,13 @@ final class UpdateReady extends UpdateFormBase {
*/
public function buildForm(array $form, FormStateInterface $form_state, string $stage_id = NULL) {
try {
$this->updater->claim($stage_id);
$this->stage->claim($stage_id);
}
catch (StageOwnershipException $e) {
catch (StageOwnershipException) {
$this->messenger()->addError($this->t('Cannot continue the update because another Composer operation is currently in progress.'));
return $form;
}
catch (ApplyFailedException $e) {
catch (StageFailureMarkerException $e) {
$this->messenger()->addError($e->getMessage());
return $form;
}
......@@ -167,7 +144,7 @@ final class UpdateReady extends UpdateFormBase {
// Don't run the status checks once the form has been submitted.
if (!$form_state->getUserInput()) {
$results = $this->runStatusCheck($this->updater, $this->eventDispatcher);
$results = $this->runStatusCheck($this->stage, $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
......@@ -214,7 +191,7 @@ final class UpdateReady extends UpdateFormBase {
*/
public function cancel(array &$form, FormStateInterface $form_state): void {
try {
$this->updater->destroy();
$this->stage->destroy();
$this->messenger()->addStatus($this->t('The update was successfully cancelled.'));
$form_state->setRedirect('automatic_updates_extensions.report_update');
}
......@@ -231,17 +208,16 @@ final class UpdateReady extends UpdateFormBase {
*/
private function showUpdates(): array {
// Get packages that were updated in the stage directory.
$active = $this->updater->getActiveComposer();
$staged = $this->updater->getStageComposer();
$updated_packages = $staged->getPackagesWithDifferentVersionsIn($active);
$installed_packages = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot());
$staged_packages = $this->composerInspector->getInstalledPackagesList($this->stage->getStageDirectory());
$updated_packages = $staged_packages->getPackagesWithDifferentVersionsIn($installed_packages);
// Build a list of package names that were updated by user request.
$updated_by_request = [];
foreach ($this->updater->getPackageVersions() as $group) {
foreach ($this->stage->getPackageVersions() as $group) {
$updated_by_request = array_merge($updated_by_request, array_keys($group));
}
$installed_packages = $active->getInstalledPackages();
$updated_by_request_info = [];
$updated_project_info = [];
$supported_package_types = ['drupal-module', 'drupal-theme'];
......@@ -250,17 +226,17 @@ final class UpdateReady extends UpdateFormBase {
// updated.
foreach ($updated_packages as $name => $updated_package) {
// Ignore anything that isn't a module or a theme.
if (!in_array($updated_package->getType(), $supported_package_types, TRUE)) {
if (!in_array($updated_package->type, $supported_package_types, TRUE)) {
continue;
}
$updated_project_info[$name] = [
'title' => $this->getProjectTitle($updated_package->getName()),
'installed_version' => $installed_packages[$name]->getPrettyVersion(),
'updated_version' => $updated_package->getPrettyVersion(),
'title' => $this->getProjectTitle($updated_package->name),
'installed_version' => $installed_packages[$updated_package->name]->version,
'updated_version' => $updated_package->version,
];
}
foreach (array_keys($updated_packages) as $name) {
foreach ($updated_packages as $name => $updated_package) {
// Sort the updated packages into two groups: the ones that were updated
// at the request of the user, and the ones that got updated anyway
// (probably due to Composer's dependency resolution).
......
......@@ -6,15 +6,17 @@ namespace Drupal\automatic_updates_extensions\Form;
use Drupal\automatic_updates\Form\UpdateFormBase;
use Drupal\automatic_updates_extensions\BatchProcessor;
use Drupal\automatic_updates_extensions\ExtensionUpdater;
use Drupal\automatic_updates_extensions\ExtensionUpdateStage;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Url;
use Drupal\package_manager\Exception\ApplyFailedException;
use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\Exception\StageFailureMarkerException;
use Drupal\package_manager\FailureMarker;
use Drupal\package_manager\PathLocator;
use Drupal\package_manager\ProjectInfo;
use Drupal\package_manager\ValidationResult;
use Drupal\system\SystemManager;
......@@ -30,75 +32,48 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*/
final class UpdaterForm extends UpdateFormBase {
/**
* The extension updater service.
*
* @var \Drupal\automatic_updates_extensions\ExtensionUpdater
*/
private $extensionUpdater;
/**
* The event dispatcher service.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
private $eventDispatcher;
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
private $state;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
private $renderer;
/**
* Failure marker service.
*
* @var \Drupal\package_manager\FailureMarker
*/
private $failureMarker;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('automatic_updates_extensions.updater'),
$container->get('automatic_updates_extensions.update_stage'),
$container->get('event_dispatcher'),
$container->get('renderer'),
$container->get('state'),
$container->get('package_manager.failure_marker')
$container->get('package_manager.failure_marker'),
$container->get('package_manager.composer_inspector'),
$container->get('package_manager.path_locator')
);
}
/**
* Constructs a new UpdaterForm object.
*
* @param \Drupal\automatic_updates_extensions\ExtensionUpdater $extension_updater
* The extension updater service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* @param \Drupal\automatic_updates_extensions\ExtensionUpdateStage $stage
* The extension update stage service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
* The extension event dispatcher service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Drupal\package_manager\FailureMarker $failure_marker
* @param \Drupal\package_manager\FailureMarker $failureMarker
* The failure marker service.
* @param \Drupal\package_manager\ComposerInspector $composerInspector
* The Composer inspector service.
* @param \Drupal\package_manager\PathLocator $pathLocator
* The path locator service.
*/
public function __construct(ExtensionUpdater $extension_updater, EventDispatcherInterface $event_dispatcher, RendererInterface $renderer, StateInterface $state, FailureMarker $failure_marker) {
$this->extensionUpdater = $extension_updater;
$this->eventDispatcher = $event_dispatcher;
$this->renderer = $renderer;
$this->state = $state;
$this->failureMarker = $failure_marker;
}
public function __construct(
private readonly ExtensionUpdateStage $stage,
private readonly EventDispatcherInterface $eventDispatcher,
private readonly RendererInterface $renderer,
private readonly StateInterface $state,
private readonly FailureMarker $failureMarker,
private readonly ComposerInspector $composerInspector,
private readonly PathLocator $pathLocator,
) {}
/**
* {@inheritdoc}
......@@ -114,7 +89,7 @@ final class UpdaterForm extends UpdateFormBase {
try {
$this->failureMarker->assertNotExists();
}
catch (ApplyFailedException $e) {
catch (StageFailureMarkerException $e) {
$this->messenger()->addError($e->getMessage());
return $form;
}
......@@ -164,7 +139,7 @@ final class UpdaterForm extends UpdateFormBase {
$results = [];
}
else {
$results = $this->runStatusCheck($this->extensionUpdater, $this->eventDispatcher, TRUE);
$results = $this->runStatusCheck($this->stage, $this->eventDispatcher);
}
$this->displayResults($results, $this->renderer);
$security_level = ValidationResult::getOverallSeverity($results);
......@@ -191,7 +166,7 @@ final class UpdaterForm extends UpdateFormBase {
*/
protected function actions(FormStateInterface $form_state): array {
$actions = ['#type' => 'actions'];
if (!$this->extensionUpdater->isAvailable()) {
if (!$this->stage->isAvailable()) {
// If the form has been submitted do not display this error message
// because ::deleteExistingUpdate() may run on submit. The message will
// still be displayed on form build if needed.
......@@ -217,7 +192,7 @@ final class UpdaterForm extends UpdateFormBase {
* Submit function to delete an existing in-progress update.
*/
public function deleteExistingUpdate(): void {
$this->extensionUpdater->destroy(TRUE);
$this->stage->destroy(TRUE);
$this->messenger()->addMessage($this->t("Staged update deleted"));
}
......@@ -261,12 +236,13 @@ final class UpdaterForm extends UpdateFormBase {
$all_projects_data = update_calculate_project_data($available_updates);
$outdated_modules = [];
$installed_packages = array_keys($this->extensionUpdater->getActiveComposer()->getInstalledPackages());
$installed_packages = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot())
->getArrayCopy();
$non_supported_update_statuses = [];
foreach ($all_projects_data as $project_name => $project_data) {
if (in_array($project_data['project_type'], $supported_project_types, TRUE)) {
if ($project_data['status'] !== UpdateManagerInterface::CURRENT) {
if (!in_array("drupal/$project_name", $installed_packages, TRUE)) {
if (!array_key_exists("drupal/$project_name", $installed_packages)) {
$non_supported_update_statuses[] = $project_data['status'];
continue;
}
......
......@@ -4,8 +4,10 @@ declare(strict_types = 1);
namespace Drupal\automatic_updates_extensions\Validator;
use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\PathLocator;
use Drupal\package_manager\ProjectInfo;
use Drupal\automatic_updates_extensions\ExtensionUpdater;
use Drupal\automatic_updates_extensions\ExtensionUpdateStage;
use Drupal\package_manager\LegacyVersionUtility;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\package_manager\Event\PreCreateEvent;
......@@ -18,12 +20,26 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
* This class is an internal part of the module's update handling and
* should not be used by external code.
*
* @todo Remove this validator completely in https://www.drupal.org/i/3307369.
* @todo Decide if this validator can be removed completely in
* https://www.drupal.org/i/3351091.
*/
final class UpdateReleaseValidator implements EventSubscriberInterface {
use StringTranslationTrait;
/**
* Constructs an UpdateReleaseValidator 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
) {}
/**
* Checks if the given version of a project is supported.
*
......@@ -71,17 +87,18 @@ final class UpdateReleaseValidator implements EventSubscriberInterface {
* The event object.
*/
public function checkRelease(PreCreateEvent $event): void {
$stage = $event->getStage();
$stage = $event->stage;
// This check only works with Automatic Updates Extensions.
if (!$stage instanceof ExtensionUpdater) {
if (!$stage instanceof ExtensionUpdateStage) {
return;
}
$active_packages = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot());
$all_versions = $stage->getPackageVersions();
$messages = [];
foreach (['production', 'dev'] as $package_type) {
foreach ($all_versions[$package_type] as $package_name => $sematic_version) {
$project_name = $stage->getActiveComposer()->getProjectForPackage($package_name);
$project_name = $active_packages[$package_name]->getProjectName();
// If the version isn't in the list of installable releases, then it
// isn't secure and supported and the user should receive an error.
if (!$this->isSupportedRelease($project_name, $sematic_version)) {
......
{
"require": {
"drupal/core-recommended": "^9",
"drupal/my_module": "^9",
"drupal/contrib_profile1": "*"
},
"require-dev": {
"drupal/my_dev_module": "^9"
}
}
{
"packages": [
{
"name": "drupal/core-recommended",
"version": "9.8.0",
"require": {
"drupal/core": "9.8.0"
}
},
{
"name": "drupal/my_module",
"version": "9.8.0",
"type": "drupal-module"
},
{
"name": "drupal/contrib_profile1",
"version": "1.0.0",
"type": "drupal-profile"
},
{
"name": "drupal/semver_test",
"version": "1.0.0",
"type": "drupal-module"
},
{
"name": "drupal/aaa_update_test",
"version": "1.0.0",
"type": "drupal-module"
},
{
"name": "drupal/aaa_automatic_updates_test",
"version": "1.0.0",
"type": "drupal-module"
}
],
"packages-dev": [
{
"name": "drupal/my_dev_module",
"version": "9.8.1",
"type": "drupal-module"
}
]
}
{
"packages": [
{
"name": "drupal/core-recommended",
"version": "9.8.0",
"require": {
"drupal/core": "9.8.0"
}
},
{
"name": "drupal/core",
"version": "9.8.0",
"extra": {
"drupal-scaffold": {
"file-mapping": {}
}
}
},
{
"name": "drupal/my_module",
"version": "9.8.0",
"type": "drupal-module"
},
{
"name": "drupal/contrib_profile1",
"version": "1.0.0",
"type": "drupal-profile"
},
{
"name": "drupal/my_dev_module",
"version": "9.8.1",
"type": "drupal-module"
},
{
"name": "drupal/semver_test",
"version": "1.0.0",
"type": "drupal-module"
},
{
"name": "drupal/aaa_update_test",
"version": "1.0.0",
"type": "drupal-module"
},
{
"name": "drupal/aaa_automatic_updates_test",
"version": "1.0.0",
"type": "drupal-module"
}
],
"dev": true,
"dev-package-names": [
"drupal/my_dev_module"
]
}
<?php
/**
* @file
*/
$projects_dir = __DIR__ . '/../../web/projects';
return [
'versions' => [
'drupal/my_module' => [
'type' => 'drupal-module',
'install_path' => $projects_dir . '/my_module',
],
'drupal/contrib_profile1' => [
'type' => 'drupal-profile',
'install_path' => __DIR__ . '/../../web/profiles/contrib_profile1',
],
'drupal/my_dev_module' => [
'type' => 'drupal-module',
'install_path' => $projects_dir . '/my_dev_module',
],
'drupal/semver_test' => [
'type' => 'drupal-module',
'install_path' => $projects_dir . '/semver_test',
],
'drupal/aaa_update_test' => [
'type' => 'drupal-module',
'install_path' => $projects_dir . '/aaa_update_test',
],
'drupal/aaa_automatic_updates_test' => [
'type' => 'drupal-module',
'install_path' => $projects_dir . '/aaa_automatic_updates_test',
],
],
];