Skip to content

Commit bb1fcd9

Browse files
authored
Merge branch 'main' into opengraph-title
2 parents ac2e99c + 5fe764b commit bb1fcd9

27 files changed

+57
-92
lines changed

modules/graceful/manager.go

+16-34
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package graceful
66

77
import (
88
"context"
9+
"runtime/pprof"
910
"sync"
1011
"time"
1112

@@ -62,15 +63,13 @@ type WithCallback func(callback func())
6263
// Similarly the callback function provided to atTerminate must return once termination is complete.
6364
// Please note that use of the atShutdown and atTerminate callbacks will create go-routines that will wait till their respective signals
6465
// - users must therefore be careful to only call these as necessary.
65-
// If run is not expected to run indefinitely RunWithShutdownChan is likely to be more appropriate.
6666
type RunnableWithShutdownFns func(atShutdown, atTerminate func(func()))
6767

6868
// RunWithShutdownFns takes a function that has both atShutdown and atTerminate callbacks
6969
// After the callback to atShutdown is called and is complete, the main function must return.
7070
// Similarly the callback function provided to atTerminate must return once termination is complete.
7171
// Please note that use of the atShutdown and atTerminate callbacks will create go-routines that will wait till their respective signals
7272
// - users must therefore be careful to only call these as necessary.
73-
// If run is not expected to run indefinitely RunWithShutdownChan is likely to be more appropriate.
7473
func (g *Manager) RunWithShutdownFns(run RunnableWithShutdownFns) {
7574
g.runningServerWaitGroup.Add(1)
7675
defer g.runningServerWaitGroup.Done()
@@ -98,32 +97,6 @@ func (g *Manager) RunWithShutdownFns(run RunnableWithShutdownFns) {
9897
})
9998
}
10099

101-
// RunnableWithShutdownChan is a runnable with functions to run at shutdown and terminate.
102-
// After the atShutdown channel is closed, the main function must return once shutdown is complete.
103-
// (Optionally IsHammer may be waited for instead however, this should be avoided if possible.)
104-
// The callback function provided to atTerminate must return once termination is complete.
105-
// Please note that use of the atTerminate function will create a go-routine that will wait till terminate - users must therefore be careful to only call this as necessary.
106-
type RunnableWithShutdownChan func(atShutdown <-chan struct{}, atTerminate WithCallback)
107-
108-
// RunWithShutdownChan takes a function that has channel to watch for shutdown and atTerminate callbacks
109-
// After the atShutdown channel is closed, the main function must return once shutdown is complete.
110-
// (Optionally IsHammer may be waited for instead however, this should be avoided if possible.)
111-
// The callback function provided to atTerminate must return once termination is complete.
112-
// Please note that use of the atTerminate function will create a go-routine that will wait till terminate - users must therefore be careful to only call this as necessary.
113-
func (g *Manager) RunWithShutdownChan(run RunnableWithShutdownChan) {
114-
g.runningServerWaitGroup.Add(1)
115-
defer g.runningServerWaitGroup.Done()
116-
defer func() {
117-
if err := recover(); err != nil {
118-
log.Critical("PANIC during RunWithShutdownChan: %v\nStacktrace: %s", err, log.Stack(2))
119-
g.doShutdown()
120-
}
121-
}()
122-
run(g.IsShutdown(), func(atTerminate func()) {
123-
g.RunAtTerminate(atTerminate)
124-
})
125-
}
126-
127100
// RunWithShutdownContext takes a function that has a context to watch for shutdown.
128101
// After the provided context is Done(), the main function must return once shutdown is complete.
129102
// (Optionally the HammerContext may be obtained and waited for however, this should be avoided if possible.)
@@ -136,7 +109,9 @@ func (g *Manager) RunWithShutdownContext(run func(context.Context)) {
136109
g.doShutdown()
137110
}
138111
}()
139-
run(g.ShutdownContext())
112+
ctx := g.ShutdownContext()
113+
pprof.SetGoroutineLabels(ctx) // We don't have a label to restore back to but I think this is fine
114+
run(ctx)
140115
}
141116

142117
// RunAtTerminate adds to the terminate wait group and creates a go-routine to run the provided function at termination
@@ -198,6 +173,8 @@ func (g *Manager) doShutdown() {
198173
}
199174
g.lock.Lock()
200175
g.shutdownCtxCancel()
176+
atShutdownCtx := pprof.WithLabels(g.hammerCtx, pprof.Labels("graceful-lifecycle", "post-shutdown"))
177+
pprof.SetGoroutineLabels(atShutdownCtx)
201178
for _, fn := range g.toRunAtShutdown {
202179
go fn()
203180
}
@@ -214,7 +191,7 @@ func (g *Manager) doShutdown() {
214191
g.doTerminate()
215192
g.WaitForTerminate()
216193
g.lock.Lock()
217-
g.doneCtxCancel()
194+
g.managerCtxCancel()
218195
g.lock.Unlock()
219196
}()
220197
}
@@ -227,6 +204,8 @@ func (g *Manager) doHammerTime(d time.Duration) {
227204
default:
228205
log.Warn("Setting Hammer condition")
229206
g.hammerCtxCancel()
207+
atHammerCtx := pprof.WithLabels(g.terminateCtx, pprof.Labels("graceful-lifecycle", "post-hammer"))
208+
pprof.SetGoroutineLabels(atHammerCtx)
230209
for _, fn := range g.toRunAtHammer {
231210
go fn()
232211
}
@@ -244,6 +223,9 @@ func (g *Manager) doTerminate() {
244223
default:
245224
log.Warn("Terminating")
246225
g.terminateCtxCancel()
226+
atTerminateCtx := pprof.WithLabels(g.managerCtx, pprof.Labels("graceful-lifecycle", "post-terminate"))
227+
pprof.SetGoroutineLabels(atTerminateCtx)
228+
247229
for _, fn := range g.toRunAtTerminate {
248230
go fn()
249231
}
@@ -331,20 +313,20 @@ func (g *Manager) InformCleanup() {
331313

332314
// Done allows the manager to be viewed as a context.Context, it returns a channel that is closed when the server is finished terminating
333315
func (g *Manager) Done() <-chan struct{} {
334-
return g.doneCtx.Done()
316+
return g.managerCtx.Done()
335317
}
336318

337319
// Err allows the manager to be viewed as a context.Context done at Terminate
338320
func (g *Manager) Err() error {
339-
return g.doneCtx.Err()
321+
return g.managerCtx.Err()
340322
}
341323

342324
// Value allows the manager to be viewed as a context.Context done at Terminate
343325
func (g *Manager) Value(key interface{}) interface{} {
344-
return g.doneCtx.Value(key)
326+
return g.managerCtx.Value(key)
345327
}
346328

347329
// Deadline returns nil as there is no fixed Deadline for the manager, it allows the manager to be viewed as a context.Context
348330
func (g *Manager) Deadline() (deadline time.Time, ok bool) {
349-
return g.doneCtx.Deadline()
331+
return g.managerCtx.Deadline()
350332
}

modules/graceful/manager_unix.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"errors"
1313
"os"
1414
"os/signal"
15+
"runtime/pprof"
1516
"sync"
1617
"syscall"
1718
"time"
@@ -29,11 +30,11 @@ type Manager struct {
2930
shutdownCtx context.Context
3031
hammerCtx context.Context
3132
terminateCtx context.Context
32-
doneCtx context.Context
33+
managerCtx context.Context
3334
shutdownCtxCancel context.CancelFunc
3435
hammerCtxCancel context.CancelFunc
3536
terminateCtxCancel context.CancelFunc
36-
doneCtxCancel context.CancelFunc
37+
managerCtxCancel context.CancelFunc
3738
runningServerWaitGroup sync.WaitGroup
3839
createServerWaitGroup sync.WaitGroup
3940
terminateWaitGroup sync.WaitGroup
@@ -58,7 +59,17 @@ func (g *Manager) start(ctx context.Context) {
5859
g.terminateCtx, g.terminateCtxCancel = context.WithCancel(ctx)
5960
g.shutdownCtx, g.shutdownCtxCancel = context.WithCancel(ctx)
6061
g.hammerCtx, g.hammerCtxCancel = context.WithCancel(ctx)
61-
g.doneCtx, g.doneCtxCancel = context.WithCancel(ctx)
62+
g.managerCtx, g.managerCtxCancel = context.WithCancel(ctx)
63+
64+
// Next add pprof labels to these contexts
65+
g.terminateCtx = pprof.WithLabels(g.terminateCtx, pprof.Labels("graceful-lifecycle", "with-terminate"))
66+
g.shutdownCtx = pprof.WithLabels(g.shutdownCtx, pprof.Labels("graceful-lifecycle", "with-shutdown"))
67+
g.hammerCtx = pprof.WithLabels(g.hammerCtx, pprof.Labels("graceful-lifecycle", "with-hammer"))
68+
g.managerCtx = pprof.WithLabels(g.managerCtx, pprof.Labels("graceful-lifecycle", "with-manager"))
69+
70+
// Now label this and all goroutines created by this goroutine with the graceful-lifecycle manager
71+
pprof.SetGoroutineLabels(g.managerCtx)
72+
defer pprof.SetGoroutineLabels(ctx)
6273

6374
// Set the running state & handle signals
6475
g.setState(stateRunning)

modules/graceful/manager_windows.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package graceful
1111
import (
1212
"context"
1313
"os"
14+
"runtime/pprof"
1415
"strconv"
1516
"sync"
1617
"time"
@@ -40,11 +41,11 @@ type Manager struct {
4041
shutdownCtx context.Context
4142
hammerCtx context.Context
4243
terminateCtx context.Context
43-
doneCtx context.Context
44+
managerCtx context.Context
4445
shutdownCtxCancel context.CancelFunc
4546
hammerCtxCancel context.CancelFunc
4647
terminateCtxCancel context.CancelFunc
47-
doneCtxCancel context.CancelFunc
48+
managerCtxCancel context.CancelFunc
4849
runningServerWaitGroup sync.WaitGroup
4950
createServerWaitGroup sync.WaitGroup
5051
terminateWaitGroup sync.WaitGroup
@@ -71,7 +72,17 @@ func (g *Manager) start() {
7172
g.terminateCtx, g.terminateCtxCancel = context.WithCancel(g.ctx)
7273
g.shutdownCtx, g.shutdownCtxCancel = context.WithCancel(g.ctx)
7374
g.hammerCtx, g.hammerCtxCancel = context.WithCancel(g.ctx)
74-
g.doneCtx, g.doneCtxCancel = context.WithCancel(g.ctx)
75+
g.managerCtx, g.managerCtxCancel = context.WithCancel(g.ctx)
76+
77+
// Next add pprof labels to these contexts
78+
g.terminateCtx = pprof.WithLabels(g.terminateCtx, pprof.Labels("graceful-lifecycle", "with-terminate"))
79+
g.shutdownCtx = pprof.WithLabels(g.shutdownCtx, pprof.Labels("graceful-lifecycle", "with-shutdown"))
80+
g.hammerCtx = pprof.WithLabels(g.hammerCtx, pprof.Labels("graceful-lifecycle", "with-hammer"))
81+
g.managerCtx = pprof.WithLabels(g.managerCtx, pprof.Labels("graceful-lifecycle", "with-manager"))
82+
83+
// Now label this and all goroutines created by this goroutine with the graceful-lifecycle manager
84+
pprof.SetGoroutineLabels(g.managerCtx)
85+
defer pprof.SetGoroutineLabels(g.ctx)
7586

7687
// Make channels
7788
g.shutdownRequested = make(chan struct{})

modules/process/manager.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"fmt"
1212
"io"
1313
"os/exec"
14+
"runtime/pprof"
1415
"sort"
1516
"strconv"
1617
"sync"
@@ -66,11 +67,9 @@ func GetManager() *Manager {
6667
// Most processes will not need to use the cancel function but there will be cases whereby you want to cancel the process but not immediately remove it from the
6768
// process table.
6869
func (pm *Manager) AddContext(parent context.Context, description string) (ctx context.Context, cancel context.CancelFunc, finished FinishedFunc) {
69-
parentPID := GetParentPID(parent)
70-
7170
ctx, cancel = context.WithCancel(parent)
7271

73-
pid, finished := pm.Add(parentPID, description, cancel)
72+
ctx, pid, finished := pm.Add(ctx, description, cancel)
7473

7574
return &Context{
7675
Context: ctx,
@@ -87,11 +86,9 @@ func (pm *Manager) AddContext(parent context.Context, description string) (ctx c
8786
// Most processes will not need to use the cancel function but there will be cases whereby you want to cancel the process but not immediately remove it from the
8887
// process table.
8988
func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Duration, description string) (ctx context.Context, cancel context.CancelFunc, finshed FinishedFunc) {
90-
parentPID := GetParentPID(parent)
91-
9289
ctx, cancel = context.WithTimeout(parent, timeout)
9390

94-
pid, finshed := pm.Add(parentPID, description, cancel)
91+
ctx, pid, finshed := pm.Add(ctx, description, cancel)
9592

9693
return &Context{
9794
Context: ctx,
@@ -100,7 +97,9 @@ func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Durati
10097
}
10198

10299
// Add create a new process
103-
func (pm *Manager) Add(parentPID IDType, description string, cancel context.CancelFunc) (IDType, FinishedFunc) {
100+
func (pm *Manager) Add(ctx context.Context, description string, cancel context.CancelFunc) (context.Context, IDType, FinishedFunc) {
101+
parentPID := GetParentPID(ctx)
102+
104103
pm.mutex.Lock()
105104
start, pid := pm.nextPID()
106105

@@ -120,6 +119,7 @@ func (pm *Manager) Add(parentPID IDType, description string, cancel context.Canc
120119
finished := func() {
121120
cancel()
122121
pm.remove(process)
122+
pprof.SetGoroutineLabels(ctx)
123123
}
124124

125125
if parent != nil {
@@ -128,7 +128,10 @@ func (pm *Manager) Add(parentPID IDType, description string, cancel context.Canc
128128
pm.processes[pid] = process
129129
pm.mutex.Unlock()
130130

131-
return pid, finished
131+
pprofCtx := pprof.WithLabels(ctx, pprof.Labels("process-description", description, "ppid", string(parentPID), "pid", string(pid)))
132+
pprof.SetGoroutineLabels(pprofCtx)
133+
134+
return pprofCtx, pid, finished
132135
}
133136

134137
// nextPID will return the next available PID. pm.mutex should already be locked.

options/locale/locale_cs-CZ.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1246,8 +1246,6 @@ issues.due_date_remove=odstranil/a termín dokončení %s %s
12461246
issues.due_date_overdue=Zpožděné
12471247
issues.due_date_invalid=Termín dokončení není platný nebo je mimo rozsah. Použijte prosím formát „rrrr-mm-dd“.
12481248
issues.dependency.title=Závislosti
1249-
issues.dependency.issue_no_dependencies=Tento úkol momentálně nemá žádné závislosti.
1250-
issues.dependency.pr_no_dependencies=Tento požadavek na natažení momentálně nemá žádné závislosti.
12511249
issues.dependency.add=Přidat závislost…
12521250
issues.dependency.cancel=Zrušit
12531251
issues.dependency.remove=Odstranit

options/locale/locale_de-DE.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1397,8 +1397,6 @@ issues.due_date_remove=hat %[2]s das Fälligkeitsdatum %[1]s entfernt
13971397
issues.due_date_overdue=Überfällig
13981398
issues.due_date_invalid=Das Fälligkeitsdatum ist ungültig oder außerhalb des zulässigen Bereichs. Bitte verwende das Format „jjjj-mm-tt“.
13991399
issues.dependency.title=Abhängigkeiten
1400-
issues.dependency.issue_no_dependencies=Dieses Issue hat momentan keine Abhängigkeiten.
1401-
issues.dependency.pr_no_dependencies=Dieser Pull-Request hat momentan keine Abhängigkeiten.
14021400
issues.dependency.add=Abhängigkeit hinzufügen…
14031401
issues.dependency.cancel=Abbrechen
14041402
issues.dependency.remove=Entfernen

options/locale/locale_el-GR.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1397,8 +1397,6 @@ issues.due_date_remove=αφαίρεσε την ημερομηνία παράδο
13971397
issues.due_date_overdue=Εκπρόθεσμο
13981398
issues.due_date_invalid=Η ημερομηνία παράδοσης δεν είναι έγκυρη ή εκτός εύρους. Παρακαλούμε χρησιμοποιήστε τη μορφή 'εεεε-μμ-ηη'.
13991399
issues.dependency.title=Εξαρτήσεις
1400-
issues.dependency.issue_no_dependencies=Αυτό το ζήτημα προς το παρόν δεν έχει καμία εξάρτηση.
1401-
issues.dependency.pr_no_dependencies=Αυτό το pull request προς το παρόν δεν έχει εξαρτήσεις.
14021400
issues.dependency.add=Προσθήκη εξάρτησης…
14031401
issues.dependency.cancel=Ακύρωση
14041402
issues.dependency.remove=Διαγραφή

options/locale/locale_es-ES.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1394,8 +1394,6 @@ issues.due_date_remove=eliminó la fecha de vencimiento %s %s
13941394
issues.due_date_overdue=Vencido
13951395
issues.due_date_invalid=La fecha de vencimiento es inválida o está fuera de rango. Por favor utilice el formato 'aaaa-mm-dd'.
13961396
issues.dependency.title=Dependencias
1397-
issues.dependency.issue_no_dependencies=Esta incidencia actualmente no tiene ninguna dependencia.
1398-
issues.dependency.pr_no_dependencies=Este pull request actualmente no tiene ninguna dependencia.
13991397
issues.dependency.add=Añadir dependencia…
14001398
issues.dependency.cancel=Cancelar
14011399
issues.dependency.remove=Eliminar

options/locale/locale_fa-IR.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1320,8 +1320,6 @@ issues.due_date_remove=موعد مقرر %s %s حذف شد
13201320
issues.due_date_overdue=تاریخ گذشته
13211321
issues.due_date_invalid=موعد مقرر نامعتبر است یا خارج از محدوده. لطفاً از قالب 'yyy-mm-dd' استفاده کنید.
13221322
issues.dependency.title=وابستگی ها
1323-
issues.dependency.issue_no_dependencies=این مسئله در حال حاضر هیچ وابستگی ندارد.
1324-
issues.dependency.pr_no_dependencies=این تقاضای واکشی در حال حاضر هیچ وابستگی ندارد.
13251323
issues.dependency.add=اضافه کردن وابستگی…
13261324
issues.dependency.cancel=انصراف
13271325
issues.dependency.remove=حذف/ساقط کردن

options/locale/locale_fi-FI.ini

-1
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,6 @@ issues.due_date_form_edit=Muokkaa
731731
issues.due_date_form_remove=Poista
732732
issues.due_date_not_set=Määräpäivää ei asetettu.
733733
issues.dependency.title=Riippuvuudet
734-
issues.dependency.pr_no_dependencies=Tällä vetopyynnöllä ei tällä hetkellä ole riippuvuuksia.
735734
issues.dependency.add=Lisää riippuvuus…
736735
issues.dependency.cancel=Peru
737736
issues.dependency.remove=Poista

options/locale/locale_fr-FR.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1253,8 +1253,6 @@ issues.due_date_remove=a supprimé l'échéance %s %s
12531253
issues.due_date_overdue=En retard
12541254
issues.due_date_invalid=La date d’échéance est invalide ou hors plage. Veuillez utiliser le format 'aaaa-mm-dd'.
12551255
issues.dependency.title=Dépendances
1256-
issues.dependency.issue_no_dependencies=Ce ticket n'a actuellement pas de dépendance.
1257-
issues.dependency.pr_no_dependencies=La demande de fusion n'a actuellement pas de dépendance.
12581256
issues.dependency.add=Ajouter une dépendance…
12591257
issues.dependency.cancel=Annuler
12601258
issues.dependency.remove=Supprimer

options/locale/locale_hu-HU.ini

-1
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,6 @@ issues.due_date_modified=határidő módosítva %s-ről %s %s-re
930930
issues.due_date_remove=%s %s-es határidő eltávolítva
931931
issues.due_date_overdue=Lejárt
932932
issues.dependency.title=Függőségek
933-
issues.dependency.issue_no_dependencies=Ennek a hibajegynek jelenleg nincsenek függőségei.
934933
issues.dependency.add=Függőség hozzáadása…
935934
issues.dependency.cancel=Mégse
936935
issues.dependency.remove=Eltávolítás

options/locale/locale_it-IT.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1135,8 +1135,6 @@ issues.due_date_remove=rimossa la data di scadenza %s %s
11351135
issues.due_date_overdue=Scaduto
11361136
issues.due_date_invalid=La data di scadenza non è valida o fuori intervallo. Si prega di utilizzare il formato 'aaaa-mm-dd'.
11371137
issues.dependency.title=Dipendenze
1138-
issues.dependency.issue_no_dependencies=Questo problema attualmente non ha alcuna dipendenza.
1139-
issues.dependency.pr_no_dependencies=Questo problema attualmente non ha alcuna dipendenza.
11401138
issues.dependency.add=Aggiungi dipendenza…
11411139
issues.dependency.cancel=Annulla
11421140
issues.dependency.remove=Rimuovi

options/locale/locale_ja-JP.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1418,8 +1418,6 @@ issues.due_date_remove=が期日 %s を削除 %s
14181418
issues.due_date_overdue=期日は過ぎています
14191419
issues.due_date_invalid=期日が正しくないか範囲を超えています。 'yyyy-mm-dd' の形式で入力してください。
14201420
issues.dependency.title=依存関係
1421-
issues.dependency.issue_no_dependencies=このイシューに依存関係はありません。
1422-
issues.dependency.pr_no_dependencies=このプルリクエストに依存関係はありません。
14231421
issues.dependency.add=依存関係を追加...
14241422
issues.dependency.cancel=キャンセル
14251423
issues.dependency.remove=削除

options/locale/locale_ko-KR.ini

-2
Original file line numberDiff line numberDiff line change
@@ -816,8 +816,6 @@ issues.due_date_remove=%s %s 마감일이 삭제되었습니다.
816816
issues.due_date_overdue=기한 초과
817817
issues.due_date_invalid=기한이 올바르지 않거나 범위를 벗어났습니다. 'yyyy-mm-dd'형식을 사용해주십시오.
818818
issues.dependency.title=의존성
819-
issues.dependency.issue_no_dependencies=이 이슈는 어떠한 의존성도 가지지 않습니다.
820-
issues.dependency.pr_no_dependencies=이 풀 리퀘스트는 어떠한 의존성도 가지지 않습니다.
821819
issues.dependency.add=의존성 추가...
822820
issues.dependency.cancel=취소
823821
issues.dependency.remove=제거

options/locale/locale_lv-LV.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1382,8 +1382,6 @@ issues.due_date_remove=noņēma izpildes termiņu %s %s
13821382
issues.due_date_overdue=Nokavēts
13831383
issues.due_date_invalid=Datums līdz nav korekts. Izmantojiet formātu 'gggg-mm-dd'.
13841384
issues.dependency.title=Atkarības
1385-
issues.dependency.issue_no_dependencies=Šai problēmai pagaidām nav nevienas atkarības.
1386-
issues.dependency.pr_no_dependencies=Šim izmaiņu pieprasījumam pagaidām nav nevienas atkarības.
13871385
issues.dependency.add=Pievienot atkarību…
13881386
issues.dependency.cancel=Atcelt
13891387
issues.dependency.remove=Noņemt

options/locale/locale_nl-NL.ini

-2
Original file line numberDiff line numberDiff line change
@@ -1152,8 +1152,6 @@ issues.due_date_remove=heeft %[2]s de deadline %[1]s verwijderd
11521152
issues.due_date_overdue=Over tijd
11531153
issues.due_date_invalid=De deadline is ongeldig of buiten bereik. Gebruik het formaat 'jjjj-mm-dd'.
11541154
issues.dependency.title=Afhankelijkheden
1155-
issues.dependency.issue_no_dependencies=Deze kwestie heeft momenteel geen afhankelijkheden.
1156-
issues.dependency.pr_no_dependencies=Deze pull-aanvraag heeft momenteel geen afhankelijkheden.
11571155
issues.dependency.add=Voeg afhankelijkheid toe…
11581156
issues.dependency.cancel=Annuleer
11591157
issues.dependency.remove=Verwijder

0 commit comments

Comments
 (0)