├── .github └── workflows │ └── update-tags.yml ├── adr-issue-template.yaml ├── LICENSE.md ├── CONTRIBUTING.md ├── proposed └── action.yaml ├── README.md └── accepted └── action.yaml /.github/workflows/update-tags.yml: -------------------------------------------------------------------------------- 1 | name: On release 2 | on: 3 | release: 4 | types: [released] 5 | 6 | jobs: 7 | update-tags: 8 | name: update tags 9 | runs-on: ubuntu 10 | steps: 11 | - name: checkout main branch 12 | uses: actions/checkout@v3 13 | with: 14 | ref: main 15 | 16 | - name: update the major version tag 17 | run: | 18 | TAG=${{ github.event.release.tag_name }} 19 | MAJOR="$(echo $TAG | sed -r 's/\.[0-9]+\.[0-9]+$//')" 20 | git tag -f $MAJOR $TAG 21 | git push -f --tags -------------------------------------------------------------------------------- /adr-issue-template.yaml: -------------------------------------------------------------------------------- 1 | name: Architecure decision record (ADR) 2 | description: Open a new draft ADR 3 | labels: ["ADR"] 4 | body: 5 | - type: textarea 6 | id: context 7 | validations: 8 | required: true 9 | attributes: 10 | label: Context 11 | description: > 12 | Describe the motivating factors behind this decision: social, politlcal, 13 | technical, etc. Why does this decision need to be made? This section should 14 | be a statement of facts. 15 | - type: textarea 16 | id: decision 17 | validations: 18 | required: true 19 | attributes: 20 | label: Decision 21 | description: > 22 | What was decided? This should be an active-voice statement. For example, 23 | "We will use the US Web Design System." 24 | - type: textarea 25 | id: consequences 26 | validations: 27 | required: true 28 | attributes: 29 | label: Consequences 30 | description: > 31 | What are the consequences of this decision? Consequences can be 32 | positive, negative, or neutral, but all known consequences of this 33 | decision should be listed here. 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | As a work of the United States Government, this project is in the 2 | public domain within the United States. 3 | 4 | Additionally, we waive copyright and related rights in the work 5 | worldwide through the CC0 1.0 Universal public domain dedication. 6 | 7 | ## CC0 1.0 Universal Summary 8 | 9 | This is a human-readable summary of the [Legal Code (read the full text)](https://creativecommons.org/publicdomain/zero/1.0/legalcode). 10 | 11 | ### No Copyright 12 | 13 | The person who associated a work with this deed has dedicated the work to 14 | the public domain by waiving all of his or her rights to the work worldwide 15 | under copyright law, including all related and neighboring rights, to the 16 | extent allowed by law. 17 | 18 | You can copy, modify, distribute and perform the work, even for commercial 19 | purposes, all without asking permission. 20 | 21 | ### Other Information 22 | 23 | In no way are the patent or trademark rights of any person affected by CC0, 24 | nor are the rights that other persons may have in the work or in how the 25 | work is used, such as publicity or privacy rights. 26 | 27 | Unless expressly stated otherwise, the person who associated a work with 28 | this deed makes no warranties about the work, and disclaims liability for 29 | all uses of the work, to the fullest extent permitted by applicable law. 30 | When using or citing the work, you should not imply endorsement by the 31 | author or the affirmer. 32 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Welcome! 2 | 3 | We're so glad you're thinking about contributing to an 18F open source project! 4 | If you're unsure about anything, just ask -- or submit the issue or pull request 5 | anyway. The worst that can happen is you'll be politely asked to change 6 | something. We love all friendly contributions. 7 | 8 | We want to ensure a welcoming environment for all of our projects. Our staff 9 | follow the [18F Code of Conduct](https://github.com/18F/code-of-conduct/blob/master/code-of-conduct.md) 10 | and all contributors should do the same. 11 | 12 | We encourage you to read this project's CONTRIBUTING policy (you are here), its 13 | [LICENSE](LICENSE.md), and its [README](README.md). 14 | 15 | If you have any questions or want to read more, check out the 16 | [18F Open Source Policy GitHub repository](https://github.com/18f/open-source-policy), 17 | or just [send us an email](mailto:18f@gsa.gov). 18 | 19 | ## Public domain 20 | 21 | This project is in the worldwide [public domain](LICENSE.md). 22 | 23 | This project is in the public domain within the United States, and copyright and 24 | related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/). 25 | 26 | All contributions to this project will be released under the CC0 dedication. By 27 | submitting a pull request, you are agreeing to comply with this waiver of 28 | copyright interest. 29 | -------------------------------------------------------------------------------- /proposed/action.yaml: -------------------------------------------------------------------------------- 1 | name: ADR proposed 2 | description: | 3 | When an issue is created as an architectural decision record, add a comment to 4 | describe how to automatically create the ADR documentation when the issue is 5 | closed as accepted. This action should only be used in conjunction with the 6 | ADR acceptance action or else the comment won't make any sense. 7 | 8 | inputs: 9 | label: 10 | description: | 11 | The name of the issue label that indicates this issue is an ADR. Defaults 12 | to "ADR". This value is case sensitive! 13 | default: "ADR: accepted" 14 | repo-token: 15 | description: | 16 | A GitHub token with permission to write issue comments on your repository. 17 | required: true 18 | 19 | runs: 20 | using: composite 21 | 22 | steps: 23 | - name: check for tags 24 | if: "${{github.event.issue.state != 'open' || !contains(github.event.issue.labels.*.name, inputs.label) }}" 25 | run: exit 0 26 | 27 | - name: add comment if appropriate 28 | uses: actions/github-script@v6 29 | with: 30 | github-token: ${{ inputs.repo-token }} 31 | script: | 32 | const { data: comments } = await github.rest.issues.listComments({ 33 | owner: context.repo.owner, 34 | repo: context.repo.repo, 35 | issue_number: context.issue.number 36 | }); 37 | 38 | const botHasCommented = comments.some(({ user: { login }}) => login === 'github-actions[bot]'); 39 | 40 | if(!botHasCommented) { 41 | github.rest.issues.createComment({ 42 | issue_number: context.issue.number, 43 | owner: context.repo.owner, 44 | repo: context.repo.repo, 45 | body: 'This issue appears to be a draft or in-progress ADR. When it is completed and accepted, add the ADR acceptance label and close the issue. This will start a process to create the ADR document and add it to the repo automatically. If you close the issue before adding the label, simply re-open and re-close it.' 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Achitectural Decision Record helpers 2 | 3 | This repo has two GitHub Actions to help with creating architectural decision 4 | records (ADRs). There is also an issue template to help teams draft consistent 5 | ADRs. 6 | 7 | By using the template together with the actions, you can manage the drafting, 8 | acceptance, and recording of ADRs automatically. 9 | 10 | ### Issue template 11 | 12 | The best way to use the issue template is to copy it from 13 | [`adr-issue-template.yaml`](/adr-issue-template.yaml) into the 14 | `.github/ISSUE_TEMPLATES/` of your repository. If you want to use a different 15 | label to identify your ADRs, modify that file. 16 | 17 | ### Proposing an ADR 18 | 19 | Beyond the issue template, this repo doesn't provide much for when an ADR is 20 | first proposed. However, it can add a comment to your ADR issue letting 21 | contributors know the process for accepting the ADR and kicking off the 22 | automation to store it. To use this proposal action, your workflow file might 23 | look something like this: 24 | 25 | 26 | ```yaml 27 | name: ADR proposed 28 | on: 29 | # When an issue is given a label... 30 | issues: 31 | types: 32 | - labeled 33 | 34 | jobs: 35 | main: 36 | name: ADR proposed 37 | runs-on: ubuntu-latest 38 | 39 | steps: 40 | # ..post a comment if the issue is an ADR 41 | - name: post ADR comment 42 | uses: 18F/adr-automation/proposed@v1 43 | with: 44 | repo-token: ${{ secrets.GITHUB_TOKEN }} 45 | ``` 46 | 47 | **Inputs:** 48 | |name|description|default|required| 49 | |---|---|---|---| 50 | |repo-token|A GitHub token with permission to write issue comments on your repository||true| 51 | |label|The name of the issue label that indicates the issue is an ADR. This value is case sensitive!|`ADR`|false| 52 | 53 | ### Accepting an ADR 54 | 55 | When you close an issue with the appropriate tag, the acceptance action can take 56 | the body of your issue, turn it into an ADR document, note it with the correct 57 | time and ADR number, and open a pull request to merge it into your repo. To use 58 | this action, your workflow file will be something like this: 59 | 60 | ```yaml 61 | name: ADR accepted 62 | on: 63 | issues: 64 | types: 65 | - closed 66 | 67 | jobs: 68 | main: 69 | name: ADR accepted 70 | runs-on: ubuntu-latest 71 | 72 | steps: 73 | - name: memorialize the ADR 74 | uses: 18F/adr-automation/accepted@v1 75 | with: 76 | repo-token: ${{ secrets.GITHUB_TOKEN }} 77 | ``` 78 | 79 | |name|description|default|required| 80 | |---|---|---|---| 81 | |repo-token|A GitHub token with permission to write issue comments on your repository||true| 82 | |label|The name of the issue label that indicates that the ADR is accepted. This value is case sensitive!|`ADR: accepted`|false| 83 | |path|The path in your repor where ADRs should be written.|`docs/architecture/decisions/`|false| 84 | |pr-label|The label to apply to the created pull reqeust. Set to `true` to re-use the issue label, `false` to not label the pull request, or a string to set a custom label.|`true`|false| -------------------------------------------------------------------------------- /accepted/action.yaml: -------------------------------------------------------------------------------- 1 | name: ADR accepted 2 | description: | 3 | When an architectural decision record is accepted, opens a pull request to 4 | memorialize the decision in the repo. 5 | 6 | inputs: 7 | label: 8 | description: | 9 | The name of the issue label that indicates the ADR has been accepted. 10 | Defaults to "ADR: accepted". This value is case sensitive! 11 | default: "ADR: accepted" 12 | path: 13 | description: | 14 | The path in your repo where ADRs should be written. Defaults to 15 | docs/architecture/decisions/ 16 | default: docs/architecture/decisions/ 17 | pr-label: 18 | description: | 19 | The label to apply to the created pull reqeust. Set to true to re-use the 20 | issue label, false to not label the pull request, or a string to set a 21 | custom label. 22 | default: true 23 | repo-token: 24 | description: | 25 | A GitHub token with permission to read and create pull requests on your 26 | repository. 27 | required: true 28 | 29 | runs: 30 | using: composite 31 | 32 | steps: 33 | - name: check for tags 34 | if: ${{ !contains(github.event.issue.labels.*.name, inputs.label )}} 35 | shell: bash 36 | run: exit 0 37 | 38 | - name: checkout main branch 39 | uses: actions/checkout@v3 40 | with: 41 | ref: main 42 | 43 | - name: get ADR number 44 | id: next 45 | shell: bash 46 | run: | 47 | mkdir -p ${{ inputs.path }} 48 | LAST_ADR=$(ls ${{ inputs.path }}/*.md | grep -Eo "/[0-9]+-" | sort | tail -n1 | grep -Eo "[0-9]+") 49 | LAST_ADR=$(echo "$LAST_ADR" | sed -E 's/^0+//') 50 | NEXT_ADR=$(($LAST_ADR + 1)) 51 | NEXT_ADR=$(printf "%04i" "$NEXT_ADR") 52 | echo "number=$NEXT_ADR" >> "$GITHUB_OUTPUT" 53 | 54 | - name: write the ADR 55 | shell: bash 56 | run: | 57 | SLUG=$(echo "${{ github.event.issue.title }}" | tr A-Z a-z) 58 | SLUG=$(echo "$SLUG" | iconv -c -t ascii//TRANSLIT) 59 | SLUG=$(echo "$SLUG" | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/-+/-/g' | sed -E 's/^-+|-+$//g') 60 | 61 | FILENAME="${{ inputs.path }}/${{ steps.next.outputs.number }}-$SLUG.md" 62 | 63 | DATE=$(date -I) 64 | 65 | echo "# ${{ github.event.issue.title }}" > $FILENAME 66 | echo "" >> $FILENAME 67 | echo "Date: $DATE" >> $FILENAME 68 | echo "" >> $FILENAME 69 | echo "### Status" >> $FILENAME 70 | echo "" >> $FILENAME 71 | echo "Accepted" >> $FILENAME 72 | echo "" >> $FILENAME 73 | echo "${{ github.event.issue.body }}" >> $FILENAME 74 | 75 | - name: branch, commit, and open PR 76 | shell: bash 77 | env: 78 | GH_TOKEN: ${{ inputs.repo_token }} 79 | run: | 80 | BRANCH="adr/auto/${{ steps.next.outputs.number }}" 81 | git config --global user.email "tts@gsa.gov" 82 | git config --global user.name "TTS ADR automation" 83 | git checkout -b $BRANCH 84 | git add ${{ inputs.path }}/*.md 85 | git commit -m "add ADR ${{ steps.next.outputs.number }}: ${{ github.event.issue.title }}" 86 | git push -f origin $BRANCH 87 | gh pr create \ 88 | --title "Add ADR ${{ steps.next.outputs.number }} to the repo" \ 89 | ${{ inputs.pr-label == false && '' || '--label "${{ inputs.pr-label == true && inputs.label || inputs.pr-label }}" \' }} 90 | --body "This pull request was opened automatically because #${{ github.event.issue.number }} was closed after being marked as an approved ADR. It contains a markdown file capturing the ADR body at the time the issue was closed. Please verify that the markdown is correct before merging!" || true 91 | gh pr merge $BRANCH --auto --squash || true 92 | --------------------------------------------------------------------------------