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"]}
\ No newline at end of file
{"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
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';
import repoEditor from './repo_editor.vue';
export default {
props: {
emptyStateSvgPath: {
type: String,
required: true,
},
},
computed: {
...mapState([
'currentBlobView',
......@@ -64,7 +70,23 @@ export default {
<template
v-else>
<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>
</template>
</div>
......
<script>
import { mapState } from 'vuex';
import RepoPreviousDirectory from './repo_prev_directory.vue';
import RepoFile from './repo_file.vue';
import RepoLoadingFile from './repo_loading_file.vue';
import repoPreviousDirectory from './repo_prev_directory.vue';
import repoFile from './repo_file.vue';
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
import { treeList } from '../stores/utils';
export default {
components: {
'repo-previous-directory': RepoPreviousDirectory,
'repo-file': RepoFile,
'repo-loading-file': RepoLoadingFile,
repoPreviousDirectory,
repoFile,
skeletonLoadingContainer,
},
props: {
treeId: {
......@@ -19,7 +19,7 @@ export default {
},
computed: {
...mapState([
'loading',
'trees',
'isRoot',
]),
...mapState({
......@@ -34,7 +34,10 @@ export default {
return !this.isRoot && this.fetchedList.length;
},
showLoading() {
return this.loading;
if (this.trees[this.treeId]) {
return this.trees[this.treeId].loading;
}
return true;
},
},
};
......@@ -49,11 +52,13 @@ export default {
<repo-previous-directory
v-if="hasPreviousDirectory"
/>
<repo-loading-file
<div
class="multi-file-loading-container"
v-if="showLoading"
v-for="n in 5"
:key="n"
/>
v-for="n in 3"
:key="n">
<skeleton-loading-container/>
</div>
<repo-file
v-for="file in fetchedList"
:key="file.key"
......
......@@ -3,6 +3,7 @@ import { mapState, mapActions } from 'vuex';
import projectTree from './ide_project_tree.vue';
import icon from '../../vue_shared/components/icon.vue';
import panelResizer from '../../vue_shared/components/panel_resizer.vue';
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
export default {
data() {
......@@ -14,9 +15,11 @@ export default {
projectTree,
icon,
panelResizer,
skeletonLoadingContainer,
},
computed: {
...mapState([
'loading',
'projects',
'leftPanelCollapsed',
]),
......@@ -32,6 +35,9 @@ export default {
}
return {};
},
showLoading() {
return this.loading;
},
},
methods: {
...mapActions([
......@@ -63,6 +69,13 @@ export default {
:style="panelStyle"
>
<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
v-for="(project, index) in projects"
:key="project.id"
......
import Vue from 'vue';
import { mapActions } from 'vuex';
import { convertPermissionToBoolean } from '../lib/utils/common_utils';
import ide from './components/ide.vue';
import store from './stores';
import router from './ide_router';
import Translate from '../vue_shared/translate';
import ContextualSidebar from '../contextual_sidebar';
function initIde(el) {
if (!el) return null;
......@@ -18,30 +14,13 @@ function initIde(el) {
components: {
ide,
},
methods: {
...mapActions([
'setInitialData',
]),
},
created() {
const data = el.dataset;
this.setInitialData({
endpoints: {
rootEndpoint: data.url,
newMergeRequestUrl: data.newMergeRequestUrl,
rootUrl: data.rootUrl,
render(createElement) {
return createElement('ide', {
props: {
emptyStateSvgPath: el.dataset.emptyStateSvgPath,
},
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');
Vue.use(Translate);
initIde(ideElement);
const contextualSidebar = new ContextualSidebar();
contextualSidebar.bindEvents();
......@@ -8,9 +8,11 @@ export const getProjectData = (
{ namespace, projectId, force = false } = {},
) => new Promise((resolve, reject) => {
if (!state.projects[`${namespace}/${projectId}`] || force) {
commit(types.TOGGLE_LOADING, state);
service.getProjectData(namespace, projectId)
.then(res => res.data)
.then((data) => {
commit(types.TOGGLE_LOADING, state);
commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
if (!state.currentProjectId) commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
resolve(data);
......
......@@ -30,6 +30,9 @@
shouldRenderContent() {
return !this.isLoading && Object.keys(this.job).length;
},
jobStarted() {
return this.job.started;
},
},
methods: {
getActions() {
......@@ -63,8 +66,9 @@
:time="job.created_at"
:user="job.user"
:actions="actions"
:hasSidebarButton="true"
/>
:has-sidebar-button="true"
:should-render-triggered-label="jobStarted"
/>
<loading-icon
v-if="isLoading"
size="2"
......
......@@ -17,6 +17,11 @@ export default {
required: true,
},
resetCachePath: {
type: String,
required: true,
},
ciLintPath: {
type: String,
required: true,
......@@ -45,6 +50,14 @@ export default {
Get started with Pipelines
</a>
<a
data-method="post"
rel="nofollow"
:href="resetCachePath"
class="btn btn-default">
Clear runner caches
</a>
<a
:href="ciLintPath"
class="btn btn-default">
......
......@@ -50,6 +50,7 @@
canCreatePipeline: pipelinesData.canCreatePipeline,
hasCi: pipelinesData.hasCi,
ciLintPath: pipelinesData.ciLintPath,
resetCachePath: pipelinesData.resetCachePath,
state: this.store.state,
scope: getParameterByName('scope') || 'all',
page: getParameterByName('page') || '1',
......@@ -220,6 +221,7 @@
:new-pipeline-path="newPipelinePath"
:has-ci-enabled="hasCiEnabled"
:help-page-path="helpPagePath"
:resetCachePath="resetCachePath"
:ci-lint-path="ciLintPath"
:can-create-pipeline="canCreatePipelineParsed "
/>
......
......@@ -45,6 +45,11 @@ export default {
required: false,
default: false,
},
shouldRenderTriggeredLabel: {
type: Boolean,
required: false,
default: true,
},
},
directives: {
......@@ -82,7 +87,12 @@ export default {
{{itemName}} #{{itemId}}
</strong>
triggered
<template v-if="shouldRenderTriggeredLabel">
triggered
</template>
<template v-else>
created
</template>
<timeago-tooltip :time="time" />
......
......@@ -20,10 +20,13 @@
width: 100%;
}
&.svg-250 {
img,
svg {
width: 250px;
$image-widths: 250 306 394;
@each $width in $image-widths {
&.svg-#{$width} {
img,
svg {
width: #{$width + 'px'};
}
}
}
}
......
......@@ -92,6 +92,19 @@
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 {
width: 350px;
padding: 6px 12px;
......
......@@ -5,8 +5,6 @@ module IssuesAction
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def issues
@finder_type = IssuesFinder
@label = finder.labels.first
@issues = issuables_collection
.non_archived
.page(params[:page])
......
......@@ -5,7 +5,6 @@ module MergeRequestsAction
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def merge_requests
@finder_type = MergeRequestsFinder
@label = finder.labels.first
@merge_requests = issuables_collection.page(params[:page])
......
......@@ -11,6 +11,16 @@ module Projects
define_auto_devops_variables
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
def define_runners_variables
......
......@@ -374,19 +374,14 @@ class IssuableFinder
end
def by_label(items)
if labels?
return items unless labels?
items =
if filter_by_no_label?
items = items.without_label
items.without_label
else
items = 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
items.with_label(label_names, params[:sort])
end
end
items
end
......
......@@ -461,7 +461,14 @@ module Ci
end
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
def credentials
......
......@@ -783,34 +783,30 @@ class Repository
end
def create_dir(user, path, **options)
options[:user] = user
options[:actions] = [{ action: :create_dir, file_path: path }]
multi_action(**options)
multi_action(user, **options)
end
def create_file(user, path, content, **options)
options[:user] = user
options[:actions] = [{ action: :create, file_path: path, content: content }]
multi_action(**options)
multi_action(user, **options)
end
def update_file(user, path, content, **options)
previous_path = options.delete(:previous_path)
action = previous_path && previous_path != path ? :move : :update
options[:user] = user
options[:actions] = [{ action: action, file_path: path, previous_path: previous_path, content: content }]
multi_action(**options)
multi_action(user, **options)
end
def delete_file(user, path, **options)
options[:user] = user
options[:actions] = [{ action: :delete, file_path: path }]
multi_action(**options)
multi_action(user, **options)
end
def with_cache_hooks
......@@ -824,59 +820,14 @@ class Repository
result.newrev
end
def with_branch(user, *args)
with_cache_hooks do
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
def multi_action(user, **options)
start_project = options.delete(:start_project)
actions.each do |options|
index.public_send(options.delete(:action), options) # rubocop:disable GitlabSecurity/PublicSend
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)
if start_project
options[:start_repository] = start_project.repository.raw_repository
end
end
# rubocop:enable Metrics/ParameterLists
def get_committer_and_author(user, email: nil, name: nil)
committer = user_to_committer(user)
author = Gitlab::Git.committer_hash(email: email, name: name) || committer
{
author: author,
committer: committer
}
with_cache_hooks { raw.multi_action(user, **options) }
end
def can_be_merged?(source_sha, target_branch)
......
......@@ -4,6 +4,8 @@ class JobEntity < Grape::Entity
expose :id
expose :name
expose :started?, as: :started
expose :build_path do |build|
build.target_url || path_to(:namespace_project_job, build)
end
......
......@@ -4,7 +4,7 @@ module Files
def create_commit!
repository.multi_action(
user: current_user,
current_user,
message: @commit_message,
branch_name: @branch_name,
actions: params[:actions],
......@@ -13,6 +13,8 @@ module Files
start_project: @start_project,
start_branch_name: @start_branch
)
rescue ArgumentError => e
raise_error(e)
end
private
......@@ -20,16 +22,7 @@ module Files
def validate!
super
params[:actions].each do |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
params[:actions].each { |action| validate_file_status!(action) }
end
def validate_file_status!(action)
......
class ResetProjectCacheService < BaseService
def execute
@project.increment!(:jobs_cache_index)
end
end
......@@ -6,7 +6,7 @@
.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
= icon('spinner spin 2x')
%h2.clgray= _('IDE Loading ...')
%h2.clgray= _('Loading the GitLab IDE...')
......@@ -49,6 +49,12 @@
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
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?
%li.line-separator.hidden-xs
- 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 @@
Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)}
- else
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
.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
.controllers.pull-right
- if @build.has_trace?
= link_to raw_project_job_path(@project, @build),
title: 'Show complete raw',
data: { placement: 'top', container: 'body' },
class: 'js-raw-link-controller has-tooltip controllers-buttons' do
= icon('file-text-o')
.controllers.pull-right
- if @build.has_trace?
= link_to raw_project_job_path(@project, @build),
title: 'Show complete raw',
data: { placement: 'top', container: 'body' },
class: 'js-raw-link-controller has-tooltip controllers-buttons' do
= icon('file-text-o')
- if @build.erasable? && can?(current_user, :erase_build, @build)
= link_to erase_project_job_path(@project, @build),
method: :post,
data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' },
title: 'Erase job log',
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
- if @build.erasable? && can?(current_user, :erase_build, @build)
= link_to erase_project_job_path(@project, @build),
method: :post,
data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' },
title: 'Erase job log',
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
- 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"
......
......@@ -10,7 +10,8 @@
"new-pipeline-path" => new_project_pipeline_path(@project),
"can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s,
"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('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
end
namespace :settings do
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 :repository, only: [:show], controller: :repository
end
......
......@@ -63,7 +63,8 @@ Sidekiq::Testing.inline! do
namespace_id: group.id,
name: project_path.titleize,
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
......
# 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
t.boolean "repository_read_only"
t.boolean "merge_requests_ff_only_enabled", default: false
t.boolean "merge_requests_rebase_enabled", default: false, null: false
t.integer "jobs_cache_index"
end
add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
......
......@@ -299,9 +299,9 @@ sudo usermod -aG redis git
### Clone the Source
# 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
......
......@@ -11,7 +11,7 @@ module SharedBuilds
step 'project has a recent build' do
@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
step 'recent build is successful' do
......
......@@ -10,6 +10,7 @@ module Gitlab
DEFAULT_MODE = 0o100644
ACTIONS = %w(create create_dir update move delete).freeze
ACTION_OPTIONS = %i(file_path previous_path content encoding).freeze
attr_reader :repository, :raw_index
......@@ -20,6 +21,11 @@ module Gitlab
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
raw_index.write_tree(repository.rugged)
end
......@@ -140,6 +146,12 @@ module Gitlab
rescue Rugged::IndexError => e
raise IndexError, e.message
end
def validate_action!(action)
unless ACTIONS.include?(action.to_s)
raise ArgumentError, "Unknown action '#{action}'"
end
end
end
end
end
......@@ -1300,6 +1300,42 @@ module Gitlab
success || gitlab_projects_error
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
Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository)
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
expect(response).to render_template(:show)
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
......@@ -7,12 +7,10 @@ FactoryBot.define do
stage_idx 0
ref 'master'
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'
protected false
created_at 'Di 29. Okt 09:50:00 CET 2013'
pending
options do
{
......@@ -29,23 +27,37 @@ FactoryBot.define do
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
finished
status 'success'
end
trait :failed do
finished
status 'failed'
end
trait :canceled do
finished
status 'canceled'
end
trait :skipped do
started
status 'skipped'
end
trait :running do
started
status 'running'
end
......@@ -114,11 +126,6 @@ FactoryBot.define do
build.project ||= build.pipeline.project
end
factory :ci_not_started_build do
started_at nil
finished_at nil
end
trait :tag do
tag true
end
......
require 'spec_helper'
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(:project) { create(:project, :repository, namespace: user.namespace) }
let(:user) { create(:user) }
......
......@@ -369,6 +369,34 @@ feature 'Jobs' do
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
describe "POST /:project/jobs/:id/cancel", :js do
......
......@@ -545,6 +545,40 @@ describe 'Pipelines', :js do
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
context 'when user is not logged in' do
......
......@@ -7,4 +7,6 @@
"new-pipeline-path" => 'foo',
"can-create-pipeline" => 'true',
"has-ci" => 'foo',
"ci-lint-path" => 'foo' } }
"ci-lint-path" => 'foo',
"reset-cache-path" => 'foo' } }
import Vue from 'vue';
import headerComponent from '~/jobs/components/header.vue';
import mountComponent from '../helpers/vue_mount_component_helper';
describe('Job details header', () => {
let HeaderComponent;
......@@ -35,7 +36,7 @@ describe('Job details header', () => {
isLoading: false,
};
vm = new HeaderComponent({ propsData: props }).$mount();
vm = mountComponent(HeaderComponent, props);
});
afterEach(() => {
......
......@@ -14,6 +14,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true,
};
......@@ -31,6 +32,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: false,
};
......@@ -41,12 +43,31 @@ describe('Pipelines Nav Controls', () => {
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', () => {
const mockData = {
newPipelinePath: 'foo',
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true,
};
......@@ -54,8 +75,8 @@ describe('Pipelines Nav Controls', () => {
propsData: mockData,
}).$mount();
expect(component.$el.querySelector('.btn-default').textContent).toContain('CI Lint');
expect(component.$el.querySelector('.btn-default').getAttribute('href')).toEqual(mockData.ciLintPath);
expect(component.$el.querySelectorAll('.btn-default')[1].textContent).toContain('CI Lint');
expect(component.$el.querySelectorAll('.btn-default')[1].getAttribute('href')).toEqual(mockData.ciLintPath);
});
it('should render link to help page when CI is not enabled', () => {
......@@ -64,6 +85,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: false,
helpPagePath: 'foo',
ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true,
};
......@@ -81,6 +103,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
resetCachePath: 'foo',
canCreatePipeline: true,
};
......
......@@ -41,11 +41,11 @@ describe('IdeRepoTree', () => {
expect(tbody.querySelector('.file')).toBeTruthy();
});
it('renders 5 loading files if tree is loading', (done) => {
vm.$store.state.loading = true;
it('renders 3 loading files if tree is loading', (done) => {
vm.treeId = '123';
Vue.nextTick(() => {
expect(vm.$el.querySelectorAll('tbody .loading-file').length).toEqual(5);
expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toEqual(3);
done();
});
......
......@@ -459,6 +459,7 @@ Project:
- delete_error
- merge_requests_ff_only_enabled
- merge_requests_rebase_enabled
- jobs_cache_index
Author:
- name
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