Skip to content

Commit

Permalink
Implement absolute versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
clong- committed Jan 13, 2025
1 parent 382b852 commit a96a1ee
Showing 1 changed file with 74 additions and 3 deletions.
77 changes: 74 additions & 3 deletions action.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ const inputs = {
}

let fetchedHistory = []
let fetchedTags = []

const Scheme = {
Absolute: 'absolute',
Continuous: 'continuous',
Semantic: 'semantic',
}
Expand Down Expand Up @@ -86,27 +88,51 @@ async function existingTags() {
}
}`
).then((result) => {
return result.repository.refs.nodes
fetchedTags = result.repository.refs.nodes
return fetchedTags
})
.catch((e) => {
core.setFailed(`Failed to fetch tags: ${e}`)
})
}

async function fetchWorkflowCommitDate() {
return await octokit.graphql(
`{
repository(owner: "${owner}", name: "${repo}") {
commit: object(oid: "${process.env['GITHUB_SHA']}") {
... on Commit {
sha: oid
committedDate
}
}
}
}`
).then((data) => data.repository.commit.committedDate)
}

async function latestTagForBranch(allTags, branch) {
core.info(
`Fetching commits for ref ${branch}. This may take a while on large repositories.`
)

const query =
`query commits($cursor: String) {
`query commits($cursor: String, $until: GitTimestamp) {
repository(owner: "${owner}", name: "${repo}") {
branch: ref(qualifiedName: "${branch}") {
head: target {
... on Commit {
history(first: 100, after: $cursor) {
history(first: 100, after: $cursor, until: $until) {
commits: nodes {
sha: oid
associatedPullRequests(first: 1) {
prs: nodes {
baseRefName
mergeCommit {
sha: oid
}
}
}
}
pageInfo {
endCursor
Expand All @@ -119,12 +145,14 @@ async function latestTagForBranch(allTags, branch) {
}
}`
let cursor = null;
let until = (inputs.scheme == Scheme.Absolute) ? await fetchWorkflowCommitDate() : null;

let latestTag
let moreToFetch = true
while (isNullString(latestTag) && moreToFetch) {
let opts = {
cursor: cursor,
until: until,
}

latestTag = await octokit.graphql(query, opts)
Expand Down Expand Up @@ -203,6 +231,47 @@ function determinePrereleaseName(semTag) {
}
}

// increments version according to the number of merge commits between
// this one and the most recent tag in history.
// assumes repo merge strategy that generates merge commits,
// and that only merge commits will receive tags.
// also assumes continuous versioning.
function computeNextAbsolute(semTag, lastTag) {
core.info(JSON.stringify(fetchedTags))
core.info(`last tag: ${lastTag}`)
const tag = fetchedTags.find((tag) => {
core.info(JSON.stringify(tag))
return tag.ref === lastTag
})
core.info(`tag ${JSON.stringify(tag)}`)
const tagSha = tag.object.sha
const tagIndex = fetchedHistory.findIndex((commit) => commit.sha === tagSha)
// we only want merge commits between now and the most recent tag
const relevantHistory = fetchedHistory.slice(0, tagIndex).filter((commit) => {
const pr = commit.associatedPullRequests.prs[0]

// filters non-merge commits
if (!pr || !pr.mergeCommit || pr.mergeCommit.sha != commit.sha) {
return false
}

// ensures merge was into this branch
// and not into a branch that was then merged into this one
if (pr.baseRefName != inputs.branch) {
return false
}

return true
})
core.info(JSON.stringify(relevantHistory))

let nextTag = semTag
for (const i = relevantHistory.length; i > 0; i++) {
nextTag = computeNextContinuous(nextTag)
}
return semver.parse(nextTag)
}

function computeNextContinuous(semTag) {
const bumpType = determineContinuousBumpType(semTag)
const preName = determinePrereleaseName(semTag)
Expand Down Expand Up @@ -300,6 +369,8 @@ async function computeNextTag() {
}

switch (inputs.scheme) {
case 'absolute':
return computeNextAbsolute(semTag, lastTag)
case 'continuous':
return computeNextContinuous(semTag)
case 'semantic':
Expand Down

0 comments on commit a96a1ee

Please sign in to comment.