-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
-
310
-
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
-
358
-
359
-
360
-
361
-
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
-
380
-
381
-
382
-
383
-
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
-
392
-
393
-
394
-
395
-
396
-
397
-
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
-
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
-
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
-
442
-
443
-
444
-
445
-
446
-
447
-
448
-
449
-
450
-
451
-
452
-
453
-
454
-
455
-
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
-
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
-
484
-
485
-
486
-
487
-
488
-
489
-
490
-
491
-
492
-
493
-
494
-
495
-
496
-
497
-
498
-
499
-
500
-
501
-
502
-
503
-
504
-
505
-
506
-
507
-
508
-
509
-
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519
-
520
-
521
-
522
-
523
-
524
-
525
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-
547
-
548
-
549
-
550
-
551
-
552
-
553
-
554
-
555
-
556
-
557
-
558
-
559
-
560
-
561
-
562
-
563
-
564
-
565
-
566
-
567
-
568
-
569
-
570
-
571
-
572
-
573
-
574
-
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
-
595
-
596
-
597
-
598
-
599
-
600
-
601
-
602
-
603
-
604
-
605
-
606
-
607
-
608
-
609
-
610
-
611
-
612
-
613
-
614
-
615
-
616
-
617
-
618
-
619
-
620
-
621
-
622
-
623
-
624
-
625
-
626
-
627
-
628
-
629
-
630
-
631
-
632
-
633
-
634
-
635
-
636
-
637
-
638
-
639
-
640
-
641
-
642
-
643
-
644
-
645
-
646
-
647
-
648
-
649
-
650
-
651
-
652
-
653
-
654
-
655
-
656
-
657
-
658
-
659
-
660
-
661
-
662
-
663
-
664
-
665
-
666
-
667
-
668
-
669
-
670
-
671
-
672
-
673
-
674
-
675
-
676
-
677
-
678
-
679
-
680
-
681
-
682
-
683
-
684
-
685
-
686
-
687
-
688
-
689
-
690
-
691
-
692
-
693
-
694
-
695
-
696
-
697
-
698
-
699
-
700
-
701
-
702
-
703
-
704
-
705
-
706
-
707
-
708
-
709
-
710
-
711
-
712
-
713
-
714
-
715
-
716
-
717
-
718
-
719
-
720
-
721
-
722
-
723
-
724
-
725
-
726
-
727
-
728
-
729
-
730
-
731
-
732
-
733
-
734
-
735
-
736
-
737
-
738
-
739
-
740
-
741
-
742
-
743
-
744
-
745
-
746
-
747
-
748
-
749
-
750
-
751
-
752
-
753
-
754
-
755
-
756
-
757
-
758
-
759
-
760
-
761
-
762
-
763
-
764
-
765
-
766
-
767
-
768
-
769
-
770
-
771
-
772
-
773
-
774
-
775
-
776
-
777
-
778
-
779
-
780
-
781
-
782
-
783
-
784
-
785
-
786
-
787
-
788
-
789
-
790
-
791
-
792
-
793
-
794
-
795
-
796
-
797
-
798
-
799
-
800
-
801
-
802
-
803
-
804
-
805
-
806
-
807
-
808
-
809
-
810
-
811
-
812
-
813
-
814
-
815
-
816
-
817
-
818
-
819
-
820
-
821
-
822
-
823
-
824
-
825
-
826
-
827
-
828
-
829
-
830
-
831
-
832
-
833
-
834
-
835
-
836
-
837
-
838
-
839
-
840
-
841
-
842
-
843
-
844
-
845
-
846
-
847
-
848
-
849
-
850
-
851
-
852
-
853
-
854
-
855
-
856
-
857
-
858
-
859
-
860
-
861
-
862
-
863
-
864
-
865
-
866
-
867
-
868
-
869
-
870
-
871
-
872
-
873
-
874
-
875
-
876
-
877
-
878
-
879
-
880
-
881
-
882
-
883
-
884
-
885
-
886
-
887
-
888
-
889
-
890
-
891
-
892
-
893
-
894
-
895
-
896
-
897
-
898
-
899
-
900
-
901
-
902
-
903
-
904
-
905
-
906
-
907
-
908
-
909
-
910
-
911
-
912
-
913
-
914
-
915
-
916
-
917
-
918
-
919
-
920
-
921
-
922
-
923
-
924
-
925
-
926
-
927
-
928
-
929
-
930
-
931
-
932
-
933
-
934
-
935
-
936
-
937
-
938
-
939
-
940
-
941
-
942
-
943
-
944
-
945
-
946
-
947
-
948
-
949
-
950
-
951
-
952
-
953
-
954
-
955
-
956
-
957
-
958
-
959
-
960
-
961
-
962
-
963
-
964
-
965
-
966
-
967
-
968
-
969
-
970
-
971
-
972
-
973
-
974
-
975
-
976
-
977
-
978
-
979
-
980
-
981
-
982
-
983
-
984
-
985
-
986
-
987
-
988
-
989
-
990
-
991
-
992
-
993
-
994
-
995
-
996
-
997
-
998
-
999
-
1000
-
1001
-
1002
-
1003
-
1004
-
1005
-
1006
-
1007
-
1008
-
1009
-
1010
-
1011
-
1012
-
1013
-
1014
-
1015
-
1016
-
1017
-
1018
-
1019
-
1020
-
1021
-
1022
-
1023
-
1024
-
1025
-
1026
-
1027
-
1028
-
1029
-
1030
-
1031
-
1032
-
1033
-
1034
-
1035
-
1036
-
1037
-
1038
-
1039
-
1040
-
1041
-
1042
-
1043
-
1044
-
1045
-
1046
-
1047
-
1048
-
1049
-
1050
-
1051
-
1052
-
1053
-
1054
-
1055
-
1056
-
1057
-
1058
-
1059
-
1060
-
1061
-
1062
-
1063
-
1064
-
1065
-
1066
-
1067
-
1068
-
1069
-
1070
-
1071
-
1072
-
1073
-
1074
-
1075
-
1076
-
1077
-
1078
-
1079
-
1080
-
1081
-
1082
-
1083
-
1084
-
1085
-
1086
-
1087
-
1088
-
1089
-
1090
-
1091
-
1092
-
1093
-
1094
-
1095
-
1096
-
1097
-
1098
-
1099
-
1100
-
1101
-
1102
-
1103
-
1104
-
1105
-
1106
-
1107
-
1108
-
1109
-
1110
-
1111
-
1112
-
1113
-
1114
-
1115
-
1116
-
1117
-
1118
-
1119
-
1120
-
1121
-
1122
-
1123
-
1124
-
1125
-
1126
-
1127
-
1128
-
1129
-
1130
-
1131
-
1132
-
1133
-
1134
-
1135
-
1136
-
1137
-
1138
-
1139
-
1140
-
1141
-
1142
-
1143
-
1144
-
1145
-
1146
-
1147
-
1148
-
1149
-
1150
-
1151
-
1152
-
1153
-
1154
-
1155
-
1156
-
1157
-
1158
-
1159
-
1160
-
1161
-
1162
-
1163
-
1164
-
1165
-
1166
-
1167
-
1168
-
1169
-
1170
-
1171
-
1172
-
1173
-
1174
-
1175
-
1176
-
1177
-
1178
-
1179
-
1180
-
1181
-
1182
-
1183
-
1184
-
1185
-
1186
-
1187
-
1188
-
1189
-
1190
-
1191
-
1192
-
1193
-
1194
-
1195
-
1196
-
1197
-
1198
-
1199
-
1200
-
1201
-
1202
-
1203
-
1204
-
1205
-
1206
-
1207
-
1208
-
1209
-
1210
-
1211
-
1212
-
1213
-
1214
-
1215
-
1216
-
1217
-
1218
-
1219
-
1220
-
1221
-
1222
-
1223
-
1224
-
1225
-
1226
-
1227
-
1228
-
1229
-
1230
-
1231
-
1232
-
1233
-
1234
-
1235
-
1236
-
1237
-
1238
-
1239
-
1240
-
1241
-
1242
-
1243
-
1244
-
1245
-
1246
-
1247
-
1248
-
1249
-
1250
-
1251
-
1252
-
1253
-
1254
-
1255
-
1256
-
1257
-
1258
-
1259
-
1260
-
1261
-
1262
-
1263
-
1264
-
1265
-
1266
-
1267
-
1268
-
1269
-
1270
-
1271
-
1272
-
1273
-
1274
-
1275
-
1276
-
1277
-
1278
-
1279
-
1280
-
1281
-
1282
-
1283
-
1284
-
1285
-
1286
-
1287
-
1288
-
1289
-
1290
-
1291
-
1292
-
1293
-
1294
-
1295
-
1296
-
1297
-
1298
-
1299
-
1300
-
1301
-
1302
-
1303
-
1304
-
1305
-
1306
-
1307
-
1308
-
1309
-
1310
-
1311
-
1312
-
1313
-
1314
-
1315
-
1316
-
1317
-
1318
-
1319
-
1320
-
1321
-
1322
-
1323
-
1324
-
1325
-
1326
-
1327
-
1328
-
1329
-
1330
-
1331
-
1332
-
1333
-
1334
-
1335
-
1336
-
1337
-
1338
-
1339
-
1340
-
1341
-
1342
-
1343
-
1344
-
1345
-
1346
-
1347
-
1348
-
1349
-
1350
-
1351
-
1352
-
1353
-
1354
-
1355
-
1356
-
1357
-
1358
-
1359
-
1360
-
1361
-
1362
-
1363
-
1364
-
1365
-
1366
-
1367
-
1368
-
1369
-
1370
-
1371
-
1372
-
1373
-
1374
-
1375
-
1376
-
1377
-
1378
-
1379
-
1380
-
1381
-
1382
-
1383
-
1384
-
1385
-
1386
-
1387
-
1388
-
1389
-
1390
-
1391
-
1392
-
1393
-
1394
-
1395
-
1396
-
1397
-
1398
-
1399
-
1400
-
1401
-
1402
-
1403
-
1404
-
1405
-
1406
-
1407
-
1408
-
1409
-
1410
-
1411
-
1412
-
1413
-
1414
-
1415
-
1416
-
1417
-
1418
-
1419
-
1420
-
1421
-
1422
-
1423
-
1424
-
1425
-
1426
-
1427
-
1428
-
1429
-
1430
-
1431
-
1432
-
1433
-
1434
-
1435
-
1436
-
1437
-
1438
-
1439
-
1440
-
1441
-
1442
-
1443
-
1444
-
1445
-
1446
-
1447
-
1448
-
1449
-
1450
-
1451
-
1452
-
1453
-
1454
-
1455
-
1456
-
1457
-
1458
-
1459
-
1460
-
1461
-
1462
-
1463
-
1464
-
1465
-
1466
-
1467
-
1468
-
1469
-
1470
-
1471
-
1472
-
1473
-
1474
-
1475
-
1476
-
1477
-
1478
-
1479
-
1480
-
1481
-
1482
-
1483
-
1484
-
1485
-
1486
-
1487
-
1488
-
1489
-
1490
-
1491
-
1492
-
1493
-
1494
-
1495
-
1496
-
1497
-
1498
-
1499
-
1500
-
1501
-
1502
-
1503
-
1504
-
1505
-
1506
-
1507
-
1508
-
1509
-
1510
-
1511
-
1512
-
1513
-
1514
-
1515
-
1516
-
1517
-
1518
-
1519
-
1520
-
1521
-
1522
-
1523
-
1524
-
1525
-
1526
-
1527
-
1528
-
1529
-
1530
-
1531
-
1532
-
1533
-
1534
-
1535
-
1536
-
1537
-
1538
-
1539
-
1540
-
1541
-
1542
-
1543
-
1544
-
1545
-
1546
-
1547
-
1548
-
1549
-
1550
-
1551
-
1552
-
1553
-
1554
-
1555
-
1556
-
1557
-
1558
-
1559
-
1560
-
1561
-
1562
-
1563
-
1564
-
1565
-
1566
-
1567
-
1568
-
1569
-
1570
-
1571
-
1572
-
1573
-
1574
-
1575
-
1576
-
1577
-
1578
-
1579
-
1580
-
1581
-
1582
-
1583
-
1584
-
1585
-
1586
-
1587
-
1588
-
1589
-
1590
-
1591
-
1592
-
1593
-
1594
-
1595
-
1596
-
1597
-
1598
-
1599
-
1600
-
1601
-
1602
-
1603
-
1604
-
1605
-
1606
-
1607
-
1608
-
1609
-
1610
-
1611
-
1612
-
1613
-
1614
-
1615
-
1616
-
1617
-
1618
-
1619
-
1620
-
1621
-
1622
-
1623
-
1624
-
1625
-
1626
-
1627
-
1628
-
1629
-
1630
-
1631
-
1632
-
1633
-
1634
-
1635
-
1636
-
1637
-
1638
-
1639
-
1640
-
1641
-
1642
-
1643
-
1644
-
1645
-
1646
-
1647
-
1648
-
1649
-
1650
-
1651
-
1652
-
1653
-
1654
-
1655
-
1656
-
1657
-
1658
-
1659
-
1660
-
1661
-
1662
-
1663
-
1664
-
1665
-
1666
-
1667
-
1668
-
1669
-
1670
-
1671
-
1672
-
1673
-
1674
-
1675
-
1676
-
1677
-
1678
-
1679
-
1680
-
1681
-
1682
-
1683
-
1684
-
1685
-
1686
-
1687
-
1688
-
1689
-
1690
-
1691
-
1692
-
1693
-
1694
-
1695
-
1696
-
1697
-
1698
-
1699
-
1700
-
1701
-
1702
-
1703
-
1704
-
1705
-
1706
-
1707
-
1708
-
1709
-
1710
-
1711
-
1712
-
1713
-
1714
-
1715
-
1716
-
1717
-
1718
-
1719
-
1720
-
1721
-
1722
-
1723
-
1724
-
1725
-
1726
-
1727
-
1728
-
1729
-
1730
-
1731
-
1732
-
1733
-
1734
-
1735
-
1736
-
1737
-
1738
-
1739
-
1740
-
1741
-
1742
-
1743
-
1744
-
1745
-
1746
-
1747
-
1748
-
1749
-
1750
-
1751
-
1752
-
1753
-
1754
-
1755
-
1756
-
1757
-
1758
-
1759
-
1760
-
1761
-
1762
-
1763
-
1764
-
1765
-
1766
-
1767
-
1768
-
1769
-
1770
-
1771
-
1772
-
1773
-
1774
-
1775
-
1776
-
1777
-
1778
-
1779
-
1780
-
1781
-
1782
-
1783
-
1784
-
1785
//
// Copyright 2021, Sander van Harmelen
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package gitlab
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"time"
)
// ProjectsService handles communication with the repositories related methods
// of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html
type ProjectsService struct {
client *Client
}
// Project represents a GitLab project.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html
type Project struct {
ID int `json:"id"`
Description string `json:"description"`
DefaultBranch string `json:"default_branch"`
Public bool `json:"public"`
Visibility VisibilityValue `json:"visibility"`
SSHURLToRepo string `json:"ssh_url_to_repo"`
HTTPURLToRepo string `json:"http_url_to_repo"`
WebURL string `json:"web_url"`
ReadmeURL string `json:"readme_url"`
TagList []string `json:"tag_list"`
Owner *User `json:"owner"`
Name string `json:"name"`
NameWithNamespace string `json:"name_with_namespace"`
Path string `json:"path"`
PathWithNamespace string `json:"path_with_namespace"`
IssuesEnabled bool `json:"issues_enabled"`
OpenIssuesCount int `json:"open_issues_count"`
MergeRequestsEnabled bool `json:"merge_requests_enabled"`
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
JobsEnabled bool `json:"jobs_enabled"`
WikiEnabled bool `json:"wiki_enabled"`
SnippetsEnabled bool `json:"snippets_enabled"`
ResolveOutdatedDiffDiscussions bool `json:"resolve_outdated_diff_discussions"`
ContainerExpirationPolicy *ContainerExpirationPolicy `json:"container_expiration_policy,omitempty"`
ContainerRegistryEnabled bool `json:"container_registry_enabled"`
CreatedAt *time.Time `json:"created_at,omitempty"`
LastActivityAt *time.Time `json:"last_activity_at,omitempty"`
CreatorID int `json:"creator_id"`
Namespace *ProjectNamespace `json:"namespace"`
ImportStatus string `json:"import_status"`
ImportError string `json:"import_error"`
Permissions *Permissions `json:"permissions"`
MarkedForDeletionAt *ISOTime `json:"marked_for_deletion_at"`
EmptyRepo bool `json:"empty_repo"`
Archived bool `json:"archived"`
AvatarURL string `json:"avatar_url"`
LicenseURL string `json:"license_url"`
License *ProjectLicense `json:"license"`
SharedRunnersEnabled bool `json:"shared_runners_enabled"`
ForksCount int `json:"forks_count"`
StarCount int `json:"star_count"`
RunnersToken string `json:"runners_token"`
PublicBuilds bool `json:"public_builds"`
AllowMergeOnSkippedPipeline bool `json:"allow_merge_on_skipped_pipeline"`
OnlyAllowMergeIfPipelineSucceeds bool `json:"only_allow_merge_if_pipeline_succeeds"`
OnlyAllowMergeIfAllDiscussionsAreResolved bool `json:"only_allow_merge_if_all_discussions_are_resolved"`
RemoveSourceBranchAfterMerge bool `json:"remove_source_branch_after_merge"`
LFSEnabled bool `json:"lfs_enabled"`
RequestAccessEnabled bool `json:"request_access_enabled"`
MergeMethod MergeMethodValue `json:"merge_method"`
ForkedFromProject *ForkParent `json:"forked_from_project"`
Mirror bool `json:"mirror"`
MirrorUserID int `json:"mirror_user_id"`
MirrorTriggerBuilds bool `json:"mirror_trigger_builds"`
OnlyMirrorProtectedBranches bool `json:"only_mirror_protected_branches"`
MirrorOverwritesDivergedBranches bool `json:"mirror_overwrites_diverged_branches"`
PackagesEnabled bool `json:"packages_enabled"`
ServiceDeskEnabled bool `json:"service_desk_enabled"`
ServiceDeskAddress string `json:"service_desk_address"`
IssuesAccessLevel AccessControlValue `json:"issues_access_level"`
RepositoryAccessLevel AccessControlValue `json:"repository_access_level"`
MergeRequestsAccessLevel AccessControlValue `json:"merge_requests_access_level"`
ForkingAccessLevel AccessControlValue `json:"forking_access_level"`
WikiAccessLevel AccessControlValue `json:"wiki_access_level"`
BuildsAccessLevel AccessControlValue `json:"builds_access_level"`
SnippetsAccessLevel AccessControlValue `json:"snippets_access_level"`
PagesAccessLevel AccessControlValue `json:"pages_access_level"`
OperationsAccessLevel AccessControlValue `json:"operations_access_level"`
AutocloseReferencedIssues bool `json:"autoclose_referenced_issues"`
SuggestionCommitMessage string `json:"suggestion_commit_message"`
CIForwardDeploymentEnabled bool `json:"ci_forward_deployment_enabled"`
SharedWithGroups []struct {
GroupID int `json:"group_id"`
GroupName string `json:"group_name"`
GroupAccessLevel int `json:"group_access_level"`
} `json:"shared_with_groups"`
Statistics *ProjectStatistics `json:"statistics"`
Links *Links `json:"_links,omitempty"`
CIConfigPath string `json:"ci_config_path"`
CIDefaultGitDepth int `json:"ci_default_git_depth"`
CustomAttributes []*CustomAttribute `json:"custom_attributes"`
ComplianceFrameworks []string `json:"compliance_frameworks"`
BuildCoverageRegex string `json:"build_coverage_regex"`
IssuesTemplate string `json:"issues_template"`
MergeRequestsTemplate string `json:"merge_requests_template"`
}
// BasicProject included in other service responses (such as todos).
type BasicProject struct {
ID int `json:"id"`
Description string `json:"description"`
Name string `json:"name"`
NameWithNamespace string `json:"name_with_namespace"`
Path string `json:"path"`
PathWithNamespace string `json:"path_with_namespace"`
CreatedAt *time.Time `json:"created_at"`
}
// ContainerExpirationPolicy represents the container expiration policy.
type ContainerExpirationPolicy struct {
Cadence string `json:"cadence"`
KeepN int `json:"keep_n"`
OlderThan string `json:"older_than"`
NameRegexDelete string `json:"name_regex_delete"`
NameRegexKeep string `json:"name_regex_keep"`
Enabled bool `json:"enabled"`
NextRunAt *time.Time `json:"next_run_at"`
}
// ForkParent represents the parent project when this is a fork.
type ForkParent struct {
HTTPURLToRepo string `json:"http_url_to_repo"`
ID int `json:"id"`
Name string `json:"name"`
NameWithNamespace string `json:"name_with_namespace"`
Path string `json:"path"`
PathWithNamespace string `json:"path_with_namespace"`
WebURL string `json:"web_url"`
}
// GroupAccess represents group access.
type GroupAccess struct {
AccessLevel AccessLevelValue `json:"access_level"`
NotificationLevel NotificationLevelValue `json:"notification_level"`
}
// Links represents a project web links for self, issues, merge_requests,
// repo_branches, labels, events, members.
type Links struct {
Self string `json:"self"`
Issues string `json:"issues"`
MergeRequests string `json:"merge_requests"`
RepoBranches string `json:"repo_branches"`
Labels string `json:"labels"`
Events string `json:"events"`
Members string `json:"members"`
}
// Permissions represents permissions.
type Permissions struct {
ProjectAccess *ProjectAccess `json:"project_access"`
GroupAccess *GroupAccess `json:"group_access"`
}
// ProjectAccess represents project access.
type ProjectAccess struct {
AccessLevel AccessLevelValue `json:"access_level"`
NotificationLevel NotificationLevelValue `json:"notification_level"`
}
// ProjectLicense represent the license for a project.
type ProjectLicense struct {
Key string `json:"key"`
Name string `json:"name"`
Nickname string `json:"nickname"`
HTMLURL string `json:"html_url"`
SourceURL string `json:"source_url"`
}
// ProjectNamespace represents a project namespace.
type ProjectNamespace struct {
ID int `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Kind string `json:"kind"`
FullPath string `json:"full_path"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
}
// ProjectStatistics represents a statistics record for a project.
type ProjectStatistics struct {
StorageStatistics
CommitCount int `json:"commit_count"`
}
// Repository represents a repository.
type Repository struct {
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL string `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
Visibility VisibilityValue `json:"visibility"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
}
// StorageStatistics represents a statistics record for a group or project.
type StorageStatistics struct {
StorageSize int64 `json:"storage_size"`
RepositorySize int64 `json:"repository_size"`
LfsObjectsSize int64 `json:"lfs_objects_size"`
JobArtifactsSize int64 `json:"job_artifacts_size"`
}
func (s Project) String() string {
return Stringify(s)
}
// ProjectApprovalRule represents a GitLab project approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-project-level-rules
type ProjectApprovalRule struct {
ID int `json:"id"`
Name string `json:"name"`
RuleType string `json:"rule_type"`
EligibleApprovers []*BasicUser `json:"eligible_approvers"`
ApprovalsRequired int `json:"approvals_required"`
Users []*BasicUser `json:"users"`
Groups []*Group `json:"groups"`
ContainsHiddenGroups bool `json:"contains_hidden_groups"`
ProtectedBranches []*ProtectedBranch `json:"protected_branches"`
}
func (s ProjectApprovalRule) String() string {
return Stringify(s)
}
// ListProjectsOptions represents the available ListProjects() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#list-projects
type ListProjectsOptions struct {
ListOptions
Archived *bool `url:"archived,omitempty" json:"archived,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
Search *string `url:"search,omitempty" json:"search,omitempty"`
SearchNamespaces *bool `url:"search_namespaces,omitempty" json:"search_namespaces,omitempty"`
Simple *bool `url:"simple,omitempty" json:"simple,omitempty"`
Owned *bool `url:"owned,omitempty" json:"owned,omitempty"`
Membership *bool `url:"membership,omitempty" json:"membership,omitempty"`
Starred *bool `url:"starred,omitempty" json:"starred,omitempty"`
Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"`
Topic *string `url:"topic,omitempty" json:"topic,omitempty"`
WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
WithIssuesEnabled *bool `url:"with_issues_enabled,omitempty" json:"with_issues_enabled,omitempty"`
WithMergeRequestsEnabled *bool `url:"with_merge_requests_enabled,omitempty" json:"with_merge_requests_enabled,omitempty"`
WithProgrammingLanguage *string `url:"with_programming_language,omitempty" json:"with_programming_language,omitempty"`
WikiChecksumFailed *bool `url:"wiki_checksum_failed,omitempty" json:"wiki_checksum_failed,omitempty"`
RepositoryChecksumFailed *bool `url:"repository_checksum_failed,omitempty" json:"repository_checksum_failed,omitempty"`
MinAccessLevel *AccessLevelValue `url:"min_access_level,omitempty" json:"min_access_level,omitempty"`
IDAfter *int `url:"id_after,omitempty" json:"id_after,omitempty"`
IDBefore *int `url:"id_before,omitempty" json:"id_before,omitempty"`
LastActivityAfter *time.Time `url:"last_activity_after,omitempty" json:"last_activity_after,omitempty"`
LastActivityBefore *time.Time `url:"last_activity_before,omitempty" json:"last_activity_before,omitempty"`
}
// ListProjects gets a list of projects accessible by the authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#list-projects
func (s *ProjectsService) ListProjects(opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) {
req, err := s.client.NewRequest(http.MethodGet, "projects", opt, options)
if err != nil {
return nil, nil, err
}
var p []*Project
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ListUserProjects gets a list of projects for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#list-user-projects
func (s *ProjectsService) ListUserProjects(uid interface{}, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) {
user, err := parseID(uid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("users/%s/projects", user)
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var p []*Project
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ProjectUser represents a GitLab project user.
type ProjectUser struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
State string `json:"state"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
}
// ListProjectUserOptions represents the available ListProjectsUsers() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#get-project-users
type ListProjectUserOptions struct {
ListOptions
Search *string `url:"search,omitempty" json:"search,omitempty"`
}
// ListProjectsUsers gets a list of users for the given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#get-project-users
func (s *ProjectsService) ListProjectsUsers(pid interface{}, opt *ListProjectUserOptions, options ...RequestOptionFunc) ([]*ProjectUser, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/users", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var p []*ProjectUser
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ProjectGroup represents a GitLab project group.
type ProjectGroup struct {
ID int `json:"id"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
WebURL string `json:"web_url"`
FullName string `json:"full_name"`
FullPath string `json:"full_path"`
}
// ListProjectGroupOptions represents the available ListProjectsGroups() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#list-a-projects-groups
type ListProjectGroupOptions struct {
ListOptions
Search *string `url:"search,omitempty" json:"search,omitempty"`
SkipGroups []int `url:"skip_groups,omitempty" json:"skip_groups,omitempty"`
WithShared *bool `url:"with_shared,omitempty" json:"with_shared,omitempty"`
SharedMinAccessLevel *AccessLevelValue `url:"shared_min_access_level,omitempty" json:"shared_min_access_level,omitempty"`
SharedVisiableOnly *bool `url:"shared_visible_only,omitempty" json:"shared_visible_only,omitempty"`
}
// ListProjectsGroups gets a list of groups for the given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#list-a-projects-groups
func (s *ProjectsService) ListProjectsGroups(pid interface{}, opt *ListProjectGroupOptions, options ...RequestOptionFunc) ([]*ProjectGroup, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/groups", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var p []*ProjectGroup
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ProjectLanguages is a map of strings because the response is arbitrary
//
// Gitlab API docs: https://docs.gitlab.com/ce/api/projects.html#languages
type ProjectLanguages map[string]float32
// GetProjectLanguages gets a list of languages used by the project
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#languages
func (s *ProjectsService) GetProjectLanguages(pid interface{}, options ...RequestOptionFunc) (*ProjectLanguages, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/languages", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
p := new(ProjectLanguages)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// GetProjectOptions represents the available GetProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#get-single-project
type GetProjectOptions struct {
Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"`
License *bool `url:"license,omitempty" json:"license,omitempty"`
WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
}
// GetProject gets a specific project, identified by project ID or
// NAMESPACE/PROJECT_NAME, which is owned by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#get-single-project
func (s *ProjectsService) GetProject(pid interface{}, opt *GetProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ProjectEvent represents a GitLab project event.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#get-project-events
type ProjectEvent struct {
Title interface{} `json:"title"`
ProjectID int `json:"project_id"`
ActionName string `json:"action_name"`
TargetID interface{} `json:"target_id"`
TargetType interface{} `json:"target_type"`
AuthorID int `json:"author_id"`
AuthorUsername string `json:"author_username"`
Data struct {
Before string `json:"before"`
After string `json:"after"`
Ref string `json:"ref"`
UserID int `json:"user_id"`
UserName string `json:"user_name"`
Repository *Repository `json:"repository"`
Commits []*Commit `json:"commits"`
TotalCommitsCount int `json:"total_commits_count"`
} `json:"data"`
TargetTitle interface{} `json:"target_title"`
}
func (s ProjectEvent) String() string {
return Stringify(s)
}
// GetProjectEventsOptions represents the available GetProjectEvents() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#get-project-events
type GetProjectEventsOptions ListOptions
// GetProjectEvents gets the events for the specified project. Sorted from
// newest to latest.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#get-project-events
func (s *ProjectsService) GetProjectEvents(pid interface{}, opt *GetProjectEventsOptions, options ...RequestOptionFunc) ([]*ProjectEvent, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/events", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var p []*ProjectEvent
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// CreateProjectOptions represents the available CreateProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-project
type CreateProjectOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
NamespaceID *int `url:"namespace_id,omitempty" json:"namespace_id,omitempty"`
DefaultBranch *string `url:"default_branch,omitempty" json:"default_branch,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
IssuesAccessLevel *AccessControlValue `url:"issues_access_level,omitempty" json:"issues_access_level,omitempty"`
RepositoryAccessLevel *AccessControlValue `url:"repository_access_level,omitempty" json:"repository_access_level,omitempty"`
MergeRequestsAccessLevel *AccessControlValue `url:"merge_requests_access_level,omitempty" json:"merge_requests_access_level,omitempty"`
ForkingAccessLevel *AccessControlValue `url:"forking_access_level,omitempty" json:"forking_access_level,omitempty"`
BuildsAccessLevel *AccessControlValue `url:"builds_access_level,omitempty" json:"builds_access_level,omitempty"`
WikiAccessLevel *AccessControlValue `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"`
SnippetsAccessLevel *AccessControlValue `url:"snippets_access_level,omitempty" json:"snippets_access_level,omitempty"`
PagesAccessLevel *AccessControlValue `url:"pages_access_level,omitempty" json:"pages_access_level,omitempty"`
OperationsAccessLevel *AccessControlValue `url:"operations_access_level,omitempty" json:"operations_access_level,omitempty"`
EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
ResolveOutdatedDiffDiscussions *bool `url:"resolve_outdated_diff_discussions,omitempty" json:"resolve_outdated_diff_discussions,omitempty"`
ContainerExpirationPolicyAttributes *ContainerExpirationPolicyAttributes `url:"container_expiration_policy_attributes,omitempty" json:"container_expiration_policy_attributes,omitempty"`
ContainerRegistryEnabled *bool `url:"container_registry_enabled,omitempty" json:"container_registry_enabled,omitempty"`
SharedRunnersEnabled *bool `url:"shared_runners_enabled,omitempty" json:"shared_runners_enabled,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
ImportURL *string `url:"import_url,omitempty" json:"import_url,omitempty"`
PublicBuilds *bool `url:"public_builds,omitempty" json:"public_builds,omitempty"`
AllowMergeOnSkippedPipeline *bool `url:"allow_merge_on_skipped_pipeline,omitempty" json:"allow_merge_on_skipped_pipeline,omitempty"`
OnlyAllowMergeIfPipelineSucceeds *bool `url:"only_allow_merge_if_pipeline_succeeds,omitempty" json:"only_allow_merge_if_pipeline_succeeds,omitempty"`
OnlyAllowMergeIfAllDiscussionsAreResolved *bool `url:"only_allow_merge_if_all_discussions_are_resolved,omitempty" json:"only_allow_merge_if_all_discussions_are_resolved,omitempty"`
MergeMethod *MergeMethodValue `url:"merge_method,omitempty" json:"merge_method,omitempty"`
RemoveSourceBranchAfterMerge *bool `url:"remove_source_branch_after_merge,omitempty" json:"remove_source_branch_after_merge,omitempty"`
LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"`
RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"`
TagList *[]string `url:"tag_list,omitempty" json:"tag_list,omitempty"`
PrintingMergeRequestLinkEnabled *bool `url:"printing_merge_request_link_enabled,omitempty" json:"printing_merge_request_link_enabled,omitempty"`
BuildGitStrategy *string `url:"build_git_strategy,omitempty" json:"build_git_strategy,omitempty"`
BuildTimeout *int `url:"build_timeout,omitempty" json:"build_timeout,omitempty"`
AutoCancelPendingPipelines *string `url:"auto_cancel_pending_pipelines,omitempty" json:"auto_cancel_pending_pipelines,omitempty"`
BuildCoverageRegex *string `url:"build_coverage_regex,omitempty" json:"build_coverage_regex,omitempty"`
CIConfigPath *string `url:"ci_config_path,omitempty" json:"ci_config_path,omitempty"`
CIForwardDeploymentEnabled *bool `url:"ci_forward_deployment_enabled,omitempty" json:"ci_forward_deployment_enabled,omitempty"`
AutoDevopsEnabled *bool `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"`
AutoDevopsDeployStrategy *string `url:"auto_devops_deploy_strategy,omitempty" json:"auto_devops_deploy_strategy,omitempty"`
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
ExternalAuthorizationClassificationLabel *string `url:"external_authorization_classification_label,omitempty" json:"external_authorization_classification_label,omitempty"`
Mirror *bool `url:"mirror,omitempty" json:"mirror,omitempty"`
MirrorTriggerBuilds *bool `url:"mirror_trigger_builds,omitempty" json:"mirror_trigger_builds,omitempty"`
InitializeWithReadme *bool `url:"initialize_with_readme,omitempty" json:"initialize_with_readme,omitempty"`
TemplateName *string `url:"template_name,omitempty" json:"template_name,omitempty"`
TemplateProjectID *int `url:"template_project_id,omitempty" json:"template_project_id,omitempty"`
UseCustomTemplate *bool `url:"use_custom_template,omitempty" json:"use_custom_template,omitempty"`
GroupWithProjectTemplatesID *int `url:"group_with_project_templates_id,omitempty" json:"group_with_project_templates_id,omitempty"`
PackagesEnabled *bool `url:"packages_enabled,omitempty" json:"packages_enabled,omitempty"`
ServiceDeskEnabled *bool `url:"service_desk_enabled,omitempty" json:"service_desk_enabled,omitempty"`
AutocloseReferencedIssues *bool `url:"autoclose_referenced_issues,omitempty" json:"autoclose_referenced_issues,omitempty"`
SuggestionCommitMessage *string `url:"suggestion_commit_message,omitempty" json:"suggestion_commit_message,omitempty"`
IssuesTemplate *string `url:"issues_template,omitempty" json:"issues_template,omitempty"`
MergeRequestsTemplate *string `url:"merge_requests_template,omitempty" json:"merge_requests_template,omitempty"`
// Deprecated members
IssuesEnabled *bool `url:"issues_enabled,omitempty" json:"issues_enabled,omitempty"`
MergeRequestsEnabled *bool `url:"merge_requests_enabled,omitempty" json:"merge_requests_enabled,omitempty"`
JobsEnabled *bool `url:"jobs_enabled,omitempty" json:"jobs_enabled,omitempty"`
WikiEnabled *bool `url:"wiki_enabled,omitempty" json:"wiki_enabled,omitempty"`
SnippetsEnabled *bool `url:"snippets_enabled,omitempty" json:"snippets_enabled,omitempty"`
}
// ContainerExpirationPolicyAttributes represents the available container
// expiration policy attributes.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#create-project
type ContainerExpirationPolicyAttributes struct {
Cadence *string `url:"cadence,omitempty" json:"cadence,omitempty"`
KeepN *int `url:"keep_n,omitempty" json:"keep_n,omitempty"`
OlderThan *string `url:"older_than,omitempty" json:"older_than,omitempty"`
NameRegexDelete *string `url:"name_regex_delete,omitempty" json:"name_regex_delete,omitempty"`
NameRegexKeep *string `url:"name_regex_keep,omitempty" json:"name_regex_keep,omitempty"`
Enabled *bool `url:"enabled,omitempty" json:"enabled,omitempty"`
// Deprecated members
NameRegex *string `url:"name_regex,omitempty" json:"name_regex,omitempty"`
}
// CreateProject creates a new project owned by the authenticated user.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#create-project
func (s *ProjectsService) CreateProject(opt *CreateProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) {
if opt.ContainerExpirationPolicyAttributes != nil {
// This is needed to satisfy the API. Should be deleted
// when NameRegex is removed (it's now deprecated).
opt.ContainerExpirationPolicyAttributes.NameRegex =
opt.ContainerExpirationPolicyAttributes.NameRegexDelete
}
req, err := s.client.NewRequest(http.MethodPost, "projects", opt, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// CreateProjectForUserOptions represents the available CreateProjectForUser()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#create-project-for-user
type CreateProjectForUserOptions CreateProjectOptions
// CreateProjectForUser creates a new project owned by the specified user.
// Available only for admins.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#create-project-for-user
func (s *ProjectsService) CreateProjectForUser(user int, opt *CreateProjectForUserOptions, options ...RequestOptionFunc) (*Project, *Response, error) {
if opt.ContainerExpirationPolicyAttributes != nil {
// This is needed to satisfy the API. Should be deleted
// when NameRegex is removed (it's now deprecated).
opt.ContainerExpirationPolicyAttributes.NameRegex =
opt.ContainerExpirationPolicyAttributes.NameRegexDelete
}
u := fmt.Sprintf("projects/user/%d", user)
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// EditProjectOptions represents the available EditProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#edit-project
type EditProjectOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
Path *string `url:"path,omitempty" json:"path,omitempty"`
DefaultBranch *string `url:"default_branch,omitempty" json:"default_branch,omitempty"`
Description *string `url:"description,omitempty" json:"description,omitempty"`
IssuesAccessLevel *AccessControlValue `url:"issues_access_level,omitempty" json:"issues_access_level,omitempty"`
RepositoryAccessLevel *AccessControlValue `url:"repository_access_level,omitempty" json:"repository_access_level,omitempty"`
MergeRequestsAccessLevel *AccessControlValue `url:"merge_requests_access_level,omitempty" json:"merge_requests_access_level,omitempty"`
ForkingAccessLevel *AccessControlValue `url:"forking_access_level,omitempty" json:"forking_access_level,omitempty"`
BuildsAccessLevel *AccessControlValue `url:"builds_access_level,omitempty" json:"builds_access_level,omitempty"`
WikiAccessLevel *AccessControlValue `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"`
SnippetsAccessLevel *AccessControlValue `url:"snippets_access_level,omitempty" json:"snippets_access_level,omitempty"`
PagesAccessLevel *AccessControlValue `url:"pages_access_level,omitempty" json:"pages_access_level,omitempty"`
OperationsAccessLevel *AccessControlValue `url:"operations_access_level,omitempty" json:"operations_access_level,omitempty"`
EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
ResolveOutdatedDiffDiscussions *bool `url:"resolve_outdated_diff_discussions,omitempty" json:"resolve_outdated_diff_discussions,omitempty"`
ContainerExpirationPolicyAttributes *ContainerExpirationPolicyAttributes `url:"container_expiration_policy_attributes,omitempty" json:"container_expiration_policy_attributes,omitempty"`
ContainerRegistryEnabled *bool `url:"container_registry_enabled,omitempty" json:"container_registry_enabled,omitempty"`
SharedRunnersEnabled *bool `url:"shared_runners_enabled,omitempty" json:"shared_runners_enabled,omitempty"`
Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
ImportURL *string `url:"import_url,omitempty" json:"import_url,omitempty"`
PublicBuilds *bool `url:"public_builds,omitempty" json:"public_builds,omitempty"`
AllowMergeOnSkippedPipeline *bool `url:"allow_merge_on_skipped_pipeline,omitempty" json:"allow_merge_on_skipped_pipeline,omitempty"`
OnlyAllowMergeIfPipelineSucceeds *bool `url:"only_allow_merge_if_pipeline_succeeds,omitempty" json:"only_allow_merge_if_pipeline_succeeds,omitempty"`
OnlyAllowMergeIfAllDiscussionsAreResolved *bool `url:"only_allow_merge_if_all_discussions_are_resolved,omitempty" json:"only_allow_merge_if_all_discussions_are_resolved,omitempty"`
MergeMethod *MergeMethodValue `url:"merge_method,omitempty" json:"merge_method,omitempty"`
RemoveSourceBranchAfterMerge *bool `url:"remove_source_branch_after_merge,omitempty" json:"remove_source_branch_after_merge,omitempty"`
LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"`
RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"`
TagList *[]string `url:"tag_list,omitempty" json:"tag_list,omitempty"`
BuildGitStrategy *string `url:"build_git_strategy,omitempty" json:"build_git_strategy,omitempty"`
BuildTimeout *int `url:"build_timeout,omitempty" json:"build_timeout,omitempty"`
AutoCancelPendingPipelines *string `url:"auto_cancel_pending_pipelines,omitempty" json:"auto_cancel_pending_pipelines,omitempty"`
BuildCoverageRegex *string `url:"build_coverage_regex,omitempty" json:"build_coverage_regex,omitempty"`
CIConfigPath *string `url:"ci_config_path,omitempty" json:"ci_config_path,omitempty"`
CIForwardDeploymentEnabled *bool `url:"ci_forward_deployment_enabled,omitempty" json:"ci_forward_deployment_enabled,omitempty"`
CIDefaultGitDepth *int `url:"ci_default_git_depth,omitempty" json:"ci_default_git_depth,omitempty"`
AutoDevopsEnabled *bool `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"`
AutoDevopsDeployStrategy *string `url:"auto_devops_deploy_strategy,omitempty" json:"auto_devops_deploy_strategy,omitempty"`
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
ExternalAuthorizationClassificationLabel *string `url:"external_authorization_classification_label,omitempty" json:"external_authorization_classification_label,omitempty"`
Mirror *bool `url:"mirror,omitempty" json:"mirror,omitempty"`
MirrorUserID *int `url:"mirror_user_id,omitempty" json:"mirror_user_id,omitempty"`
MirrorTriggerBuilds *bool `url:"mirror_trigger_builds,omitempty" json:"mirror_trigger_builds,omitempty"`
OnlyMirrorProtectedBranches *bool `url:"only_mirror_protected_branches,omitempty" json:"only_mirror_protected_branches,omitempty"`
MirrorOverwritesDivergedBranches *bool `url:"mirror_overwrites_diverged_branches,omitempty" json:"mirror_overwrites_diverged_branches,omitempty"`
PackagesEnabled *bool `url:"packages_enabled,omitempty" json:"packages_enabled,omitempty"`
ServiceDeskEnabled *bool `url:"service_desk_enabled,omitempty" json:"service_desk_enabled,omitempty"`
AutocloseReferencedIssues *bool `url:"autoclose_referenced_issues,omitempty" json:"autoclose_referenced_issues,omitempty"`
SuggestionCommitMessage *string `url:"suggestion_commit_message,omitempty" json:"suggestion_commit_message,omitempty"`
IssuesTemplate *string `url:"issues_template,omitempty" json:"issues_template,omitempty"`
MergeRequestsTemplate *string `url:"merge_requests_template,omitempty" json:"merge_requests_template,omitempty"`
// Deprecated members
IssuesEnabled *bool `url:"issues_enabled,omitempty" json:"issues_enabled,omitempty"`
MergeRequestsEnabled *bool `url:"merge_requests_enabled,omitempty" json:"merge_requests_enabled,omitempty"`
JobsEnabled *bool `url:"jobs_enabled,omitempty" json:"jobs_enabled,omitempty"`
WikiEnabled *bool `url:"wiki_enabled,omitempty" json:"wiki_enabled,omitempty"`
SnippetsEnabled *bool `url:"snippets_enabled,omitempty" json:"snippets_enabled,omitempty"`
}
// EditProject updates an existing project.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#edit-project
func (s *ProjectsService) EditProject(pid interface{}, opt *EditProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) {
if opt.ContainerExpirationPolicyAttributes != nil {
// This is needed to satisfy the API. Should be deleted
// when NameRegex is removed (it's now deprecated).
opt.ContainerExpirationPolicyAttributes.NameRegex =
opt.ContainerExpirationPolicyAttributes.NameRegexDelete
}
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ForkProjectOptions represents the available ForkProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#fork-project
type ForkProjectOptions struct {
Namespace *string `url:"namespace,omitempty" json:"namespace,omitempty"`
Name *string `url:"name,omitempty" json:"name,omitempty" `
Path *string `url:"path,omitempty" json:"path,omitempty"`
}
// ForkProject forks a project into the user namespace of the authenticated
// user.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#fork-project
func (s *ProjectsService) ForkProject(pid interface{}, opt *ForkProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/fork", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// StarProject stars a given the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#star-a-project
func (s *ProjectsService) StarProject(pid interface{}, options ...RequestOptionFunc) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/star", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// UnstarProject unstars a given project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#unstar-a-project
func (s *ProjectsService) UnstarProject(pid interface{}, options ...RequestOptionFunc) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/unstar", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ArchiveProject archives the project if the user is either admin or the
// project owner of this project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#archive-a-project
func (s *ProjectsService) ArchiveProject(pid interface{}, options ...RequestOptionFunc) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/archive", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// UnarchiveProject unarchives the project if the user is either admin or
// the project owner of this project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#unarchive-a-project
func (s *ProjectsService) UnarchiveProject(pid interface{}, options ...RequestOptionFunc) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/unarchive", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// DeleteProject removes a project including all associated resources
// (issues, merge requests etc.)
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#remove-project
func (s *ProjectsService) DeleteProject(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s", pathEscape(project))
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ShareWithGroupOptions represents options to share project with groups
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#share-project-with-group
type ShareWithGroupOptions struct {
GroupID *int `url:"group_id" json:"group_id"`
GroupAccess *AccessLevelValue `url:"group_access" json:"group_access"`
ExpiresAt *string `url:"expires_at" json:"expires_at"`
}
// ShareProjectWithGroup allows to share a project with a group.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#share-project-with-group
func (s *ProjectsService) ShareProjectWithGroup(pid interface{}, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/share", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// DeleteSharedProjectFromGroup allows to unshare a project from a group.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#delete-a-shared-project-link-within-a-group
func (s *ProjectsService) DeleteSharedProjectFromGroup(pid interface{}, groupID int, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/share/%d", pathEscape(project), groupID)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ProjectMember represents a project member.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#list-project-team-members
type ProjectMember struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt *time.Time `json:"created_at"`
ExpiresAt *ISOTime `json:"expires_at"`
AccessLevel AccessLevelValue `json:"access_level"`
WebURL string `json:"web_url"`
AvatarURL string `json:"avatar_url"`
}
// ProjectHook represents a project hook.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#list-project-hooks
type ProjectHook struct {
ID int `json:"id"`
URL string `json:"url"`
ConfidentialNoteEvents bool `json:"confidential_note_events"`
ProjectID int `json:"project_id"`
PushEvents bool `json:"push_events"`
PushEventsBranchFilter string `json:"push_events_branch_filter"`
IssuesEvents bool `json:"issues_events"`
ConfidentialIssuesEvents bool `json:"confidential_issues_events"`
MergeRequestsEvents bool `json:"merge_requests_events"`
TagPushEvents bool `json:"tag_push_events"`
NoteEvents bool `json:"note_events"`
JobEvents bool `json:"job_events"`
PipelineEvents bool `json:"pipeline_events"`
WikiPageEvents bool `json:"wiki_page_events"`
DeploymentEvents bool `json:"deployment_events"`
ReleasesEvents bool `json:"releases_events"`
EnableSSLVerification bool `json:"enable_ssl_verification"`
CreatedAt *time.Time `json:"created_at"`
}
// ListProjectHooksOptions represents the available ListProjectHooks() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#list-project-hooks
type ListProjectHooksOptions ListOptions
// ListProjectHooks gets a list of project hooks.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#list-project-hooks
func (s *ProjectsService) ListProjectHooks(pid interface{}, opt *ListProjectHooksOptions, options ...RequestOptionFunc) ([]*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var ph []*ProjectHook
resp, err := s.client.Do(req, &ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// GetProjectHook gets a specific hook for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#get-project-hook
func (s *ProjectsService) GetProjectHook(pid interface{}, hook int, options ...RequestOptionFunc) (*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks/%d", pathEscape(project), hook)
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
ph := new(ProjectHook)
resp, err := s.client.Do(req, ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// AddProjectHookOptions represents the available AddProjectHook() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#add-project-hook
type AddProjectHookOptions struct {
URL *string `url:"url,omitempty" json:"url,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
PushEventsBranchFilter *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"`
ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"`
JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"`
EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
Token *string `url:"token,omitempty" json:"token,omitempty"`
}
// AddProjectHook adds a hook to a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#add-project-hook
func (s *ProjectsService) AddProjectHook(pid interface{}, opt *AddProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
ph := new(ProjectHook)
resp, err := s.client.Do(req, ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// EditProjectHookOptions represents the available EditProjectHook() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#edit-project-hook
type EditProjectHookOptions struct {
URL *string `url:"url,omitempty" json:"url,omitempty"`
ConfidentialNoteEvents *bool `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
PushEvents *bool `url:"push_events,omitempty" json:"push_events,omitempty"`
PushEventsBranchFilter *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
IssuesEvents *bool `url:"issues_events,omitempty" json:"issues_events,omitempty"`
ConfidentialIssuesEvents *bool `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
MergeRequestsEvents *bool `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
TagPushEvents *bool `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
NoteEvents *bool `url:"note_events,omitempty" json:"note_events,omitempty"`
JobEvents *bool `url:"job_events,omitempty" json:"job_events,omitempty"`
PipelineEvents *bool `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
WikiPageEvents *bool `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
DeploymentEvents *bool `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
ReleasesEvents *bool `url:"releases_events,omitempty" json:"releases_events,omitempty"`
EnableSSLVerification *bool `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
Token *string `url:"token,omitempty" json:"token,omitempty"`
}
// EditProjectHook edits a hook for a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#edit-project-hook
func (s *ProjectsService) EditProjectHook(pid interface{}, hook int, opt *EditProjectHookOptions, options ...RequestOptionFunc) (*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks/%d", pathEscape(project), hook)
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, nil, err
}
ph := new(ProjectHook)
resp, err := s.client.Do(req, ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// DeleteProjectHook removes a hook from a project. This is an idempotent
// method and can be called multiple times. Either the hook is available or not.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#delete-project-hook
func (s *ProjectsService) DeleteProjectHook(pid interface{}, hook int, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/hooks/%d", pathEscape(project), hook)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ProjectForkRelation represents a project fork relationship.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#admin-fork-relation
type ProjectForkRelation struct {
ID int `json:"id"`
ForkedToProjectID int `json:"forked_to_project_id"`
ForkedFromProjectID int `json:"forked_from_project_id"`
CreatedAt *time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
}
// CreateProjectForkRelation creates a forked from/to relation between
// existing projects.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#create-a-forked-fromto-relation-between-existing-projects.
func (s *ProjectsService) CreateProjectForkRelation(pid int, fork int, options ...RequestOptionFunc) (*ProjectForkRelation, *Response, error) {
u := fmt.Sprintf("projects/%d/fork/%d", pid, fork)
req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, nil, err
}
pfr := new(ProjectForkRelation)
resp, err := s.client.Do(req, pfr)
if err != nil {
return nil, resp, err
}
return pfr, resp, err
}
// DeleteProjectForkRelation deletes an existing forked from relationship.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#delete-an-existing-forked-from-relationship
func (s *ProjectsService) DeleteProjectForkRelation(pid int, options ...RequestOptionFunc) (*Response, error) {
u := fmt.Sprintf("projects/%d/fork", pid)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ProjectFile represents an uploaded project file
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#upload-a-file
type ProjectFile struct {
Alt string `json:"alt"`
URL string `json:"url"`
Markdown string `json:"markdown"`
}
// UploadFile upload a file from disk
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#upload-a-file
func (s *ProjectsService) UploadFile(pid interface{}, file string, options ...RequestOptionFunc) (*ProjectFile, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/uploads", pathEscape(project))
f, err := os.Open(file)
if err != nil {
return nil, nil, err
}
defer f.Close()
b := &bytes.Buffer{}
w := multipart.NewWriter(b)
_, filename := filepath.Split(file)
fw, err := w.CreateFormFile("file", filename)
if err != nil {
return nil, nil, err
}
_, err = io.Copy(fw, f)
if err != nil {
return nil, nil, err
}
w.Close()
req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, nil, err
}
// Set the buffer as the request body.
if err = req.SetBody(b); err != nil {
return nil, nil, err
}
// Overwrite the default content type.
req.Header.Set("Content-Type", w.FormDataContentType())
uf := &ProjectFile{}
resp, err := s.client.Do(req, uf)
if err != nil {
return nil, resp, err
}
return uf, resp, nil
}
// ListProjectForks gets a list of project forks.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/projects.html#list-forks-of-a-project
func (s *ProjectsService) ListProjectForks(pid interface{}, opt *ListProjectsOptions, options ...RequestOptionFunc) ([]*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/forks", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}
var forks []*Project
resp, err := s.client.Do(req, &forks)
if err != nil {
return nil, resp, err
}
return forks, resp, err
}
// ProjectPushRules represents a project push rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#push-rules
type ProjectPushRules struct {
ID int `json:"id"`
ProjectID int `json:"project_id"`
CommitMessageRegex string `json:"commit_message_regex"`
CommitMessageNegativeRegex string `json:"commit_message_negative_regex"`
BranchNameRegex string `json:"branch_name_regex"`
DenyDeleteTag bool `json:"deny_delete_tag"`
CreatedAt *time.Time `json:"created_at"`
MemberCheck bool `json:"member_check"`
PreventSecrets bool `json:"prevent_secrets"`
AuthorEmailRegex string `json:"author_email_regex"`
FileNameRegex string `json:"file_name_regex"`
MaxFileSize int `json:"max_file_size"`
CommitCommitterCheck bool `json:"commit_committer_check"`
RejectUnsignedCommits bool `json:"reject_unsigned_commits"`
}
// GetProjectPushRules gets the push rules of a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#get-project-push-rules
func (s *ProjectsService) GetProjectPushRules(pid interface{}, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/push_rule", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
ppr := new(ProjectPushRules)
resp, err := s.client.Do(req, ppr)
if err != nil {
return nil, resp, err
}
return ppr, resp, err
}
// AddProjectPushRuleOptions represents the available AddProjectPushRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#add-project-push-rule
type AddProjectPushRuleOptions struct {
DenyDeleteTag *bool `url:"deny_delete_tag,omitempty" json:"deny_delete_tag,omitempty"`
MemberCheck *bool `url:"member_check,omitempty" json:"member_check,omitempty"`
PreventSecrets *bool `url:"prevent_secrets,omitempty" json:"prevent_secrets,omitempty"`
CommitMessageRegex *string `url:"commit_message_regex,omitempty" json:"commit_message_regex,omitempty"`
CommitMessageNegativeRegex *string `url:"commit_message_negative_regex,omitempty" json:"commit_message_negative_regex,omitempty"`
BranchNameRegex *string `url:"branch_name_regex,omitempty" json:"branch_name_regex,omitempty"`
AuthorEmailRegex *string `url:"author_email_regex,omitempty" json:"author_email_regex,omitempty"`
FileNameRegex *string `url:"file_name_regex,omitempty" json:"file_name_regex,omitempty"`
MaxFileSize *int `url:"max_file_size,omitempty" json:"max_file_size,omitempty"`
CommitCommitterCheck *bool `url:"commit_committer_check,omitempty" json:"commit_committer_check,omitempty"`
RejectUnsignedCommits *bool `url:"reject_unsigned_commits,omitempty" json:"reject_unsigned_commits,omitempty"`
}
// AddProjectPushRule adds a push rule to a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#add-project-push-rule
func (s *ProjectsService) AddProjectPushRule(pid interface{}, opt *AddProjectPushRuleOptions, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/push_rule", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
ppr := new(ProjectPushRules)
resp, err := s.client.Do(req, ppr)
if err != nil {
return nil, resp, err
}
return ppr, resp, err
}
// EditProjectPushRuleOptions represents the available EditProjectPushRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#edit-project-push-rule
type EditProjectPushRuleOptions struct {
AuthorEmailRegex *string `url:"author_email_regex,omitempty" json:"author_email_regex,omitempty"`
BranchNameRegex *string `url:"branch_name_regex,omitempty" json:"branch_name_regex,omitempty"`
CommitMessageRegex *string `url:"commit_message_regex,omitempty" json:"commit_message_regex,omitempty"`
CommitMessageNegativeRegex *string `url:"commit_message_negative_regex,omitempty" json:"commit_message_negative_regex,omitempty"`
FileNameRegex *string `url:"file_name_regex,omitempty" json:"file_name_regex,omitempty"`
DenyDeleteTag *bool `url:"deny_delete_tag,omitempty" json:"deny_delete_tag,omitempty"`
MemberCheck *bool `url:"member_check,omitempty" json:"member_check,omitempty"`
PreventSecrets *bool `url:"prevent_secrets,omitempty" json:"prevent_secrets,omitempty"`
MaxFileSize *int `url:"max_file_size,omitempty" json:"max_file_size,omitempty"`
CommitCommitterCheck *bool `url:"commit_committer_check,omitempty" json:"commit_committer_check,omitempty"`
RejectUnsignedCommits *bool `url:"reject_unsigned_commits,omitempty" json:"reject_unsigned_commits,omitempty"`
}
// EditProjectPushRule edits a push rule for a specified project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#edit-project-push-rule
func (s *ProjectsService) EditProjectPushRule(pid interface{}, opt *EditProjectPushRuleOptions, options ...RequestOptionFunc) (*ProjectPushRules, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/push_rule", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, nil, err
}
ppr := new(ProjectPushRules)
resp, err := s.client.Do(req, ppr)
if err != nil {
return nil, resp, err
}
return ppr, resp, err
}
// DeleteProjectPushRule removes a push rule from a project. This is an
// idempotent method and can be called multiple times. Either the push rule is
// available or not.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#delete-project-push-rule
func (s *ProjectsService) DeleteProjectPushRule(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/push_rule", pathEscape(project))
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ProjectApprovals represents GitLab project level merge request approvals.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals
type ProjectApprovals struct {
Approvers []*MergeRequestApproverUser `json:"approvers"`
ApproverGroups []*MergeRequestApproverGroup `json:"approver_groups"`
ApprovalsBeforeMerge int `json:"approvals_before_merge"`
ResetApprovalsOnPush bool `json:"reset_approvals_on_push"`
DisableOverridingApproversPerMergeRequest bool `json:"disable_overriding_approvers_per_merge_request"`
MergeRequestsAuthorApproval bool `json:"merge_requests_author_approval"`
MergeRequestsDisableCommittersApproval bool `json:"merge_requests_disable_committers_approval"`
RequirePasswordToApprove bool `json:"require_password_to_approve"`
}
// GetApprovalConfiguration get the approval configuration for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-configuration
func (s *ProjectsService) GetApprovalConfiguration(pid interface{}, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approvals", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
pa := new(ProjectApprovals)
resp, err := s.client.Do(req, pa)
if err != nil {
return nil, resp, err
}
return pa, resp, err
}
// ChangeApprovalConfigurationOptions represents the available
// ApprovalConfiguration() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-configuration
type ChangeApprovalConfigurationOptions struct {
ApprovalsBeforeMerge *int `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
ResetApprovalsOnPush *bool `url:"reset_approvals_on_push,omitempty" json:"reset_approvals_on_push,omitempty"`
DisableOverridingApproversPerMergeRequest *bool `url:"disable_overriding_approvers_per_merge_request,omitempty" json:"disable_overriding_approvers_per_merge_request,omitempty"`
MergeRequestsAuthorApproval *bool `url:"merge_requests_author_approval,omitempty" json:"merge_requests_author_approval,omitempty"`
MergeRequestsDisableCommittersApproval *bool `url:"merge_requests_disable_committers_approval,omitempty" json:"merge_requests_disable_committers_approval,omitempty"`
RequirePasswordToApprove *bool `url:"require_password_to_approve,omitempty" json:"require_password_to_approve,omitempty"`
}
// ChangeApprovalConfiguration updates the approval configuration for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-configuration
func (s *ProjectsService) ChangeApprovalConfiguration(pid interface{}, opt *ChangeApprovalConfigurationOptions, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approvals", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
pa := new(ProjectApprovals)
resp, err := s.client.Do(req, pa)
if err != nil {
return nil, resp, err
}
return pa, resp, err
}
// GetProjectApprovalRules looks up the list of project level approvers.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#get-project-level-rules
func (s *ProjectsService) GetProjectApprovalRules(pid interface{}, options ...RequestOptionFunc) ([]*ProjectApprovalRule, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approval_rules", pathEscape(project))
req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}
var par []*ProjectApprovalRule
resp, err := s.client.Do(req, &par)
if err != nil {
return nil, resp, err
}
return par, resp, err
}
// CreateProjectLevelRuleOptions represents the available CreateProjectApprovalRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-project-level-rules
type CreateProjectLevelRuleOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"`
UserIDs []int `url:"user_ids,omitempty" json:"user_ids,omitempty"`
GroupIDs []int `url:"group_ids,omitempty" json:"group_ids,omitempty"`
ProtectedBranchIDs []int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"`
}
// CreateProjectApprovalRule creates a new project-level approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-project-level-rules
func (s *ProjectsService) CreateProjectApprovalRule(pid interface{}, opt *CreateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approval_rules", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
if err != nil {
return nil, nil, err
}
par := new(ProjectApprovalRule)
resp, err := s.client.Do(req, &par)
if err != nil {
return nil, resp, err
}
return par, resp, err
}
// UpdateProjectLevelRuleOptions represents the available UpdateProjectApprovalRule()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-project-level-rules
type UpdateProjectLevelRuleOptions struct {
Name *string `url:"name,omitempty" json:"name,omitempty"`
ApprovalsRequired *int `url:"approvals_required,omitempty" json:"approvals_required,omitempty"`
UserIDs []int `url:"user_ids,omitempty" json:"user_ids,omitempty"`
GroupIDs []int `url:"group_ids,omitempty" json:"group_ids,omitempty"`
ProtectedBranchIDs []int `url:"protected_branch_ids,omitempty" json:"protected_branch_ids,omitempty"`
}
// UpdateProjectApprovalRule updates an existing approval rule with new options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#update-project-level-rules
func (s *ProjectsService) UpdateProjectApprovalRule(pid interface{}, approvalRule int, opt *UpdateProjectLevelRuleOptions, options ...RequestOptionFunc) (*ProjectApprovalRule, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approval_rules/%d", pathEscape(project), approvalRule)
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, nil, err
}
par := new(ProjectApprovalRule)
resp, err := s.client.Do(req, &par)
if err != nil {
return nil, resp, err
}
return par, resp, err
}
// DeleteProjectApprovalRule deletes a project-level approval rule.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#delete-project-level-rules
func (s *ProjectsService) DeleteProjectApprovalRule(pid interface{}, approvalRule int, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/approval_rules/%d", pathEscape(project), approvalRule)
req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// ChangeAllowedApproversOptions represents the available ChangeAllowedApprovers()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers
type ChangeAllowedApproversOptions struct {
ApproverIDs []int `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
ApproverGroupIDs []int `url:"approver_group_ids,omitempty" json:"approver_group_ids,omitempty"`
}
// ChangeAllowedApprovers updates the list of approvers and approver groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#change-allowed-approvers
func (s *ProjectsService) ChangeAllowedApprovers(pid interface{}, opt *ChangeAllowedApproversOptions, options ...RequestOptionFunc) (*ProjectApprovals, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/approvers", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, nil, err
}
pa := new(ProjectApprovals)
resp, err := s.client.Do(req, pa)
if err != nil {
return nil, resp, err
}
return pa, resp, err
}
// StartMirroringProject start the pull mirroring process for a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project-starter
func (s *ProjectsService) StartMirroringProject(pid interface{}, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/mirror/pull", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// TransferProjectOptions represents the available TransferProject() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#transfer-a-project-to-a-new-namespace
type TransferProjectOptions struct {
Namespace interface{} `url:"namespace,omitempty" json:"namespace,omitempty"`
}
// TransferProject transfer a project into the specified namespace
//
// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#transfer-a-project-to-a-new-namespace
func (s *ProjectsService) TransferProject(pid interface{}, opt *TransferProjectOptions, options ...RequestOptionFunc) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/transfer", pathEscape(project))
req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}