Skip to content

Bump actions/download-artifact from 2 to 4.1.7 in /.github/workflows #35

Bump actions/download-artifact from 2 to 4.1.7 in /.github/workflows

Bump actions/download-artifact from 2 to 4.1.7 in /.github/workflows #35

Workflow file for this run

name: Monorepo Versioning
concurrency: #avoid concurrent runs on label events, might cause issues on super fast commits ¯\_(ツ)_/¯
group: ${{ github.head_ref }}
cancel-in-progress: true
on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
pull_request_target:
types: [closed]
jobs:
detect:
runs-on: ubuntu-latest
name: 'Detect pull request context'
outputs:
directories: ${{ steps.condense.outputs.result }}
release-type: ${{ steps.check_pr_label.outputs.release-type}}
is-merge-event: >-
${{ github.event_name == 'pull_request_target'
&& github.event.action == 'closed'
&& github.event.pull_request.merged == true }}
steps:
# I'm getting the labels from the API and not the context("contains(github.event.pull_request.labels.*.name, 'Env Promote')") as the labels
# are added in 2nd API call so they aren't included in the PR context
- name: Check PR labels
id: check_pr_label
env:
PR_URL: ${{github.event.pull_request.html_url}} #TODO: check if needed (we don't checkout the code..)
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: |
LABELS=$(gh pr view $PR_URL --json labels --jq '.labels[]| select((.name=="minor") or (.name=="major") or (.name=="patch") or (.name=="no-release")) |.name')
NUMBER_OF_LABELS=$(echo "$LABELS" |wc -w)
if [ "$NUMBER_OF_LABELS" -eq "1" ] ; then
echo "Found: $LABELS"
echo "::set-output name=release-type::$LABELS"
elif [ "$NUMBER_OF_LABELS" -gt "1" ] ; then
echo "::error ::Too many release type labels: $( echo $LABELS | tr '\n' ' ' )"
exit 1
else
echo "::error ::No release type labels found(patch/minor/major/no-release)"
exit 2
fi
- name: Get changed files
uses: Ana06/[email protected]
id: raw-files
with:
format: 'json'
- name: Condense to directory list
uses: actions/github-script@v4
id: condense
env:
RAW_FILES: '${{ steps.raw-files.outputs.all }}'
with:
script: |
const raw = JSON.parse(process.env.RAW_FILES);
const directories = Array.from(new Set(raw
.filter(x => !x.startsWith('.'))
.filter(x => x.includes('/'))
.map(x => x.split('/')[0])
));
if (directories.length < 1) return {};
return {
include: directories.map(directory => ({ directory })),
};
plan:
needs: detect
if: ${{ needs.detect.outputs.directories != '{}' }}
runs-on: ubuntu-latest
strategy:
matrix: "${{ fromJson(needs.detect.outputs.directories) }}"
fail-fast: false
name: 'Module: ${{ matrix.directory }}'
steps:
- name: Detect previous version number
uses: actions/github-script@v4
id: prev-version
env:
PACKAGE_NAME: '${{ matrix.directory }}'
with:
script: |
const { owner, repo } = context.repo;
const query = `query($owner: String!, $repo: String!, $refPrefix: String!) {
repository(owner: $owner, name: $repo) {
refs(refPrefix: $refPrefix, first: 1, orderBy: {field: TAG_COMMIT_DATE, direction: DESC}) {
edges { node { name } }
}
}
}`;
const result = await github.graphql(query, { owner, repo,
refPrefix: `refs/tags/rel/${process.env.PACKAGE_NAME}/`,
});
const prevNode = result.repository.refs.edges[0];
const prevVer = prevNode ? prevNode.node.name : '0.0.0';
console.log('Found previous version', prevVer);
return prevVer;
result-encoding: string
- name: Determine new version number
uses: actions/github-script@v4
id: new-version
env:
PREV_VERSION: '${{ steps.prev-version.outputs.result }}'
RELEASE_TYPE: '${{ needs.detect.outputs.release-type }}'
with:
script: |
const { PREV_VERSION, RELEASE_TYPE } = process.env;
console.log('Previous version was', PREV_VERSION);
console.log('Release type is', RELEASE_TYPE);
const numbers = PREV_VERSION.split('.');
const numberIdx = ['major', 'minor', 'patch'].indexOf(RELEASE_TYPE);
numbers[numberIdx] = parseInt(numbers[numberIdx]) + 1;
for (let i = numberIdx + 1; i < numbers.length; i++) {
numbers[i] = 0;
}
return numbers.join('.');
result-encoding: string
- name: Store version numbers
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: |
mkdir output
echo '${{ steps.prev-version.outputs.result }}' > output/previous-version.txt
echo '${{ steps.new-version.outputs.result }}' > output/new-version.txt
- name: Extract changelog entry
uses: actions/github-script@v5
with:
script: |
const { owner, repo } = context.repo;
const { data: prInfo } = await github.rest.pulls.get({
owner, repo,
pull_number: context.issue.number,
});
console.log('Found PR body:|');
console.log(prInfo.body);
const changelogEntry = ((prInfo.body
.split(/^#+ ?/m)
.find(x => x.startsWith('Changelog'))
|| '').split(/^```/m)[1] || '').trim();
if (!changelogEntry)
throw `'Changelog' section not found in PR body! Please add it back.`;
if (changelogEntry.match(/^TODO:/m))
throw `'Changelog' section needs proper text, instead of 'TODO'`;
const { writeFile } = require('fs').promises;
await writeFile('output/changelog.md', `
* PR [#${ prInfo.number }](${ prInfo.html_url }) - ${ prInfo.title }
\`\`\`
${changelogEntry}
\`\`\`
`.trimLeft(), { encoding: 'utf-8' })
- name: Document example 'source' line
run: |
cat > output/documentation.md <<'EOF'
# Module Location
To use this module in your Terraform, use the below source value.
```hcl
module "my_${{ matrix.directory }}" {
source = "s3::https://forto-terrform-modules-demo.s3.eu-west-1.amazonaws.com/${{ matrix.directory }}-${{ steps.new-version.outputs.result }}.zip"
# also any inputs for the module (see below)
}
```
EOF
- name: Install terraform docs
run: |
wget https://github.com/terraform-docs/terraform-docs/releases/download/v0.15.0/terraform-docs-v0.15.0-linux-amd64.tar.gz \
--output-document - \
--progress dot:mega \
| tar -xvz
- name: Clone repository for analysis
uses: actions/checkout@v2
with:
ref: ${{ github.sha }}
path: src
- name: Render terraform docs
run: |
echo '# Module Attributes' >> output/documentation.md
./terraform-docs markdown table \
--output-file "$(pwd)"/output/documentation.md \
--sort-by required \
'src/${{ matrix.directory }}'
- name: Bundle up Terraform module
working-directory: src/${{ matrix.directory }}
run: zip -vr ../../output/terraform-module.zip *
- name: Upload result artifacts
uses: actions/upload-artifact@v2
with:
name: '${{ matrix.directory }}'
path: output
retention-days: 5
comment:
needs: [detect, plan]
if: needs.detect.outputs.is-merge-event == 'false'
runs-on: ubuntu-latest
name: 'Comment on PR'
steps:
- uses: actions/[email protected]
with:
path: outputs
- name: Display structure of downloaded files
run: ls -R
working-directory: outputs
- uses: actions/github-script@v2
with:
script: |
const { owner, repo } = context.repo;
const { number: issue_number } = context.issue;
const { readdir, readFile } = require('fs').promises;
const utf8 = { encoding: 'utf-8' };
const lines = [
'# Release plan', '',
'| Directory | Previous version | New version |',
'|--|--|--|',
];
const sections = [];
for (const folder of await readdir('outputs', { withFileTypes: true })) {
if (!folder.isDirectory()) continue;
const readText = (name) => readFile(name, utf8).then(x => x.trim());
lines.push('| '+[
`\`${folder.name}\``,
`${await readText(`outputs/${folder.name}/previous-version.txt`)}`,
`**${await readText(`outputs/${folder.name}/new-version.txt`)}**`,
].join(' | ')+' |');
sections.push(`<details><summary>Changelog preview: ${folder.name}</summary>\n\n${await readText(`outputs/${folder.name}/changelog.md`)}\n</details>`);
}
const finalBody = [lines.join('\n'), ...sections].join('\n\n');
const {data: allComments} = await github.issues.listComments({ issue_number, owner, repo });
const ourComments = allComments
.filter(comment => comment.user.login === 'github-actions[bot]')
.filter(comment => comment.body.startsWith(lines[0]+'\n'));
const latestComment = ourComments.slice(-1)[0];
if (latestComment && latestComment.body === finalBody) {
console.log('Existing comment is already up to date.');
return;
}
const {data: newComment} = await github.issues.createComment({ issue_number, owner, repo, body: finalBody });
console.log('Posted comment', newComment.id, '@', newComment.html_url);
// Delete all our previous comments
for (const comment of ourComments) {
if (comment.id === newComment.id) continue;
console.log('Deleting previous PR comment from', comment.created_at);
await github.issues.deleteComment({ comment_id: comment.id, owner, repo });
}
trigger-release:
needs: [detect, plan]
if: needs.detect.outputs.is-merge-event == 'true'
runs-on: ubuntu-latest
name: 'Dispatch release event'
steps:
- uses: actions/[email protected]
with:
path: outputs
- name: Combine version information
id: extract-releases
uses: actions/github-script@v2
with:
script: |
const { readdir, readFile } = require('fs').promises;
const utf8 = { encoding: 'utf-8' };
const readText = (name) => readFile(name, utf8).then(x => x.trim());
const directories = await readdir('outputs', { withFileTypes: true });
return await Promise.all(directories
.filter(x => x.isDirectory())
.map(async folder => ({
module: folder.name,
prevVersion: await readText(`outputs/${folder.name}/previous-version.txt`),
newVersion: await readText(`outputs/${folder.name}/new-version.txt`),
})));
- name: Dispatch monorepo_release event
uses: actions/github-script@v2
env:
RELEASE_LIST: '${{ steps.extract-releases.outputs.result }}'
with:
github-token: ${{ secrets.GH_PAT_FREIGHTBOT }}
script: |
const payload = {
run_id: "${{ github.run_id }}",
sha: context.sha,
releases: JSON.parse(process.env.RELEASE_LIST),
};
console.log('Event payload:', JSON.stringify(payload, null, 2));
const { owner, repo } = context.repo;
await github.repos.createDispatchEvent({
owner, repo,
event_type: 'monorepo_release',
client_payload: payload,
});