Commit 1fd8d300 authored by Matija Čupić's avatar Matija Čupić

Merge branch 'master' into...

Merge branch 'master' into 39957-redirect-to-gpc-page-if-users-try-to-create-a-cluster-but-the-account-is-not-enabled
parents d13be3c2 54bacb18
{"iconCount":186,"spriteSize":84748,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]} {"iconCount":189,"spriteSize":85766,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o-open","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","staged","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","unstaged","user","users","volume-up","warning","work"]}
\ No newline at end of file \ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
<svg xmlns="http://www.w3.org/2000/svg" width="430" height="300"><g fill="none" fill-rule="evenodd" transform="translate(35 29)"><path fill="#EEE" fill-rule="nonzero" d="M90 23a2 2 0 1 1 0-4h10a2 2 0 0 1 0 4H90zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h10a2 2 0 0 1 0 4h-10zm20 0a2 2 0 0 1 0-4h1a11.98 11.98 0 0 1 9.457 4.612 2 2 0 0 1-3.151 2.464A7.981 7.981 0 0 0 331 23h-1zm9 11.39a2 2 0 0 1 4 0v10a2 2 0 0 1-4 0v-10zm0 180a2 2 0 1 1 4 0V223c0 .56-.038 1.114-.114 1.662a2 2 0 0 1-3.962-.55A8.21 8.21 0 0 0 339 223v-8.61zm-4.769 15.931a2 2 0 0 1 1.618 3.658A11.967 11.967 0 0 1 331 235h-5.782a2 2 0 0 1 0-4H331c1.13 0 2.224-.233 3.231-.679zm-19.013.679a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zm-20 0a2 2 0 1 1 0 4h-10a2 2 0 0 1 0-4h10zM115 231a2 2 0 0 1 0 4h-10a2 2 0 0 1 0-4h10zm-26.2 4c.131-.646.2-1.315.2-2v-2h4a2 2 0 0 1 0 4h-4.2z"/><path fill="#EEE" fill-rule="nonzero" d="M103 211h258a6 6 0 0 0 6-6V63a6 6 0 0 0-6-6H166a5 5 0 0 1-5-5v-8.5a5.5 5.5 0 0 0-5.5-5.5H109a6 6 0 0 0-6 6v167zm62-167.5V52a1 1 0 0 0 1 1h195c5.523 0 10 4.477 10 10v142c0 5.523-4.477 10-10 10H99V44c0-5.523 4.477-10 10-10h46.5a9.5 9.5 0 0 1 9.5 9.5z"/><rect width="40" height="4" x="118" y="78" fill="#6B4FBB" rx="2"/><rect width="30" height="4" x="118" y="90" fill="#EFEDF8" rx="2"/><rect width="30" height="4" x="153" y="90" fill="#E1DBF1" rx="2"/><rect width="150" height="4" x="118" y="102" fill="#EFEDF8" rx="2"/><rect width="90" height="4" x="118" y="114" fill="#E1DBF1" rx="2"/><rect width="60" height="4" x="118" y="138" fill="#EFEDF8" rx="2"/><rect width="20" height="4" x="118" y="150" fill="#6B4FBB" rx="2"/><rect width="20" height="4" x="144" y="150" fill="#C3B8E3" rx="2"/><rect width="20" height="4" x="170" y="150" fill="#E1DBF1" rx="2"/><rect width="130" height="4" x="118" y="162" fill="#EFEDF8" rx="2"/><rect width="30" height="4" x="118" y="174" fill="#C3B8E3" rx="2"/><rect width="30" height="4" x="154" y="174" fill="#EFEDF8" rx="2"/><rect width="30" height="4" x="190" y="174" fill="#EFEDF8" rx="2"/><rect width="40" height="4" x="118" y="186" fill="#E1DBF1" rx="2"/><path fill="#F9F9F9" d="M89 24.292l11.434 19.326v170.326L89 226.336V24.292z"/><path fill="#EEE" fill-rule="nonzero" d="M89 229.286v-5.9l9.434-10.223V44.165L89 28.22v-7.856l13.434 22.707v171.655L89 229.286zM10 4a6 6 0 0 0-6 6v223a6 6 0 0 0 6 6h69a6 6 0 0 0 6-6V10a6 6 0 0 0-6-6H10zm0-4h69c5.523 0 10 4.477 10 10v223c0 5.523-4.477 10-10 10H10c-5.523 0-10-4.477-10-10V10C0 4.477 4.477 0 10 0z"/><circle cx="25" cy="23" r="11" fill="#FEF0E8"/><path fill="#FEE1D3" d="M46 17h16a2 2 0 1 1 0 4H46a2 2 0 1 1 0-4zm0 8h27a2 2 0 1 1 0 4H46a2 2 0 1 1 0-4z"/><path fill="#EEE" d="M16 50h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-4 12h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H40a2 2 0 1 1 0-4zM26 78h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H40a2 2 0 1 1 0-4z"/><g transform="translate(14 110)"><rect width="8" height="8" fill="#FEE1D3" rx="2"/><rect width="28" height="4" x="14" y="2" fill="#FEF0E8" rx="2"/></g><path fill="#EEE" d="M16 140h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-14 14h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-14 14h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4zm-14 14h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm14 2h24a2 2 0 1 1 0 4H30a2 2 0 1 1 0-4z"/><g transform="translate(24 124)"><rect width="8" height="8" fill="#FEE1D3" rx="2"/><rect width="28" height="4" x="14" y="2" fill="#FEF0E8" rx="2"/></g><g fill="#FC6D26" transform="translate(24 92)"><rect width="8" height="8" rx="2"/><rect width="28" height="4" x="14" y="2" rx="2"/></g><path fill="#FDC4A8" fill-rule="nonzero" d="M152 50.5a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9zm0-3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="386" height="298" viewBox="0 0 386 298" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="a" d="M4 51h16v15.997A5.003 5.003 0 0 1 15.003 72H8.997A5.005 5.005 0 0 1 4 66.997V51z"/><rect id="b" width="24" height="10" y="44" rx="3"/></defs><g fill="none" fill-rule="evenodd" transform="translate(0 3)"><g transform="rotate(15 23.151 968.24)"><rect width="53" height="44" fill="#FFF" stroke="#FDE5D8" stroke-width="3" stroke-linecap="round" rx="5"/><path fill="#FDE5D8" d="M29.5 28.3l2.758-3.861c.962-1.347 2.527-1.34 3.484 0l6.516 9.122c.962 1.347.399 2.439-1.252 2.439H17.994c-1.653 0-2.21-1.099-1.252-2.439l6.516-9.122c.962-1.347 2.527-1.34 3.484 0L29.5 28.3z" opacity=".6"/><circle cx="16" cy="16" r="6" fill="#FDB997"/></g><g transform="scale(-1 1) rotate(25 -75.08 -334.15)"><rect width="3" height="11" x="12.45" y="23.45" fill="#6B4FBB" transform="rotate(45 13.95 28.95)" rx="1.5"/><rect width="3" height="14" x="9.45" y="15.45" fill="#6B4FBB" transform="rotate(45 10.95 22.45)" rx="1.5"/><path fill="#FFF" stroke="#E1DCF1" stroke-width="3" d="M16 39.6C6.871 37.747 0 29.676 0 20 0 8.954 8.954 0 20 0s20 8.954 20 20c0 8.955-5.886 16.536-14 19.084v15.91A5.007 5.007 0 0 1 21 60c-2.761 0-5-2.244-5-5.006V39.6zm4-7.6c6.627 0 12-5.373 12-12S26.627 8 20 8 8 13.373 8 20s5.373 12 12 12z"/></g><g transform="scale(1 -1) rotate(-15 -383.616 -172.407)"><path stroke="#FDE5D8" stroke-width="3" d="M1.5 38.5h9V4c0-1.378-1.12-2.5-2.496-2.5H3.996A2.503 2.503 0 0 0 1.5 4v34.5z"/><rect width="2" height="27" x="5" y="7" fill="#FDA77D" opacity=".8" rx="1"/><path stroke="#FDE5D8" stroke-width="3" d="M2.427 41.553h7.146L6 48.699l-3.573-7.146z"/></g><g transform="rotate(-30 420.145 -545.422)"><path fill="#FFF" stroke="#FDE5D8" stroke-width="3" d="M9 3c0-1.657 1.347-3 3-3 1.657 0 3 1.352 3 3v43H9V3z"/><use fill="#FFF" xlink:href="#a"/><path stroke="#FDE5D8" stroke-width="3" d="M5.5 52.5v14.497A3.505 3.505 0 0 0 8.997 70.5h6.006a3.503 3.503 0 0 0 3.497-3.503V52.5h-13z"/><rect width="2" height="14" x="9" y="51" fill="#FDA77D" rx="1"/><rect width="2" height="14" x="13" y="51" fill="#FDA77D" rx="1"/><use fill="#FFF" xlink:href="#b"/><rect width="21" height="7" x="1.5" y="45.5" stroke="#FDE5D8" stroke-width="3" rx="3"/></g><g transform="translate(72 97.488)"><rect width="125" height="160" fill="#FFF" stroke="#E5E5E5" stroke-width="4" stroke-linecap="round" rx="10"/><rect width="125" height="160" x="125" fill="#FFF" stroke="#E5E5E5" stroke-width="4" stroke-linecap="round" rx="10"/><path fill="#FFF" stroke="#E5E5E5" stroke-width="4" d="M7 12.008C7 8.69 9.686 6 12.993 6H125v148H12.993C9.683 154 7 151.305 7 147.992V12.008zm236 0C243 8.69 240.314 6 237.007 6H125v148h112.007c3.31 0 5.993-2.695 5.993-6.008V12.008z" stroke-linecap="round"/><rect width="84" height="42" x="142" y="29" stroke="#EEE" stroke-width="4" rx="3"/><rect width="88" height="4" x="141" y="93" fill="#E5E5E5" rx="2"/><rect width="88" height="4" x="141" y="107" fill="#BFBFBF" rx="2"/><rect width="56" height="4" x="141" y="121" fill="#E5E5E5" rx="2"/><rect width="56" height="4" x="22" y="93" fill="#E5E5E5" rx="2"/><rect width="26" height="4" x="22" y="27" fill="#BFBFBF" rx="2"/><rect width="56" height="4" x="22" y="41" fill="#E5E5E5" rx="2"/><rect width="36" height="4" x="22" y="55" fill="#BFBFBF" rx="2"/><rect width="56" height="4" x="22" y="69" fill="#E5E5E5" rx="2"/><rect width="36" height="4" x="22" y="107" fill="#E5E5E5" rx="2"/><rect width="56" height="4" x="22" y="121" fill="#BFBFBF" rx="2"/></g><path stroke="#B5A7DD" stroke-width="2.5" d="M23.139 182.922l-1.347-.6a2.004 2.004 0 0 1-1.02-2.64l.815-1.831a1.995 1.995 0 0 1 2.645-1.01l1.308.583a9.959 9.959 0 0 1 2.177-1.876l-.376-1.402a2.004 2.004 0 0 1 1.41-2.455l1.937-.519a1.995 1.995 0 0 1 2.449 1.421l.375 1.402a9.959 9.959 0 0 1 2.824.536l.84-1.158a2.004 2.004 0 0 1 2.796-.448l1.622 1.178a1.995 1.995 0 0 1 .437 2.797l-.867 1.193a9.946 9.946 0 0 1 1.341 2.541l1.461-.05a2.004 2.004 0 0 1 2.075 1.926l.07 2.003a1.995 1.995 0 0 1-1.935 2.067l-1.445.05c-.256.93-.644 1.817-1.15 2.632l.944 1.087a2.004 2.004 0 0 1-.191 2.825l-1.513 1.315a1.995 1.995 0 0 1-2.824-.204l-.963-1.108a10.084 10.084 0 0 1-2.776.744l-.28 1.441a2.004 2.004 0 0 1-2.344 1.588l-1.967-.382a1.995 1.995 0 0 1-1.579-2.35l.275-1.414a10.044 10.044 0 0 1-2.312-1.704l-1.277.678a2.004 2.004 0 0 1-2.709-.822l-.94-1.77a1.995 1.995 0 0 1 .833-2.705l1.29-.687a9.946 9.946 0 0 1-.11-2.872zm10.98 4.93a4 4 0 1 0-2.07-7.727 4 4 0 0 0 2.07 7.728z"/><ellipse cx="197" cy="289.988" fill="#F9F9F9" rx="125" ry="4.5"/><path fill="#6B4FBB" d="M164 100.492a3.002 3.002 0 0 1 3.001-3.004H183a3.006 3.006 0 0 1 3.001 3.004v34.988c0 2.213-1.45 2.954-3.24 1.651l-7.76-5.643-7.76 5.643c-1.789 1.302-3.24.566-3.24-1.651v-34.988z"/><g opacity=".2"><path fill="#FC8A51" d="M5.747 234.768l-2.688 1.114c-1.017.422-1.803-.134-1.754-1.228l.128-2.907-1.115-2.688c-.422-1.017.135-1.803 1.229-1.754l2.907.128 2.687-1.115c1.018-.422 1.803.135 1.755 1.229l-.128 2.907 1.114 2.687c.422 1.018-.134 1.803-1.228 1.755l-2.907-.128zM191.564 37.953l-3.72.164c-1.326.059-1.992-.88-1.48-2.115l1.426-3.438-.164-3.72c-.059-1.326.88-1.992 2.115-1.48l3.438 1.426 3.72-.164c1.326-.059 1.992.88 1.48 2.114l-1.426 3.44.164 3.719c.059 1.326-.88 1.992-2.114 1.48l-3.44-1.426z"/><path fill="#6B4FBB" d="M348.789 75.876l-1.967-2.144c-.744-.812-.49-1.74.555-2.07l2.775-.873 2.144-1.967c.812-.744 1.74-.49 2.07.555l.873 2.775 1.967 2.144c.744.812.49 1.74-.555 2.07l-2.775.873-2.144 1.967c-.812.745-1.74.49-2.07-.555l-.873-2.775zm9.261 164.735l-2.907-.125c-1.1-.048-1.577-.884-1.07-1.855l1.344-2.58.126-2.908c.047-1.1.883-1.577 1.855-1.07l2.58 1.344 2.907.126c1.1.047 1.577.883 1.07 1.855l-1.344 2.58-.125 2.907c-.048 1.1-.884 1.577-1.856 1.07l-2.58-1.344zM88.789 75.876l-1.967-2.144c-.744-.812-.49-1.74.555-2.07l2.775-.873 2.144-1.967c.812-.744 1.74-.49 2.07.555l.873 2.775 1.967 2.144c.744.812.49 1.74-.555 2.07l-2.775.873-2.144 1.967c-.812.745-1.74.49-2.07-.555l-.873-2.775z"/></g></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="412" height="260" viewBox="0 0 412 260" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="a" d="M6.447.894L12 12H0L5.553.894a.5.5 0 0 1 .894 0z"/></defs><g fill="none" fill-rule="evenodd"><path fill="#FEF0E8" fill-rule="nonzero" d="M338 50.287C322.695 41.45 303.124 46.694 294.287 62c-8.836 15.305-3.592 34.876 11.713 43.712 15.306 8.837 34.877 3.593 43.713-11.712 8.837-15.306 3.593-34.877-11.713-43.713zm2-3.464C357.22 56.763 363.118 78.78 353.177 96c-9.941 17.218-31.958 23.118-49.177 13.176-17.218-9.94-23.118-31.958-13.177-49.176C300.764 42.78 322.782 36.88 340 46.823z"/><g transform="rotate(-150 171.003 8.53)"><path fill="#FC6D26" fill-rule="nonzero" d="M4 16v25a2 2 0 1 0 4 0V16H4zm8-4v29a6 6 0 1 1-12 0V12h12z"/><use fill="#D8D8D8" xlink:href="#a"/><path stroke="#FDC4A8" stroke-width="4" d="M6 4.472L3.236 10h5.528L6 4.472z"/><path fill="#FC6D26" d="M9 6L6.447.894a.5.5 0 0 0-.894 0L3 6c.836.628 1.874 1 3 1a4.978 4.978 0 0 0 3-1z"/></g><path fill="#F9F9F9" d="M263.116 237.116A10.002 10.002 0 0 1 254 243h-86c-11.046 0-20-8.954-20-20V121c0-4.056 2.414-7.547 5.884-9.116A9.964 9.964 0 0 0 153 116v106c0 8.837 7.163 16 16 16h90c1.467 0 2.86-.316 4.116-.884z"/><path fill="#EEE" fill-rule="nonzero" d="M214.5 106H163c-5.523 0-10 4.477-10 10v106c0 8.837 7.163 16 16 16h90c5.523 0 10-4.477 10-10v-17.999a10.036 10.036 0 0 1-4 3.167V228a6 6 0 0 1-6 6h-90c-6.627 0-12-5.373-12-12V116a6 6 0 0 1 6-6h7v-4h44.5z"/><path fill="#EEE" fill-rule="nonzero" d="M260 218.268V214h-90a6 6 0 0 0 0 12h86a4 4 0 0 0 4-4v-.268a1.99 1.99 0 0 1-1 .268h-50a2 2 0 0 1 0-4h50c.364 0 .706.097 1 .268zM170 210h90.5a3.5 3.5 0 0 1 3.5 3.5v8.5a8 8 0 0 1-8 8h-86c-5.523 0-10-4.477-10-10s4.477-10 10-10z"/><path fill="#EEE" fill-rule="nonzero" d="M174 110v100h87a6 6 0 0 0 6-6v-88a6 6 0 0 0-6-6h-87zm-4-4h91c5.523 0 10 4.477 10 10v88c0 5.523-4.477 10-10 10h-91V106z"/><path fill="#EFEDF8" d="M230 99h18a6 6 0 0 1 6 6v31.35a3 3 0 0 1-4.68 2.484l-9.277-6.274a1.5 1.5 0 0 0-1.664-.01l-9.731 6.395a3 3 0 0 1-4.648-2.507V105a6 6 0 0 1 6-6z"/><path fill="#C3B8E3" fill-rule="nonzero" d="M236.182 129.207a5.5 5.5 0 0 1 6.102.04l7.716 5.219V105a2 2 0 0 0-2-2h-18a2 2 0 0 0-2 2v29.584l8.182-5.377zM230 99h18a6 6 0 0 1 6 6v31.35a3 3 0 0 1-4.68 2.484l-9.277-6.274a1.5 1.5 0 0 0-1.664-.01l-9.731 6.395a3 3 0 0 1-4.648-2.507V105a6 6 0 0 1 6-6z"/><g fill-rule="nonzero"><path fill="#EFEDF8" d="M156 74c14.912 0 27-12.088 27-27s-12.088-27-27-27-27 12.088-27 27 12.088 27 27 27zm0 4c-17.12 0-31-13.88-31-31s13.88-31 31-31 31 13.88 31 31-13.88 31-31 31z"/><path fill="#6B4FBB" d="M147.535 44.916l-.116 1.086a8.446 8.446 0 0 0 .093 2.44l.2 1.08-2.262 1.202a.495.495 0 0 0-.213.678l.941 1.77c.128.239.434.332.68.201l2.25-1.196.785.775a8.544 8.544 0 0 0 1.967 1.45l.975.522-.486 2.5a.495.495 0 0 0 .392.59l1.968.383a.504.504 0 0 0 .585-.401l.489-2.515 1.086-.13a8.584 8.584 0 0 0 2.363-.633l1.005-.43 1.68 1.933a.495.495 0 0 0 .708.055l1.513-1.315a.504.504 0 0 0 .044-.708l-1.67-1.922.583-.94c.431-.696.761-1.45.978-2.239l.292-1.063 2.547-.089a.495.495 0 0 0 .488-.515l-.07-2.003a.504.504 0 0 0-.523-.48l-2.56.09-.367-1.037a8.446 8.446 0 0 0-1.139-2.159l-.644-.882 1.509-2.076a.495.495 0 0 0-.106-.702l-1.621-1.178a.504.504 0 0 0-.7.116l-1.494 2.057-1.05-.362a8.459 8.459 0 0 0-2.398-.455l-1.1-.047-.66-2.466a.495.495 0 0 0-.613-.36l-1.936.519a.504.504 0 0 0-.35.617l.661 2.466-.93.59a8.459 8.459 0 0 0-1.848 1.594l-.728.838-2.322-1.034a.495.495 0 0 0-.665.25l-.815 1.83a.504.504 0 0 0 .26.661l2.344 1.044zm-3.565 1.697a3.504 3.504 0 0 1-1.78-4.622l.815-1.83a3.495 3.495 0 0 1 4.626-1.77l.346.154c.259-.245.529-.477.81-.697l-.106-.394a3.504 3.504 0 0 1 2.471-4.292l1.936-.519a3.495 3.495 0 0 1 4.286 2.481l.106.395c.353.05.703.116 1.05.198l.222-.306a3.504 3.504 0 0 1 4.89-.78l1.622 1.178a3.495 3.495 0 0 1 .769 4.892l-.258.355c.184.312.354.633.508.962l.42-.014a3.504 3.504 0 0 1 3.625 3.373l.07 2.003a3.495 3.495 0 0 1-3.382 3.618l-.4.014c-.127.332-.27.659-.426.978l.256.294a3.504 3.504 0 0 1-.34 4.941l-1.512 1.315a3.495 3.495 0 0 1-4.94-.351l-.283-.325a11.669 11.669 0 0 1-1.05.28l-.082.424a3.504 3.504 0 0 1-4.103 2.774l-1.967-.382a3.495 3.495 0 0 1-2.765-4.11l.075-.383a11.547 11.547 0 0 1-.858-.633l-.354.188a3.504 3.504 0 0 1-4.738-1.442l-.94-1.77a3.495 3.495 0 0 1 1.453-4.734l.37-.197a11.436 11.436 0 0 1-.041-1.088l-.4-.178zm13.326 5.608a5.5 5.5 0 1 1-2.847-10.625 5.5 5.5 0 0 1 2.847 10.625zm-.776-2.898a2.5 2.5 0 1 0-1.294-4.83 2.5 2.5 0 0 0 1.294 4.83z"/></g><g fill-rule="nonzero"><path fill="#EFEDF8" d="M326.979 222.047c14.403 3.86 29.209-4.688 33.068-19.092 3.86-14.403-4.688-29.209-19.092-33.068-14.403-3.86-29.209 4.688-33.068 19.092-3.86 14.404 4.688 29.209 19.092 33.068zm-1.035 3.864c-16.538-4.431-26.352-21.43-21.92-37.967 4.43-16.538 21.429-26.352 37.966-21.92 16.538 4.43 26.352 21.429 21.92 37.966-4.43 16.538-21.429 26.352-37.966 21.92z"/><path fill="#6B4FBB" d="M329.376 201.598c-4.668-2.621-7.155-8.157-5.706-13.566 1.715-6.402 8.295-10.201 14.697-8.486 6.402 1.716 10.2 8.296 8.485 14.697-1.45 5.41-6.371 8.96-11.725 8.897a3.03 3.03 0 0 1-.074.365l-1.812 6.761a3 3 0 0 1-5.795-1.552l1.812-6.762a3.03 3.03 0 0 1 .118-.354zm3.815-2.733a8 8 0 1 0 4.14-15.455 8 8 0 0 0-4.14 15.455z"/></g><path fill="#FEF0E8" fill-rule="nonzero" d="M91.373 193c17.071-4.574 27.202-22.12 22.628-39.191-4.575-17.071-22.121-27.202-39.192-22.628-17.071 4.574-27.202 22.121-22.628 39.192 4.574 17.071 22.121 27.202 39.192 22.627zm1.035 3.864c-19.204 5.146-38.945-6.25-44.09-25.456-5.146-19.204 6.25-38.945 25.455-44.09 19.205-5.146 38.945 6.25 44.091 25.455 5.146 19.205-6.25 38.945-25.456 44.091z"/><path fill="#FDC4A8" fill-rule="nonzero" d="M70.067 152.122l6.73 25.114 19.318-5.176-6.73-25.114-19.318 5.176zm-1.035-3.864l19.318-5.176a4 4 0 0 1 4.9 2.828l6.729 25.114a4 4 0 0 1-2.829 4.9L77.832 181.1a4 4 0 0 1-4.9-2.829l-6.729-25.114a4 4 0 0 1 2.829-4.899z"/><path fill="#FC6D26" d="M76.898 154.433l7.727-2.07a2 2 0 0 1 1.036 3.863l-7.728 2.07a2 2 0 1 1-1.035-3.863zm1.812 6.761l5.795-1.553a2 2 0 0 1 1.035 3.864l-5.795 1.553a2 2 0 1 1-1.035-3.864zm1.811 6.762l7.728-2.07a2 2 0 0 1 1.035 3.863l-7.727 2.07a2 2 0 1 1-1.036-3.863z"/></g></svg>
\ No newline at end of file
...@@ -9,6 +9,12 @@ import repoPreview from './repo_preview.vue'; ...@@ -9,6 +9,12 @@ import repoPreview from './repo_preview.vue';
import repoEditor from './repo_editor.vue'; import repoEditor from './repo_editor.vue';
export default { export default {
props: {
emptyStateSvgPath: {
type: String,
required: true,
},
},
computed: { computed: {
...mapState([ ...mapState([
'currentBlobView', 'currentBlobView',
...@@ -64,7 +70,23 @@ export default { ...@@ -64,7 +70,23 @@ export default {
<template <template
v-else> v-else>
<div class="ide-empty-state"> <div class="ide-empty-state">
<h2 class="clgray">Welcome to the GitLab IDE</h2> <div class="row js-empty-state">
<div class="col-xs-12">
<div class="svg-content svg-250">
<img :src="emptyStateSvgPath">
</div>
</div>
<div class="col-xs-12">
<div class="text-content text-center">
<h4>
Welcome to the GitLab IDE
</h4>
<p>
You can select a file in the left sidebar to begin editing and use the right sidebar to commit your changes.
</p>
</div>
</div>
</div>
</div> </div>
</template> </template>
</div> </div>
......
<script> <script>
import { mapState } from 'vuex'; import { mapState } from 'vuex';
import RepoPreviousDirectory from './repo_prev_directory.vue'; import repoPreviousDirectory from './repo_prev_directory.vue';
import RepoFile from './repo_file.vue'; import repoFile from './repo_file.vue';
import RepoLoadingFile from './repo_loading_file.vue'; import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
import { treeList } from '../stores/utils'; import { treeList } from '../stores/utils';
export default { export default {
components: { components: {
'repo-previous-directory': RepoPreviousDirectory, repoPreviousDirectory,
'repo-file': RepoFile, repoFile,
'repo-loading-file': RepoLoadingFile, skeletonLoadingContainer,
}, },
props: { props: {
treeId: { treeId: {
...@@ -19,7 +19,7 @@ export default { ...@@ -19,7 +19,7 @@ export default {
}, },
computed: { computed: {
...mapState([ ...mapState([
'loading', 'trees',
'isRoot', 'isRoot',
]), ]),
...mapState({ ...mapState({
...@@ -34,7 +34,10 @@ export default { ...@@ -34,7 +34,10 @@ export default {
return !this.isRoot && this.fetchedList.length; return !this.isRoot && this.fetchedList.length;
}, },
showLoading() { showLoading() {
return this.loading; if (this.trees[this.treeId]) {
return this.trees[this.treeId].loading;
}
return true;
}, },
}, },
}; };
...@@ -49,11 +52,13 @@ export default { ...@@ -49,11 +52,13 @@ export default {
<repo-previous-directory <repo-previous-directory
v-if="hasPreviousDirectory" v-if="hasPreviousDirectory"
/> />
<repo-loading-file <div
class="multi-file-loading-container"
v-if="showLoading" v-if="showLoading"
v-for="n in 5" v-for="n in 3"
:key="n" :key="n">
/> <skeleton-loading-container/>
</div>
<repo-file <repo-file
v-for="file in fetchedList" v-for="file in fetchedList"
:key="file.key" :key="file.key"
......
...@@ -3,6 +3,7 @@ import { mapState, mapActions } from 'vuex'; ...@@ -3,6 +3,7 @@ import { mapState, mapActions } from 'vuex';
import projectTree from './ide_project_tree.vue'; import projectTree from './ide_project_tree.vue';
import icon from '../../vue_shared/components/icon.vue'; import icon from '../../vue_shared/components/icon.vue';
import panelResizer from '../../vue_shared/components/panel_resizer.vue'; import panelResizer from '../../vue_shared/components/panel_resizer.vue';
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
export default { export default {
data() { data() {
...@@ -14,9 +15,11 @@ export default { ...@@ -14,9 +15,11 @@ export default {
projectTree, projectTree,
icon, icon,
panelResizer, panelResizer,
skeletonLoadingContainer,
}, },
computed: { computed: {
...mapState([ ...mapState([
'loading',
'projects', 'projects',
'leftPanelCollapsed', 'leftPanelCollapsed',
]), ]),
...@@ -32,6 +35,9 @@ export default { ...@@ -32,6 +35,9 @@ export default {
} }
return {}; return {};
}, },
showLoading() {
return this.loading;
},
}, },
methods: { methods: {
...mapActions([ ...mapActions([
...@@ -63,6 +69,13 @@ export default { ...@@ -63,6 +69,13 @@ export default {
:style="panelStyle" :style="panelStyle"
> >
<div class="multi-file-commit-panel-inner"> <div class="multi-file-commit-panel-inner">
<div
class="multi-file-loading-container"
v-if="showLoading"
v-for="n in 3"
:key="n">
<skeleton-loading-container/>
</div>
<project-tree <project-tree
v-for="(project, index) in projects" v-for="(project, index) in projects"
:key="project.id" :key="project.id"
......
import Vue from 'vue'; import Vue from 'vue';
import { mapActions } from 'vuex';
import { convertPermissionToBoolean } from '../lib/utils/common_utils';
import ide from './components/ide.vue'; import ide from './components/ide.vue';
import store from './stores'; import store from './stores';
import router from './ide_router'; import router from './ide_router';
import Translate from '../vue_shared/translate'; import Translate from '../vue_shared/translate';
import ContextualSidebar from '../contextual_sidebar';
function initIde(el) { function initIde(el) {
if (!el) return null; if (!el) return null;
...@@ -18,30 +14,13 @@ function initIde(el) { ...@@ -18,30 +14,13 @@ function initIde(el) {
components: { components: {
ide, ide,
}, },
methods: { render(createElement) {
...mapActions([ return createElement('ide', {
'setInitialData', props: {
]), emptyStateSvgPath: el.dataset.emptyStateSvgPath,
},
created() {
const data = el.dataset;
this.setInitialData({
endpoints: {
rootEndpoint: data.url,
newMergeRequestUrl: data.newMergeRequestUrl,
rootUrl: data.rootUrl,
}, },
canCommit: convertPermissionToBoolean(data.canCommit),
onTopOfBranch: convertPermissionToBoolean(data.onTopOfBranch),
path: data.currentPath,
isRoot: convertPermissionToBoolean(data.root),
isInitialRoot: convertPermissionToBoolean(data.root),
}); });
}, },
render(createElement) {
return createElement('ide');
},
}); });
} }
...@@ -50,6 +29,3 @@ const ideElement = document.getElementById('ide'); ...@@ -50,6 +29,3 @@ const ideElement = document.getElementById('ide');
Vue.use(Translate); Vue.use(Translate);
initIde(ideElement); initIde(ideElement);
const contextualSidebar = new ContextualSidebar();
contextualSidebar.bindEvents();
...@@ -8,9 +8,11 @@ export const getProjectData = ( ...@@ -8,9 +8,11 @@ export const getProjectData = (
{ namespace, projectId, force = false } = {}, { namespace, projectId, force = false } = {},
) => new Promise((resolve, reject) => { ) => new Promise((resolve, reject) => {
if (!state.projects[`${namespace}/${projectId}`] || force) { if (!state.projects[`${namespace}/${projectId}`] || force) {
commit(types.TOGGLE_LOADING, state);
service.getProjectData(namespace, projectId) service.getProjectData(namespace, projectId)
.then(res => res.data) .then(res => res.data)
.then((data) => { .then((data) => {
commit(types.TOGGLE_LOADING, state);
commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data }); commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
if (!state.currentProjectId) commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`); if (!state.currentProjectId) commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
resolve(data); resolve(data);
......
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
shouldRenderContent() { shouldRenderContent() {
return !this.isLoading && Object.keys(this.job).length; return !this.isLoading && Object.keys(this.job).length;
}, },
jobStarted() {
return this.job.started;
},
}, },
methods: { methods: {
getActions() { getActions() {
...@@ -63,8 +66,9 @@ ...@@ -63,8 +66,9 @@
:time="job.created_at" :time="job.created_at"
:user="job.user" :user="job.user"
:actions="actions" :actions="actions"
:hasSidebarButton="true" :has-sidebar-button="true"
/> :should-render-triggered-label="jobStarted"
/>
<loading-icon <loading-icon
v-if="isLoading" v-if="isLoading"
size="2" size="2"
......
...@@ -17,6 +17,11 @@ export default { ...@@ -17,6 +17,11 @@ export default {
required: true, required: true,
}, },
resetCachePath: {
type: String,
required: true,
},
ciLintPath: { ciLintPath: {
type: String, type: String,
required: true, required: true,
...@@ -45,6 +50,14 @@ export default { ...@@ -45,6 +50,14 @@ export default {
Get started with Pipelines Get started with Pipelines
</a> </a>
<a
data-method="post"
rel="nofollow"
:href="resetCachePath"
class="btn btn-default">
Clear runner caches
</a>
<a <a
:href="ciLintPath" :href="ciLintPath"
class="btn btn-default"> class="btn btn-default">
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
canCreatePipeline: pipelinesData.canCreatePipeline, canCreatePipeline: pipelinesData.canCreatePipeline,
hasCi: pipelinesData.hasCi, hasCi: pipelinesData.hasCi,
ciLintPath: pipelinesData.ciLintPath, ciLintPath: pipelinesData.ciLintPath,
resetCachePath: pipelinesData.resetCachePath,
state: this.store.state, state: this.store.state,
scope: getParameterByName('scope') || 'all', scope: getParameterByName('scope') || 'all',
page: getParameterByName('page') || '1', page: getParameterByName('page') || '1',
...@@ -220,6 +221,7 @@ ...@@ -220,6 +221,7 @@
:new-pipeline-path="newPipelinePath" :new-pipeline-path="newPipelinePath"
:has-ci-enabled="hasCiEnabled" :has-ci-enabled="hasCiEnabled"
:help-page-path="helpPagePath" :help-page-path="helpPagePath"
:resetCachePath="resetCachePath"
:ci-lint-path="ciLintPath" :ci-lint-path="ciLintPath"
:can-create-pipeline="canCreatePipelineParsed " :can-create-pipeline="canCreatePipelineParsed "
/> />
......
...@@ -45,6 +45,11 @@ export default { ...@@ -45,6 +45,11 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
shouldRenderTriggeredLabel: {
type: Boolean,
required: false,
default: true,
},
}, },
directives: { directives: {
...@@ -82,7 +87,12 @@ export default { ...@@ -82,7 +87,12 @@ export default {
{{itemName}} #{{itemId}} {{itemName}} #{{itemId}}
</strong> </strong>
triggered <template v-if="shouldRenderTriggeredLabel">
triggered
</template>
<template v-else>
created
</template>
<timeago-tooltip :time="time" /> <timeago-tooltip :time="time" />
......
...@@ -20,10 +20,13 @@ ...@@ -20,10 +20,13 @@
width: 100%; width: 100%;
} }
&.svg-250 { $image-widths: 250 306 394;
img, @each $width in $image-widths {
svg { &.svg-#{$width} {
width: 250px; img,
svg {
width: #{$width + 'px'};
}
} }
} }
} }
......
...@@ -92,6 +92,19 @@ ...@@ -92,6 +92,19 @@
padding: 6px 12px; padding: 6px 12px;
} }
.multi-file-loading-container {
margin-top: 10px;
padding: 10px;
.animation-container {
background: $gray-light;
div {
background: $gray-light;
}
}
}
table.table tr td.multi-file-table-name { table.table tr td.multi-file-table-name {
width: 350px; width: 350px;
padding: 6px 12px; padding: 6px 12px;
......
...@@ -5,8 +5,6 @@ module IssuesAction ...@@ -5,8 +5,6 @@ module IssuesAction
# rubocop:disable Gitlab/ModuleWithInstanceVariables # rubocop:disable Gitlab/ModuleWithInstanceVariables
def issues def issues
@finder_type = IssuesFinder @finder_type = IssuesFinder
@label = finder.labels.first
@issues = issuables_collection @issues = issuables_collection
.non_archived .non_archived
.page(params[:page]) .page(params[:page])
......
...@@ -5,7 +5,6 @@ module MergeRequestsAction ...@@ -5,7 +5,6 @@ module MergeRequestsAction
# rubocop:disable Gitlab/ModuleWithInstanceVariables # rubocop:disable Gitlab/ModuleWithInstanceVariables
def merge_requests def merge_requests
@finder_type = MergeRequestsFinder @finder_type = MergeRequestsFinder
@label = finder.labels.first
@merge_requests = issuables_collection.page(params[:page]) @merge_requests = issuables_collection.page(params[:page])
......
...@@ -11,6 +11,16 @@ module Projects ...@@ -11,6 +11,16 @@ module Projects
define_auto_devops_variables define_auto_devops_variables
end end
def reset_cache
if ResetProjectCacheService.new(@project, current_user).execute
flash[:notice] = _("Project cache successfully reset.")
else
flash[:error] = _("Unable to reset project cache.")
end
redirect_to project_pipelines_path(@project)
end
private private
def define_runners_variables def define_runners_variables
......
...@@ -374,19 +374,14 @@ class IssuableFinder ...@@ -374,19 +374,14 @@ class IssuableFinder
end end
def by_label(items) def by_label(items)
if labels? return items unless labels?
items =
if filter_by_no_label? if filter_by_no_label?
items = items.without_label items.without_label
else else
items = items.with_label(label_names, params[:sort]) items.with_label(label_names, params[:sort])
items_projects = projects(items)
if items_projects
label_ids = LabelsFinder.new(current_user, project_ids: items_projects).execute(skip_authorization: true).select(:id)
items = items.where(labels: { id: label_ids })
end
end end
end
items items
end end
......
...@@ -461,7 +461,14 @@ module Ci ...@@ -461,7 +461,14 @@ module Ci
end end
def cache def cache
[options[:cache]] cache = options[:cache]
if cache && project.jobs_cache_index
cache = cache.merge(
key: "#{cache[:key]}:#{project.jobs_cache_index}")
end
[cache]
end end
def credentials def credentials
......
...@@ -783,34 +783,30 @@ class Repository ...@@ -783,34 +783,30 @@ class Repository
end end
def create_dir(user, path, **options) def create_dir(user, path, **options)
options[:user] = user
options[:actions] = [{ action: :create_dir, file_path: path }] options[:actions] = [{ action: :create_dir, file_path: path }]
multi_action(**options) multi_action(user, **options)
end end
def create_file(user, path, content, **options) def create_file(user, path, content, **options)
options[:user] = user
options[:actions] = [{ action: :create, file_path: path, content: content }] options[:actions] = [{ action: :create, file_path: path, content: content }]
multi_action(**options) multi_action(user, **options)
end end
def update_file(user, path, content, **options) def update_file(user, path, content, **options)
previous_path = options.delete(:previous_path) previous_path = options.delete(:previous_path)
action = previous_path && previous_path != path ? :move : :update action = previous_path && previous_path != path ? :move : :update
options[:user] = user
options[:actions] = [{ action: action, file_path: path, previous_path: previous_path, content: content }] options[:actions] = [{ action: action, file_path: path, previous_path: previous_path, content: content }]
multi_action(**options) multi_action(user, **options)
end end
def delete_file(user, path, **options) def delete_file(user, path, **options)
options[:user] = user
options[:actions] = [{ action: :delete, file_path: path }] options[:actions] = [{ action: :delete, file_path: path }]
multi_action(**options) multi_action(user, **options)
end end
def with_cache_hooks def with_cache_hooks
...@@ -824,59 +820,14 @@ class Repository ...@@ -824,59 +820,14 @@ class Repository
result.newrev result.newrev
end end
def with_branch(user, *args) def multi_action(user, **options)
with_cache_hooks do start_project = options.delete(:start_project)
Gitlab::Git::OperationService.new(user, raw_repository).with_branch(*args) do |start_commit|
yield start_commit
end
end
end
# rubocop:disable Metrics/ParameterLists
def multi_action(
user:, branch_name:, message:, actions:,
author_email: nil, author_name: nil,
start_branch_name: nil, start_project: project)
with_branch(
user,
branch_name,
start_branch_name: start_branch_name,
start_repository: start_project.repository.raw_repository) do |start_commit|
index = Gitlab::Git::Index.new(raw_repository)
if start_commit
index.read_tree(start_commit.rugged_commit.tree)
parents = [start_commit.sha]
else
parents = []
end
actions.each do |options| if start_project
index.public_send(options.delete(:action), options) # rubocop:disable GitlabSecurity/PublicSend options[:start_repository] = start_project.repository.raw_repository
end
options = {
tree: index.write_tree,
message: message,
parents: parents
}
options.merge!(get_committer_and_author(user, email: author_email, name: author_name))
create_commit(options)
end end
end
# rubocop:enable Metrics/ParameterLists
def get_committer_and_author(user, email: nil, name: nil) with_cache_hooks { raw.multi_action(user, **options) }
committer = user_to_committer(user)
author = Gitlab::Git.committer_hash(email: email, name: name) || committer
{
author: author,
committer: committer
}
end end
def can_be_merged?(source_sha, target_branch) def can_be_merged?(source_sha, target_branch)
......
...@@ -4,6 +4,8 @@ class JobEntity < Grape::Entity ...@@ -4,6 +4,8 @@ class JobEntity < Grape::Entity
expose :id expose :id
expose :name expose :name
expose :started?, as: :started
expose :build_path do |build| expose :build_path do |build|
build.target_url || path_to(:namespace_project_job, build) build.target_url || path_to(:namespace_project_job, build)
end end
......
...@@ -4,7 +4,7 @@ module Files ...@@ -4,7 +4,7 @@ module Files
def create_commit! def create_commit!
repository.multi_action( repository.multi_action(
user: current_user, current_user,
message: @commit_message, message: @commit_message,
branch_name: @branch_name, branch_name: @branch_name,
actions: params[:actions], actions: params[:actions],
...@@ -13,6 +13,8 @@ module Files ...@@ -13,6 +13,8 @@ module Files
start_project: @start_project, start_project: @start_project,
start_branch_name: @start_branch start_branch_name: @start_branch
) )
rescue ArgumentError => e
raise_error(e)
end end
private private
...@@ -20,16 +22,7 @@ module Files ...@@ -20,16 +22,7 @@ module Files
def validate! def validate!
super super
params[:actions].each do |action| params[:actions].each { |action| validate_file_status!(action) }
validate_action!(action)
validate_file_status!(action)
end
end
def validate_action!(action)
unless Gitlab::Git::Index::ACTIONS.include?(action[:action].to_s)
raise_error("Unknown action '#{action[:action]}'")
end
end end
def validate_file_status!(action) def validate_file_status!(action)
......
class ResetProjectCacheService < BaseService
def execute
@project.increment!(:jobs_cache_index)
end
end
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.ide-flash-container.flash-container .ide-flash-container.flash-container
#ide.ide-loading #ide.ide-loading{ data: {"empty-state-svg-path" => image_path('illustrations/multi_file_editor_empty.svg')} }
.text-center .text-center
= icon('spinner spin 2x') = icon('spinner spin 2x')
%h2.clgray= _('IDE Loading ...') %h2.clgray= _('Loading the GitLab IDE...')
...@@ -49,6 +49,12 @@ ...@@ -49,6 +49,12 @@
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects Projects
- if current_controller?('ide')
%li.line-separator.hidden-xs
= nav_link(controller: 'ide') do
= link_to '#', class: 'dashboard-shortcuts-web-ide', title: 'Web IDE' do
Web IDE
- if current_user.admin? || Gitlab::Sherlock.enabled? - if current_user.admin? || Gitlab::Sherlock.enabled?
%li.line-separator.hidden-xs %li.line-separator.hidden-xs
- if current_user.admin? - if current_user.admin?
......
- illustration = local_assigns.fetch(:illustration)
- illustration_size = local_assigns.fetch(:illustration_size)
- title = local_assigns.fetch(:title)
- content = local_assigns.fetch(:content)
- action = local_assigns.fetch(:action, nil)
.row.empty-state
.col-xs-12
.svg-content{ class: illustration_size }
= image_tag illustration
.col-xs-12
.text-content
%h4.text-center= title
%p= content
- if action
.text-center
= action
...@@ -54,41 +54,53 @@ ...@@ -54,41 +54,53 @@
Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)} Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)}
- else - else
Job has been erased #{time_ago_with_tooltip(@build.erased_at)} Job has been erased #{time_ago_with_tooltip(@build.erased_at)}
- if @build.started?
.build-trace-container.prepend-top-default
.top-bar.js-top-bar
.js-truncated-info.truncated-info.hidden-xs.pull-left.hidden<
Showing last
%span.js-truncated-info-size.truncated-info-size><
of log -
%a.js-raw-link.raw-link{ href: raw_project_job_path(@project, @build) }>< Complete Raw
.build-trace-container.prepend-top-default .controllers.pull-right
.top-bar.js-top-bar - if @build.has_trace?
.js-truncated-info.truncated-info.hidden-xs.pull-left.hidden< = link_to raw_project_job_path(@project, @build),
Showing last title: 'Show complete raw',
%span.js-truncated-info-size.truncated-info-size>< data: { placement: 'top', container: 'body' },
of log - class: 'js-raw-link-controller has-tooltip controllers-buttons' do
%a.js-raw-link.raw-link{ href: raw_project_job_path(@project, @build) }>< Complete Raw = icon('file-text-o')
.controllers.pull-right - if @build.erasable? && can?(current_user, :erase_build, @build)
- if @build.has_trace? = link_to erase_project_job_path(@project, @build),
= link_to raw_project_job_path(@project, @build), method: :post,
title: 'Show complete raw', data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' },
data: { placement: 'top', container: 'body' }, title: 'Erase job log',
class: 'js-raw-link-controller has-tooltip controllers-buttons' do class: 'has-tooltip js-erase-link controllers-buttons' do
= icon('file-text-o') = icon('trash')
.has-tooltip.controllers-buttons{ title: 'Scroll to top', data: { placement: 'top', container: 'body'} }
- if @build.erasable? && can?(current_user, :erase_build, @build) %button.js-scroll-up.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
= link_to erase_project_job_path(@project, @build), = custom_icon('scroll_up')
method: :post, .has-tooltip.controllers-buttons{ title: 'Scroll to bottom', data: { placement: 'top', container: 'body'} }
data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' }, %button.js-scroll-down.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
title: 'Erase job log', = custom_icon('scroll_down')
class: 'has-tooltip js-erase-link controllers-buttons' do
= icon('trash')
.has-tooltip.controllers-buttons{ title: 'Scroll to top', data: { placement: 'top', container: 'body'} }
%button.js-scroll-up.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
= custom_icon('scroll_up')
.has-tooltip.controllers-buttons{ title: 'Scroll to bottom', data: { placement: 'top', container: 'body'} }
%button.js-scroll-down.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
= custom_icon('scroll_down')
%pre.build-trace#build-trace
%code.bash.js-build-output
.build-loader-animation.js-build-refresh
%pre.build-trace#build-trace
%code.bash.js-build-output
.build-loader-animation.js-build-refresh
- elsif @build.playable?
= render 'empty_state',
illustration: 'illustrations/manual_action.svg',
illustration_size: 'svg-394',
title: _('This job requires a manual action'),
content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments.'),
action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), class: 'btn btn-primary', title: _('Trigger this manual action') )
- else
= render 'empty_state',
illustration: 'illustrations/job_not_triggered.svg',
illustration_size: 'svg-306',
title: _('This job has not been triggered yet'),
content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered.')
= render "sidebar" = render "sidebar"
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
"new-pipeline-path" => new_project_pipeline_path(@project), "new-pipeline-path" => new_project_pipeline_path(@project),
"can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s, "can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s,
"has-ci" => @repository.gitlab_ci_yml, "has-ci" => @repository.gitlab_ci_yml,
"ci-lint-path" => ci_lint_path } } "ci-lint-path" => ci_lint_path,
"reset-cache-path" => reset_cache_project_settings_ci_cd_path(@project) } }
= page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('pipelines') = page_specific_javascript_bundle_tag('pipelines')
---
title: Implement project jobs cache reset
merge_request: 16067
author:
type: added
---
title: Fix timeout when filtering issues by label
merge_request:
author:
type: performance
...@@ -408,7 +408,9 @@ constraints(ProjectUrlConstrainer.new) do ...@@ -408,7 +408,9 @@ constraints(ProjectUrlConstrainer.new) do
end end
namespace :settings do namespace :settings do
get :members, to: redirect("%{namespace_id}/%{project_id}/project_members") get :members, to: redirect("%{namespace_id}/%{project_id}/project_members")
resource :ci_cd, only: [:show], controller: 'ci_cd' resource :ci_cd, only: [:show], controller: 'ci_cd' do
post :reset_cache
end
resource :integrations, only: [:show] resource :integrations, only: [:show]
resource :repository, only: [:show], controller: :repository resource :repository, only: [:show], controller: :repository
end end
......
...@@ -63,7 +63,8 @@ Sidekiq::Testing.inline! do ...@@ -63,7 +63,8 @@ Sidekiq::Testing.inline! do
namespace_id: group.id, namespace_id: group.id,
name: project_path.titleize, name: project_path.titleize,
description: FFaker::Lorem.sentence, description: FFaker::Lorem.sentence,
visibility_level: Gitlab::VisibilityLevel.values.sample visibility_level: Gitlab::VisibilityLevel.values.sample,
skip_disk_validation: true
} }
project = Projects::CreateService.new(User.first, params).execute project = Projects::CreateService.new(User.first, params).execute
......
# This migration is a duplicate of 20171230123729_add_rebase_commit_sha_to_merge_requests_ce.rb
#
# We backported this feature from EE using the same migration, but with a new
# timestamp, which caused an error when the backport was then to be merged back
# into EE.
#
# See discussion at https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3932
class AddRebaseCommitShaToMergeRequests < ActiveRecord::Migration
DOWNTIME = false
def up
unless column_exists?(:merge_requests, :rebase_commit_sha)
add_column :merge_requests, :rebase_commit_sha, :string
end
end
def down
if column_exists?(:merge_requests, :rebase_commit_sha)
remove_column :merge_requests, :rebase_commit_sha
end
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddJobsCacheIndexToProject < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def change
add_column :projects, :jobs_cache_index, :integer
end
end
class AddRebaseCommitShaToMergeRequests < ActiveRecord::Migration
DOWNTIME = false
def change
add_column :merge_requests, :rebase_commit_sha, :string
end
end
class AddRebaseCommitShaToMergeRequestsCe < ActiveRecord::Migration
DOWNTIME = false
def up
unless column_exists?(:merge_requests, :rebase_commit_sha)
add_column :merge_requests, :rebase_commit_sha, :string
end
end
def down
if column_exists?(:merge_requests, :rebase_commit_sha)
remove_column :merge_requests, :rebase_commit_sha
end
end
end
...@@ -1451,6 +1451,7 @@ ActiveRecord::Schema.define(version: 20171230123729) do ...@@ -1451,6 +1451,7 @@ ActiveRecord::Schema.define(version: 20171230123729) do
t.boolean "repository_read_only" t.boolean "repository_read_only"
t.boolean "merge_requests_ff_only_enabled", default: false t.boolean "merge_requests_ff_only_enabled", default: false
t.boolean "merge_requests_rebase_enabled", default: false, null: false t.boolean "merge_requests_rebase_enabled", default: false, null: false
t.integer "jobs_cache_index"
end end
add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
......
...@@ -299,9 +299,9 @@ sudo usermod -aG redis git ...@@ -299,9 +299,9 @@ sudo usermod -aG redis git
### Clone the Source ### Clone the Source
# Clone GitLab repository # Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 10-3-stable gitlab sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 10-4-stable gitlab
**Note:** You can change `10-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! **Note:** You can change `10-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It ### Configure It
......
...@@ -11,7 +11,7 @@ module SharedBuilds ...@@ -11,7 +11,7 @@ module SharedBuilds
step 'project has a recent build' do step 'project has a recent build' do
@pipeline = create(:ci_empty_pipeline, project: @project, sha: @project.commit.sha, ref: 'master') @pipeline = create(:ci_empty_pipeline, project: @project, sha: @project.commit.sha, ref: 'master')
@build = create(:ci_build, :coverage, pipeline: @pipeline) @build = create(:ci_build, :running, :coverage, pipeline: @pipeline)
end end
step 'recent build is successful' do step 'recent build is successful' do
......
...@@ -10,6 +10,7 @@ module Gitlab ...@@ -10,6 +10,7 @@ module Gitlab
DEFAULT_MODE = 0o100644 DEFAULT_MODE = 0o100644
ACTIONS = %w(create create_dir update move delete).freeze ACTIONS = %w(create create_dir update move delete).freeze
ACTION_OPTIONS = %i(file_path previous_path content encoding).freeze
attr_reader :repository, :raw_index attr_reader :repository, :raw_index
...@@ -20,6 +21,11 @@ module Gitlab ...@@ -20,6 +21,11 @@ module Gitlab
delegate :read_tree, :get, to: :raw_index delegate :read_tree, :get, to: :raw_index
def apply(action, options)
validate_action!(action)
public_send(action, options.slice(*ACTION_OPTIONS)) # rubocop:disable GitlabSecurity/PublicSend
end
def write_tree def write_tree
raw_index.write_tree(repository.rugged) raw_index.write_tree(repository.rugged)
end end
...@@ -140,6 +146,12 @@ module Gitlab ...@@ -140,6 +146,12 @@ module Gitlab
rescue Rugged::IndexError => e rescue Rugged::IndexError => e
raise IndexError, e.message raise IndexError, e.message
end end
def validate_action!(action)
unless ACTIONS.include?(action.to_s)
raise ArgumentError, "Unknown action '#{action}'"
end
end
end end
end end
end end
...@@ -1300,6 +1300,42 @@ module Gitlab ...@@ -1300,6 +1300,42 @@ module Gitlab
success || gitlab_projects_error success || gitlab_projects_error
end end
# rubocop:disable Metrics/ParameterLists
def multi_action(
user, branch_name:, message:, actions:,
author_email: nil, author_name: nil,
start_branch_name: nil, start_repository: self)
OperationService.new(user, self).with_branch(
branch_name,
start_branch_name: start_branch_name,
start_repository: start_repository
) do |start_commit|
index = Gitlab::Git::Index.new(self)
parents = []
if start_commit
index.read_tree(start_commit.rugged_commit.tree)
parents = [start_commit.sha]
end
actions.each { |opts| index.apply(opts.delete(:action), opts) }
committer = user_to_committer(user)
author = Gitlab::Git.committer_hash(email: author_email, name: author_name) || committer
options = {
tree: index.write_tree,
message: message,
parents: parents,
author: author,
committer: committer
}
create_commit(options)
end
end
# rubocop:enable Metrics/ParameterLists
def gitaly_repository def gitaly_repository
Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository) Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository)
end end
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -17,4 +17,51 @@ describe Projects::Settings::CiCdController do ...@@ -17,4 +17,51 @@ describe Projects::Settings::CiCdController do
expect(response).to render_template(:show) expect(response).to render_template(:show)
end end
end end
describe '#reset_cache' do
before do
sign_in(user)
project.add_master(user)
allow(ResetProjectCacheService).to receive_message_chain(:new, :execute).and_return(true)
end
subject { post :reset_cache, namespace_id: project.namespace, project_id: project }
it 'calls reset project cache service' do
expect(ResetProjectCacheService).to receive_message_chain(:new, :execute)
subject
end
it 'redirects to project pipelines path' do
subject
expect(response).to have_gitlab_http_status(:redirect)
expect(response).to redirect_to(project_pipelines_path(project))
end
context 'when service returns successfully' do
it 'sets the flash notice variable' do
subject
expect(controller).to set_flash[:notice]
expect(controller).not_to set_flash[:error]
end
end
context 'when service does not return successfully' do
before do
allow(ResetProjectCacheService).to receive_message_chain(:new, :execute).and_return(false)
end
it 'sets the flash error variable' do
subject
expect(controller).not_to set_flash[:notice]
expect(controller).to set_flash[:error]
end
end
end
end end
...@@ -7,12 +7,10 @@ FactoryBot.define do ...@@ -7,12 +7,10 @@ FactoryBot.define do
stage_idx 0 stage_idx 0
ref 'master' ref 'master'
tag false tag false
status 'pending'
created_at 'Di 29. Okt 09:50:00 CET 2013'
started_at 'Di 29. Okt 09:51:28 CET 2013'
finished_at 'Di 29. Okt 09:53:28 CET 2013'
commands 'ls -a' commands 'ls -a'
protected false protected false
created_at 'Di 29. Okt 09:50:00 CET 2013'
pending
options do options do
{ {
...@@ -29,23 +27,37 @@ FactoryBot.define do ...@@ -29,23 +27,37 @@ FactoryBot.define do
pipeline factory: :ci_pipeline pipeline factory: :ci_pipeline
trait :started do
started_at 'Di 29. Okt 09:51:28 CET 2013'
end
trait :finished do
started
finished_at 'Di 29. Okt 09:53:28 CET 2013'
end
trait :success do trait :success do
finished
status 'success' status 'success'
end end
trait :failed do trait :failed do
finished
status 'failed' status 'failed'
end end
trait :canceled do trait :canceled do
finished
status 'canceled' status 'canceled'
end end
trait :skipped do trait :skipped do
started
status 'skipped' status 'skipped'
end end
trait :running do trait :running do
started
status 'running' status 'running'
end end
...@@ -114,11 +126,6 @@ FactoryBot.define do ...@@ -114,11 +126,6 @@ FactoryBot.define do
build.project ||= build.pipeline.project build.project ||= build.pipeline.project
end end
factory :ci_not_started_build do
started_at nil
finished_at nil
end
trait :tag do trait :tag do
tag true tag true
end end
......
require 'spec_helper' require 'spec_helper'
describe 'User browses a job', :js do describe 'User browses a job', :js do
let!(:build) { create(:ci_build, :coverage, pipeline: pipeline) } let!(:build) { create(:ci_build, :running, :coverage, pipeline: pipeline) }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') } let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
let(:project) { create(:project, :repository, namespace: user.namespace) } let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -369,6 +369,34 @@ feature 'Jobs' do ...@@ -369,6 +369,34 @@ feature 'Jobs' do
end end
end end
end end
context 'Playable manual action' do
let(:job) { create(:ci_build, :playable, pipeline: pipeline) }
before do
project.add_developer(user)
visit project_job_path(project, job)
end
it 'shows manual action empty state' do
expect(page).to have_content('This job requires a manual action')
expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments.')
expect(page).to have_link('Trigger this manual action')
end
end
context 'Non triggered job' do
let(:job) { create(:ci_build, :created, pipeline: pipeline) }
before do
visit project_job_path(project, job)
end
it 'shows manual action empty state' do
expect(page).to have_content('This job has not been triggered yet')
expect(page).to have_content('This job depends on upstream jobs that need to succeed in order for this job to be triggered.')
end
end
end end
describe "POST /:project/jobs/:id/cancel", :js do describe "POST /:project/jobs/:id/cancel", :js do
......
...@@ -545,6 +545,40 @@ describe 'Pipelines', :js do ...@@ -545,6 +545,40 @@ describe 'Pipelines', :js do
end end
end end
end end
describe 'Reset runner caches' do
let(:project) { create(:project, :repository) }
before do
create(:ci_empty_pipeline, status: 'success', project: project, sha: project.commit.id, ref: 'master')
project.add_master(user)
visit project_pipelines_path(project)
end
it 'has a clear caches button' do
expect(page).to have_link 'Clear runner caches'
end
describe 'user clicks the button' do
context 'when project already has jobs_cache_index' do
before do
project.update_attributes(jobs_cache_index: 1)
end
it 'increments jobs_cache_index' do
click_link 'Clear runner caches'
expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
end
end
context 'when project does not have jobs_cache_index' do
it 'sets jobs_cache_index to 1' do
click_link 'Clear runner caches'
expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
end
end
end
end
end end
context 'when user is not logged in' do context 'when user is not logged in' do
......
...@@ -7,4 +7,6 @@ ...@@ -7,4 +7,6 @@
"new-pipeline-path" => 'foo', "new-pipeline-path" => 'foo',
"can-create-pipeline" => 'true', "can-create-pipeline" => 'true',
"has-ci" => 'foo', "has-ci" => 'foo',
"ci-lint-path" => 'foo' } } "ci-lint-path" => 'foo',
"reset-cache-path" => 'foo' } }
import Vue from 'vue'; import Vue from 'vue';
import headerComponent from '~/jobs/components/header.vue'; import headerComponent from '~/jobs/components/header.vue';
import mountComponent from '../helpers/vue_mount_component_helper';
describe('Job details header', () => { describe('Job details header', () => {
let HeaderComponent; let HeaderComponent;
...@@ -35,7 +36,7 @@ describe('Job details header', () => { ...@@ -35,7 +36,7 @@ describe('Job details header', () => {
isLoading: false, isLoading: false,
}; };
vm = new HeaderComponent({ propsData: props }).$mount(); vm = mountComponent(HeaderComponent, props);
}); });
afterEach(() => { afterEach(() => {
......
...@@ -14,6 +14,7 @@ describe('Pipelines Nav Controls', () => { ...@@ -14,6 +14,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true, hasCiEnabled: true,
helpPagePath: 'foo', helpPagePath: 'foo',
ciLintPath: 'foo', ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true, canCreatePipeline: true,
}; };
...@@ -31,6 +32,7 @@ describe('Pipelines Nav Controls', () => { ...@@ -31,6 +32,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true, hasCiEnabled: true,
helpPagePath: 'foo', helpPagePath: 'foo',
ciLintPath: 'foo', ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: false, canCreatePipeline: false,
}; };
...@@ -41,12 +43,31 @@ describe('Pipelines Nav Controls', () => { ...@@ -41,12 +43,31 @@ describe('Pipelines Nav Controls', () => {
expect(component.$el.querySelector('.btn-create')).toEqual(null); expect(component.$el.querySelector('.btn-create')).toEqual(null);
}); });
it('should render link for resetting runner caches', () => {
const mockData = {
newPipelinePath: 'foo',
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: false,
};
const component = new NavControlsComponent({
propsData: mockData,
}).$mount();
expect(component.$el.querySelectorAll('.btn-default')[0].textContent).toContain('Clear runner caches');
expect(component.$el.querySelectorAll('.btn-default')[0].getAttribute('href')).toEqual(mockData.resetCachePath);
});
it('should render link for CI lint', () => { it('should render link for CI lint', () => {
const mockData = { const mockData = {
newPipelinePath: 'foo', newPipelinePath: 'foo',
hasCiEnabled: true, hasCiEnabled: true,
helpPagePath: 'foo', helpPagePath: 'foo',
ciLintPath: 'foo', ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true, canCreatePipeline: true,
}; };
...@@ -54,8 +75,8 @@ describe('Pipelines Nav Controls', () => { ...@@ -54,8 +75,8 @@ describe('Pipelines Nav Controls', () => {
propsData: mockData, propsData: mockData,
}).$mount(); }).$mount();
expect(component.$el.querySelector('.btn-default').textContent).toContain('CI Lint'); expect(component.$el.querySelectorAll('.btn-default')[1].textContent).toContain('CI Lint');
expect(component.$el.querySelector('.btn-default').getAttribute('href')).toEqual(mockData.ciLintPath); expect(component.$el.querySelectorAll('.btn-default')[1].getAttribute('href')).toEqual(mockData.ciLintPath);
}); });
it('should render link to help page when CI is not enabled', () => { it('should render link to help page when CI is not enabled', () => {
...@@ -64,6 +85,7 @@ describe('Pipelines Nav Controls', () => { ...@@ -64,6 +85,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: false, hasCiEnabled: false,
helpPagePath: 'foo', helpPagePath: 'foo',
ciLintPath: 'foo', ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true, canCreatePipeline: true,
}; };
...@@ -81,6 +103,7 @@ describe('Pipelines Nav Controls', () => { ...@@ -81,6 +103,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true, hasCiEnabled: true,
helpPagePath: 'foo', helpPagePath: 'foo',
ciLintPath: 'foo', ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true, canCreatePipeline: true,
}; };
......
...@@ -41,11 +41,11 @@ describe('IdeRepoTree', () => { ...@@ -41,11 +41,11 @@ describe('IdeRepoTree', () => {
expect(tbody.querySelector('.file')).toBeTruthy(); expect(tbody.querySelector('.file')).toBeTruthy();
}); });
it('renders 5 loading files if tree is loading', (done) => { it('renders 3 loading files if tree is loading', (done) => {
vm.$store.state.loading = true; vm.treeId = '123';
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$el.querySelectorAll('tbody .loading-file').length).toEqual(5); expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toEqual(3);
done(); done();
}); });
......
...@@ -459,6 +459,7 @@ Project: ...@@ -459,6 +459,7 @@ Project:
- delete_error - delete_error
- merge_requests_ff_only_enabled - merge_requests_ff_only_enabled
- merge_requests_rebase_enabled - merge_requests_rebase_enabled
- jobs_cache_index
Author: Author:
- name - name
ProjectFeature: ProjectFeature:
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment