This repository has been archived by the owner on Jul 25, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Initial commit PROV from gitlab
- Loading branch information
1 parent
46aae93
commit cdc233f
Showing
4 changed files
with
182 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import rdf from 'rdf-ext' | ||
import { Transform } from 'readable-stream' | ||
import { provFromGitlab } from './metadata/produceProv.js' | ||
import { prov } from './namespaces.js' | ||
|
||
const typePredicate = rdf.namedNode( | ||
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') | ||
|
||
class ProvMetadata extends Transform { | ||
constructor (context, { subjectsWithClass, graph }) { | ||
super({ objectMode: true }) | ||
|
||
this.type = subjectsWithClass | ||
this.provPointer = provFromGitlab() | ||
this.graph = graph | ||
} | ||
|
||
_transform (quad, encoding, callback) { | ||
if (quad.predicate.equals(typePredicate) && quad.object.equals(this.type)) { | ||
this.provPointer.addOut(prov.generates, quad.subject) | ||
} | ||
|
||
callback(null, quad) | ||
} | ||
|
||
async _flush (callback) { | ||
try { | ||
for (const quad of [...this.provPointer.dataset]) { | ||
if (this.graph) { | ||
this.push( | ||
rdf.quad(quad.subject, quad.predicate, quad.object, this.graph)) | ||
} else { | ||
this.push(quad) | ||
} | ||
} | ||
} catch (err) { | ||
this.destroy(err) | ||
} finally { | ||
callback() | ||
} | ||
} | ||
} | ||
|
||
function toNamedNode (item) { | ||
if (item && item.term) { | ||
return item.term | ||
} | ||
return typeof item === 'string' ? rdf.namedNode(item) : item | ||
} | ||
|
||
async function appendGitlabProv ({ | ||
subjectsWithClass, graph = undefined | ||
} = {}) { | ||
return new ProvMetadata(this, { | ||
subjectsWithClass: toNamedNode(subjectsWithClass), | ||
graph: toNamedNode(graph) | ||
}) | ||
} | ||
|
||
export default appendGitlabProv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import namespace from '@rdfjs/namespace' | ||
import rdf from 'rdf-ext' | ||
import { xsd, schema, prov } from '../namespaces.js' | ||
|
||
const withoutLastSegment = url => url.split('/') | ||
.splice(0, url.split('/').length - 1) | ||
.join('/') | ||
|
||
const ex = namespace('http://example.org/') | ||
|
||
const type = rdf.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type') | ||
|
||
function validateVars () { | ||
if (!process.env.CI_JOB_URL) { | ||
throw Error('required environment variable CI_JOB_URL') | ||
} | ||
if (!process.env.CI_JOB_STARTED_AT) { | ||
throw Error('required environment variable CI_JOB_STARTED_AT') | ||
} | ||
if (!process.env.CI_PROJECT_URL) { | ||
throw Error('required environment variable CI_PROJECT_URL') | ||
} | ||
if (!process.env.CI_COMMIT_SHA) { | ||
throw Error('required environment variable CI_COMMIT_SHA') | ||
} | ||
if (!process.env.CI_PIPELINE_URL) { | ||
throw Error('required environment variable CI_PIPELINE_URL') | ||
} | ||
if (!process.env.CI_PIPELINE_CREATED_AT) { | ||
throw Error('required environment variable CI_PIPELINE_CREATED_AT') | ||
} | ||
} | ||
|
||
function provFromGitlab () { | ||
validateVars() | ||
|
||
// Job | ||
const jobUrl = process.env.CI_JOB_URL | ||
const jobStartTime = process.env.CI_JOB_STARTED_AT | ||
const jobUri = rdf.namedNode(jobUrl) | ||
|
||
// Codebase | ||
const projectUrl = process.env.CI_PROJECT_URL | ||
const codebaseUri = rdf.namedNode(projectUrl) | ||
|
||
// Commit | ||
const commitSha = process.env.CI_COMMIT_SHA | ||
const commitUri = rdf.namedNode(`${projectUrl}/-/commit/${commitSha}`) | ||
|
||
// All the jobs that were triggered by this commit, the pipelineRun. Might include download files | ||
const pipelineRun = process.env.CI_PIPELINE_URL | ||
const pipelineRunStartTime = process.env.CI_PIPELINE_CREATED_AT | ||
const pipelineRunUri = rdf.namedNode(pipelineRun) | ||
|
||
// all the pipelines for the codebase | ||
const pipelinesUri = rdf.namedNode(withoutLastSegment(pipelineRun)) | ||
|
||
const pointer = rdf.clownface({ dataset: rdf.dataset(), term: jobUri }) | ||
|
||
pointer.node(codebaseUri) | ||
.addOut(type, ex.Codebase) | ||
.addOut(ex.hasPipelines, pipelinesUri) | ||
|
||
pointer.node(commitUri) | ||
.addOut(type, ex.Commit) | ||
.addOut(ex.triggered, pipelineRunUri) | ||
|
||
pointer.node(pipelinesUri).addOut(ex.contains, pipelineRunUri) | ||
|
||
pointer.node(pipelineRunUri) | ||
.addOut(type, ex.PipelineRun) | ||
.addOut(prov.startedAtTime, rdf.literal(pipelineRunStartTime, xsd.dateTime)) | ||
.addOut(ex.hasJob, jobUri) | ||
|
||
pointer.node(jobUri) | ||
.addOut(type, ex.Activity) | ||
.addOut(prov.startedAtTime, rdf.literal(jobStartTime, xsd.dateTime)) | ||
.addOut(prov.wasTriggeredBy, commitUri) | ||
|
||
// Job Optionals | ||
const environment = process.env.CI_BUILD_REF_SLUG | ||
if (environment) { | ||
const environmentUri = ex[`environment/${environment}`] | ||
pointer.node(jobUri).addOut(ex.hasEnvironment, environmentUri) | ||
} | ||
|
||
// Codebase optionals | ||
const codebaseDescription = process.env.CI_PROJECT_DESCRIPTION | ||
if (codebaseDescription) { | ||
pointer.node(codebaseUri).addOut(schema.description, codebaseDescription) | ||
} | ||
|
||
const codebaseName = process.env.CI_PROJECT_NAME | ||
if (codebaseName) { | ||
pointer.node(codebaseUri).addOut(schema.name, codebaseName) | ||
} | ||
|
||
// Commit Optionals | ||
const commitName = process.env.CI_COMMIT_TITLE | ||
if (commitName) { | ||
pointer.node(commitUri).addOut(schema.name, commitName) | ||
} | ||
|
||
const commitAuthor = process.env.CI_COMMIT_AUTHOR | ||
if (commitAuthor) { | ||
pointer.node(commitUri).addOut(ex.author, commitAuthor) | ||
} | ||
|
||
const commitTime = process.env.CI_COMMIT_TIMESTAMP | ||
if (commitTime) { | ||
pointer.node(commitUri) | ||
.addOut(prov.atTime, rdf.literal(commitTime, xsd.dateTime)) | ||
} | ||
|
||
return pointer | ||
} | ||
|
||
export { provFromGitlab } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import append from './lib/append.js' | ||
import appendGitlabProv from './lib/appendGitlabProv.js' | ||
import voidStats from './lib/voidStats.js' | ||
|
||
export { append, voidStats } | ||
export { append, voidStats, appendGitlabProv } |