mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 03:18:24 +00:00 
			
		
		
		
	Implement actions artifacts (#22738)
Implement action artifacts server api. This change is used for supporting https://github.com/actions/upload-artifact and https://github.com/actions/download-artifact in gitea actions. It can run sample workflow from doc https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts. The api design is inspired by https://github.com/nektos/act/blob/master/pkg/artifacts/server.go and includes some changes from gitea internal structs and methods. Actions artifacts contains two parts: - Gitea server api and storage (this pr implement basic design without some complex cases supports) - Runner communicate with gitea server api (in comming) Old pr https://github.com/go-gitea/gitea/pull/22345 is outdated after actions merged. I create new pr from main branch.  Add artifacts list in actions workflow page.
This commit is contained in:
		| @@ -42,6 +42,18 @@ | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="job-artifacts" v-if="artifacts.length > 0"> | ||||
|           <div class="job-artifacts-title"> | ||||
|             {{ locale.artifactsTitle }} | ||||
|           </div> | ||||
|           <ul class="job-artifacts-list"> | ||||
|             <li class="job-artifacts-item" v-for="artifact in artifacts" :key="artifact.id"> | ||||
|               <a class="job-artifacts-link" target="_blank" :href="run.link+'/artifacts/'+artifact.id"> | ||||
|                 <SvgIcon name="octicon-file" class="ui text black job-artifacts-icon" />{{ artifact.name }} | ||||
|               </a> | ||||
|             </li> | ||||
|           </ul> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|       <div class="action-view-right"> | ||||
| @@ -102,6 +114,7 @@ const sfc = { | ||||
|       loading: false, | ||||
|       intervalID: null, | ||||
|       currentJobStepsStates: [], | ||||
|       artifacts: [], | ||||
|  | ||||
|       // provided by backend | ||||
|       run: { | ||||
| @@ -156,6 +169,15 @@ const sfc = { | ||||
|     this.intervalID = setInterval(this.loadJob, 1000); | ||||
|   }, | ||||
|  | ||||
|   unmounted() { | ||||
|     // clear the interval timer when the component is unmounted | ||||
|     // even our page is rendered once, not spa style | ||||
|     if (this.intervalID) { | ||||
|       clearInterval(this.intervalID); | ||||
|       this.intervalID = null; | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     // get the active container element, either the `job-step-logs` or the `job-log-list` in the `job-log-group` | ||||
|     getLogsContainer(idx) { | ||||
| @@ -259,6 +281,11 @@ const sfc = { | ||||
|       try { | ||||
|         this.loading = true; | ||||
|  | ||||
|         // refresh artifacts if upload-artifact step done | ||||
|         const resp = await this.fetchPost(`${this.actionsURL}/runs/${this.runIndex}/artifacts`); | ||||
|         const artifacts = await resp.json(); | ||||
|         this.artifacts = artifacts['artifacts'] || []; | ||||
|  | ||||
|         const response = await this.fetchJob(); | ||||
|  | ||||
|         // save the state to Vue data, then the UI will be updated | ||||
| @@ -287,6 +314,7 @@ const sfc = { | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|  | ||||
|     fetchPost(url, body) { | ||||
|       return fetch(url, { | ||||
|         method: 'POST', | ||||
| @@ -319,6 +347,7 @@ export function initRepositoryActionView() { | ||||
|       approve: el.getAttribute('data-locale-approve'), | ||||
|       cancel: el.getAttribute('data-locale-cancel'), | ||||
|       rerun: el.getAttribute('data-locale-rerun'), | ||||
|       artifactsTitle: el.getAttribute('data-locale-artifacts-title'), | ||||
|       status: { | ||||
|         unknown: el.getAttribute('data-locale-status-unknown'), | ||||
|         waiting: el.getAttribute('data-locale-status-waiting'), | ||||
| @@ -423,6 +452,27 @@ export function ansiLogToHTML(line) { | ||||
|   padding: 10px; | ||||
| } | ||||
|  | ||||
| .job-artifacts-title { | ||||
|   font-size: 18px; | ||||
|   margin-top: 16px; | ||||
|   padding: 16px 10px 0px 20px; | ||||
|   border-top: 1px solid var(--color-secondary); | ||||
| } | ||||
|  | ||||
| .job-artifacts-item { | ||||
|   margin: 5px 0; | ||||
|   padding: 6px; | ||||
| } | ||||
|  | ||||
| .job-artifacts-list { | ||||
|   padding-left: 12px; | ||||
|   list-style: none; | ||||
| } | ||||
|  | ||||
| .job-artifacts-icon { | ||||
|   padding-right: 3px; | ||||
| } | ||||
|  | ||||
| .job-group-section .job-brief-list .job-brief-item { | ||||
|   margin: 5px 0; | ||||
|   padding: 10px; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user