├── .editorconfig ├── .github └── workflows │ ├── gradle-versions-watchdog.yml │ ├── gradle.yml │ └── release.yml ├── .gitignore ├── .lazybones └── stored-params.properties ├── README.md ├── build.gradle ├── config ├── checkstyle │ └── checkstyle.xml └── codenarc │ └── codenarc.xml ├── docs └── guide │ ├── guide.gradle │ └── src │ └── docs │ └── asciidoc │ ├── _links.adoc │ ├── index.adoc │ ├── installation.adoc │ ├── introduction.adoc │ └── usage.adoc ├── examples └── remember-example │ └── remember-example.gradle ├── gradle.properties ├── gradle ├── LICENSE_HEADER └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libs └── remember │ ├── remember.gradle │ └── src │ ├── main │ └── groovy │ │ └── com │ │ └── agorapulse │ │ └── remember │ │ ├── DoNotMerge.java │ │ ├── DoNotMergeTransformation.java │ │ ├── Remember.java │ │ └── RememberTransformation.java │ └── test │ └── groovy │ └── com │ └── agorapulse │ └── remember │ ├── DoNotMergeSpec.groovy │ └── RememberSpec.groovy └── settings.gradle /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | 15 | [*.yml] 16 | # YAML should be space separated see https://en.wikipedia.org/wiki/YAML#Pitfalls_and_implementation_defects 17 | indent_style = space 18 | indent_size = 2 -------------------------------------------------------------------------------- /.github/workflows/gradle-versions-watchdog.yml: -------------------------------------------------------------------------------- 1 | name: Gradle RC Watchdog 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 13 * *' 6 | 7 | jobs: 8 | check: 9 | name: Verify the Latest Gradle Version 10 | runs-on: ubuntu-latest 11 | env: 12 | GRADLE_OPTS: "-Xmx6g -Xms4g" 13 | CI: true 14 | 15 | steps: 16 | - uses: actions/checkout@v1 17 | 18 | - name: Set up JDK 1.8 19 | uses: actions/setup-java@v1 20 | with: 21 | java-version: 1.8 22 | - uses: eskatos/gradle-command-action@v1 23 | with: 24 | arguments: check --stacktrace 25 | gradle-version: rc 26 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | # Copyright 2019-2021 Agorapulse. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | name: Check 20 | 21 | on: [push, pull_request] 22 | jobs: 23 | check: 24 | name: Check 25 | runs-on: ubuntu-latest 26 | env: 27 | GRADLE_OPTS: "-Xmx6g -Xms4g" 28 | COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} 29 | 30 | steps: 31 | - uses: actions/checkout@v1 32 | 33 | - name: Set up JDK 1.8 34 | uses: actions/setup-java@v1 35 | with: 36 | java-version: 1.8 37 | 38 | - uses: actions/cache@v1 39 | with: 40 | path: ~/.gradle/caches 41 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}-${{ hashFiles('**/gradle.properties') }} 42 | restore-keys: | 43 | ${{ runner.os }}-gradle- 44 | - uses: eskatos/gradle-command-action@v1 45 | with: 46 | arguments: check coveralls --stacktrace 47 | - name: Show Reports 48 | uses: actions/upload-artifact@v1 49 | if: failure() 50 | with: 51 | name: reports 52 | path: build/reports/ 53 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | release: 8 | name: Release 9 | runs-on: ubuntu-latest 10 | env: 11 | GRADLE_OPTS: "-Xmx6g -Xms4g" 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Set up JDK 1.8 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 1.8 18 | - name: Semantic Version 19 | id: version 20 | uses: ncipollo/semantic-version-action@v1 21 | - uses: eskatos/gradle-command-action@v1 22 | with: 23 | arguments: gitPublishPush bintrayUpload -PbintrayUsername=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }} -Pversion=${{ steps.version.outputs.tag }} -Prelease=true -Dorg.ajoberstar.grgit.auth.username=${{ secrets.AGORAPULSE_BOT_PERSONAL_TOKEN }} --stacktrace 24 | ping: 25 | name: Notify Upstream Repositories 26 | runs-on: ubuntu-latest 27 | needs: [release] 28 | strategy: 29 | matrix: 30 | repository: 31 | - agorapulse/agorapulse-bom 32 | steps: 33 | - uses: actions/checkout@v1 34 | - name: Semantic Version 35 | id: version 36 | uses: ncipollo/semantic-version-action@v1 37 | - name: Dispatch to ${{ matrix.repository }} 38 | uses: peter-evans/repository-dispatch@v1 39 | with: 40 | token: ${{ secrets.AGORAPULSE_BOT_PERSONAL_TOKEN }} 41 | repository: ${{ matrix.repository }} 42 | event-type: ap-new-version-released-event 43 | client-payload: '{ "group": "com.agorapulse", "module": "remember", "version": "${{ steps.version.outputs.tag }}", "property" : "remember.version", "github" : ${{ toJson(github) }} }' 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Gradle 3 | build/ 4 | .gradle/ 5 | 6 | # IDEs 7 | 8 | *.c9 9 | *.iml 10 | *.ipr 11 | *.iws 12 | *.vscode 13 | .idea/ 14 | .asscache 15 | MANIFEST.MF 16 | out 17 | 18 | # PAW 19 | *.paw 20 | 21 | # Redis 22 | *.rdb 23 | 24 | -------------------------------------------------------------------------------- /.lazybones/stored-params.properties: -------------------------------------------------------------------------------- 1 | #Lazybones saved template parameters 2 | #Tue Apr 13 05:26:25 CEST 2021 3 | name=Agorapulse Remember 4 | id=remember 5 | dev.name=Vladimir Orany 6 | dev.id=musketyr 7 | bintray.repo=libs 8 | bintray.org=agorapulse 9 | desc=Agorapulse Remember 10 | pkg=com.agorapulse.remember 11 | vendor=Agorapulse 12 | group=com.agorapulse 13 | org=agorapulse 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Agorapulse Remember 2 | 3 | [![Build Status](https://github.com/agorapulse/remember/workflows/Check/badge.svg)](https://github.com/agorapulse/remember/actions) 4 | [![Download](https://api.bintray.com/packages/agorapulse/libs/remember/images/download.svg)](https://bintray.com/agorapulse/libs/remember/_latestVersion) 5 | [![Coverage Status](https://coveralls.io/repos/github/agorapulse/remember/badge.svg?branch=master)](https://coveralls.io/github/agorapulse/remember?branch=master) 6 | 7 | See [Full Documentation][DOCS] 8 | 9 | [DOCS]: https://agorapulse.github.io/remember 10 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | plugins { 19 | id 'org.kordamp.gradle.groovy-project' 20 | id 'org.kordamp.gradle.bintray' 21 | id 'org.kordamp.gradle.checkstyle' 22 | id 'org.kordamp.gradle.codenarc' 23 | id 'org.kordamp.gradle.coveralls' 24 | } 25 | 26 | if (!project.hasProperty('bintrayUsername')) ext.bintrayUsername = '**UNDEFINED**' 27 | if (!project.hasProperty('bintrayApiKey')) ext.bintrayApiKey = '**UNDEFINED**' 28 | 29 | config { 30 | release = (rootProject.findProperty('release') ?: false).toBoolean() 31 | 32 | info { 33 | name = 'Agorapulse Remember' 34 | vendor = 'Agorapulse' 35 | description = 'Agorapulse Remember' 36 | 37 | links { 38 | website = "https://github.com/" + slug 39 | issueTracker = "https://github.com/" + slug + "/issues" 40 | scm = "https://github.com/" + slug + ".git" 41 | } 42 | 43 | people { 44 | person { 45 | id = 'musketyr' 46 | name = 'Vladimir Orany' 47 | roles = ['developer'] 48 | } 49 | } 50 | 51 | repositories { 52 | repository { 53 | name = 'localRelease' 54 | url = "" + project.rootProject.buildDir + "/repos/local/release" 55 | } 56 | repository { 57 | name = 'localSnapshot' 58 | url = "" + project.rootProject.buildDir + "/repos/local/snapshot" 59 | } 60 | } 61 | } 62 | 63 | licensing { 64 | licenses { 65 | license { 66 | id = 'Apache-2.0' 67 | } 68 | } 69 | } 70 | 71 | publishing { 72 | signing = false 73 | releasesRepository = 'localRelease' 74 | snapshotsRepository = 'localSnapshot' 75 | } 76 | 77 | bintray { 78 | credentials { 79 | username = bintrayUsername 80 | password = bintrayApiKey 81 | } 82 | // TODO: replace 83 | userOrg = 'agorapulse' 84 | repo = 'libs' 85 | name = 'remember' 86 | publish = true 87 | } 88 | 89 | quality { 90 | checkstyle { 91 | toolVersion = '8.27' 92 | } 93 | 94 | codenarc { 95 | toolVersion = '1.5' 96 | } 97 | } 98 | 99 | docs { 100 | groovydoc { 101 | enabled = false 102 | aggregate { 103 | enabled = false 104 | } 105 | } 106 | } 107 | 108 | } 109 | 110 | allprojects { 111 | repositories { 112 | jcenter() 113 | mavenCentral() 114 | maven { url "https://dl.bintray.com/agorapulse/libs" } 115 | maven { url "https://repo.spring.io/release" } 116 | } 117 | 118 | license { 119 | exclude '**/*.json' 120 | exclude '***.yml' 121 | } 122 | } 123 | 124 | projects { 125 | subprojects { 126 | dirs(['libs', 'examples']) { Project subproject -> 127 | sourceCompatibility = 1.8 128 | targetCompatibility = 1.8 129 | 130 | repositories { 131 | mavenCentral() 132 | } 133 | 134 | config { 135 | bintray { 136 | name = subproject.name 137 | } 138 | } 139 | 140 | // location independent tests (useful for stable CI builds) 141 | tasks.withType(Test) { 142 | useJUnitPlatform() 143 | 144 | systemProperty 'user.timezone', 'UTC' 145 | systemProperty 'user.language', 'en' 146 | } 147 | 148 | tasks.withType(JavaCompile) { 149 | options.encoding = "UTF-8" 150 | options.compilerArgs.add('-parameters') 151 | } 152 | 153 | tasks.withType(GroovyCompile) { 154 | groovyOptions.forkOptions.jvmArgs.add('-Dgroovy.parameters=true') 155 | } 156 | 157 | dependencies { 158 | api platform("org.codehaus.groovy:groovy-bom:$groovyVersion") 159 | compile platform("org.codehaus.groovy:groovy-bom:$groovyVersion") 160 | implementation platform("org.codehaus.groovy:groovy-bom:$groovyVersion") 161 | compileOnly platform("org.codehaus.groovy:groovy-bom:$groovyVersion") 162 | testCompile platform("org.codehaus.groovy:groovy-bom:$groovyVersion") 163 | testImplementation platform("org.codehaus.groovy:groovy-bom:$groovyVersion") 164 | } 165 | 166 | // useful for IntelliJ 167 | task cleanOut(type: Delete) { 168 | delete file('out') 169 | } 170 | 171 | clean.dependsOn cleanOut 172 | } 173 | 174 | dir('libs') { 175 | processResources { 176 | filesMatching('**/org.codehaus.groovy.runtime.ExtensionModule') { 177 | filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [VERSION: version]) 178 | } 179 | } 180 | 181 | jar { 182 | manifest.attributes provider: 'gradle' 183 | } 184 | 185 | config { 186 | bintray { 187 | enabled = true 188 | } 189 | } 190 | 191 | dependencies { 192 | testImplementation group: 'org.spockframework', name: 'spock-core', version: spockVersion 193 | } 194 | } 195 | } 196 | } 197 | 198 | 199 | check.dependsOn('aggregateCheckstyle', 'aggregateCodenarc', 'aggregateAllTestReports', 'coveralls') 200 | -------------------------------------------------------------------------------- /config/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /config/codenarc/codenarc.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | Sample rule set 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/guide/guide.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | plugins { 19 | id 'org.kordamp.gradle.guide' 20 | id 'org.ajoberstar.git-publish' 21 | } 22 | 23 | config { 24 | docs { 25 | guide { 26 | publish { 27 | enabled = true 28 | } 29 | } 30 | } 31 | } 32 | 33 | configurations { 34 | asciidoctorExtensions 35 | } 36 | 37 | dependencies { 38 | asciidoctorExtensions 'com.bmuschko:asciidoctorj-tabbed-code-extension:0.3' 39 | } 40 | 41 | asciidoctor { 42 | configurations 'asciidoctorExtensions' 43 | 44 | baseDirFollowsSourceDir() 45 | 46 | attributes = [ 47 | 'gradle-version': project.gradle.gradleVersion, 48 | 'source-highlighter': 'prettify', 49 | 'root-dir': rootDir, 50 | 'project-slug': slug 51 | ] 52 | 53 | } 54 | -------------------------------------------------------------------------------- /docs/guide/src/docs/asciidoc/_links.adoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agorapulse/remember/28ad2ea05b8846e57a6b2c3fa0c7110b2796dbe1/docs/guide/src/docs/asciidoc/_links.adoc -------------------------------------------------------------------------------- /docs/guide/src/docs/asciidoc/index.adoc: -------------------------------------------------------------------------------- 1 | ifndef::imagesdir[] 2 | :imagesdir: ../resources/images 3 | endif::[] 4 | ifndef::includedir[] 5 | :includedir: . 6 | endif::[] 7 | = {project-title} 8 | :author: {project-author} 9 | :revnumber: {project-version} 10 | :toclevels: 4 11 | :docinfo1: 12 | 13 | include::{includedir}/_links.adoc[] 14 | 15 | :leveloffset: 1 16 | include::{includedir}/introduction.adoc[] 17 | include::{includedir}/installation.adoc[] 18 | include::{includedir}/usage.adoc[] 19 | 20 | = Links 21 | 22 | link:api/index.html[Javadoc, window="_blank"] 23 | 24 | link:api-html/index.html[Source, window="_blank"] 25 | -------------------------------------------------------------------------------- /docs/guide/src/docs/asciidoc/installation.adoc: -------------------------------------------------------------------------------- 1 | [[_installation_]] 2 | = Installation 3 | 4 | 5 | ---- 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | compile 'com.agorapulse:remember:{project-version}' 12 | } 13 | ---- 14 | -------------------------------------------------------------------------------- /docs/guide/src/docs/asciidoc/introduction.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[_introduction]] 3 | = Introduction 4 | 5 | == @Remember 6 | 7 | `@Remember` is an annotation which helps you not to forget any temporary solution (aka hacks or quick wins) 8 | you have introduced into your code base.You specify the date in the future when you want to revisit the code, e.g. `@Remember('2018-12-24)`. 9 | After this date the code no longer compiles forcing you to re-evaluate if the code is still required or to find 10 | more permanent solution. 11 | -------------------------------------------------------------------------------- /docs/guide/src/docs/asciidoc/usage.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[_usage]] 3 | = Usage 4 | 5 | [source,groovy] 6 | ---- 7 | import com.agorapulse.remember.Remember 8 | 9 | @Remember( 10 | value = '2019', 11 | description = 'This method should be already removed', 12 | format = 'yyyy', 13 | owner = 'musketyr', 14 | ci = true 15 | ) 16 | class Subject { } 17 | ---- 18 | 19 | You can modify the format of the date `value` by setting `format` property of the annotation. 20 | 21 | You can customize the message being shown by using `description` property. 22 | 23 | You can add an `owner` who is responsible for action which needs to be taken when the annotation expires. 24 | 25 | You can force failing on continuous integration server by setting `ci` to `true`.By default, the annotation will 26 | only fail during local builds. 27 | 28 | == @DoNotMerge 29 | 30 | If you have a code you want to discuss with your colleagues before merging to the main branch or simply 31 | you have created a temporary solution which should never enter the main branch then you can use `@DoNotMerge` 32 | annotation.If the library recognizes (on a best effort) that the build has been triggered by pull request then 33 | it will fail to compile. 34 | 35 | [source,groovy] 36 | ---- 37 | import com.agorapulse.remember.DoNotMerge 38 | 39 | @DoNotMerge('Just testing some stuff') 40 | class Subject { } 41 | ---- 42 | 43 | -------------------------------------------------------------------------------- /examples/remember-example/remember-example.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // delete if this subproject should not be published to BinTray 20 | 21 | dependencies { 22 | implementation project(":remember") 23 | 24 | // add example project's dependencies 25 | } 26 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | # Copyright 2019-2021 Agorapulse. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | slug=agorapulse/remember 20 | group=com.agorapulse 21 | version=1.0.0-SNAPSHOT 22 | kordampPluginVersion=0.44.0 23 | gitPublishPluginVersion=2.1.3 24 | 25 | groovyVersion=2.5.14 26 | spockVersion=2.0-groovy-2.5 27 | systemLambdaVersion = 1.2.0 28 | 29 | -------------------------------------------------------------------------------- /gradle/LICENSE_HEADER: -------------------------------------------------------------------------------- 1 | SPDX-License-Identifier: Apache-2.0 2 | 3 | Copyright 2019-${copyrightYear} Agorapulse. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | https://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agorapulse/remember/28ad2ea05b8846e57a6b2c3fa0c7110b2796dbe1/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" 184 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /libs/remember/remember.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | dependencies { 19 | compile 'org.codehaus.groovy:groovy' 20 | 21 | testCompile "com.github.stefanbirkner:system-lambda:$systemLambdaVersion" 22 | testCompile 'org.spockframework:spock-core:1.1-groovy-2.4' 23 | testCompile 'org.codehaus.groovy:groovy-test' 24 | } 25 | -------------------------------------------------------------------------------- /libs/remember/src/main/groovy/com/agorapulse/remember/DoNotMerge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.agorapulse.remember; 19 | 20 | import org.codehaus.groovy.transform.GroovyASTTransformationClass; 21 | 22 | import java.lang.annotation.*; 23 | 24 | @Documented 25 | @Retention(RetentionPolicy.SOURCE) 26 | @Target({ 27 | ElementType.TYPE, 28 | ElementType.FIELD, 29 | ElementType.METHOD, 30 | ElementType.PARAMETER, 31 | ElementType.CONSTRUCTOR, 32 | ElementType.LOCAL_VARIABLE, 33 | ElementType.ANNOTATION_TYPE, 34 | ElementType.PACKAGE, 35 | ElementType.TYPE_PARAMETER, 36 | ElementType.TYPE_USE 37 | }) 38 | @GroovyASTTransformationClass("com.agorapulse.remember.DoNotMergeTransformation") 39 | /** 40 | * @DoNotMergeis an annotation which helps you not to forget any temporary solution on a feature branch 41 | * which you have introduced into your code base. The code won't compile if the code is running from pull request continuous build. 42 | * 43 | */ 44 | public @interface DoNotMerge { 45 | 46 | /** 47 | * @return description why should the code expression should not be merged into the main branch 48 | */ 49 | String value() default "Do not merge"; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /libs/remember/src/main/groovy/com/agorapulse/remember/DoNotMergeTransformation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.agorapulse.remember; 19 | 20 | import org.codehaus.groovy.ast.ASTNode; 21 | import org.codehaus.groovy.ast.AnnotationNode; 22 | import org.codehaus.groovy.ast.expr.Expression; 23 | import org.codehaus.groovy.control.CompilePhase; 24 | import org.codehaus.groovy.control.SourceUnit; 25 | import org.codehaus.groovy.syntax.SyntaxException; 26 | import org.codehaus.groovy.transform.ASTTransformation; 27 | import org.codehaus.groovy.transform.GroovyASTTransformation; 28 | 29 | import java.util.Optional; 30 | 31 | /** 32 | * AST Transformation for {@link DoNotMerge} annotation. 33 | */ 34 | @GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS) 35 | public class DoNotMergeTransformation implements ASTTransformation { 36 | 37 | @Override 38 | public void visit(ASTNode[] nodes, SourceUnit source) { 39 | AnnotationNode annotation = (AnnotationNode) nodes[0]; 40 | 41 | Expression valueExpression = annotation.getMember("value"); 42 | String value = Optional.ofNullable(valueExpression).map(Expression::getText).orElse("Do not merge"); 43 | 44 | if (isPullRequest()) { 45 | source.addError(createSyntaxException(annotation, value)); 46 | } 47 | } 48 | 49 | private boolean isPullRequest() { 50 | return isTravisPullRequest() || isGithubActionPullRequest(); 51 | } 52 | 53 | private boolean isGithubActionPullRequest() { 54 | return System.getenv() 55 | .keySet() 56 | .stream() 57 | .filter(key -> key.endsWith("GITHUB_REF")) 58 | .findAny() 59 | .map(System::getenv) 60 | .map(value -> value != null && value.length() > 0 && value.startsWith("refs/pull/")) 61 | .orElse(false); 62 | } 63 | 64 | private boolean isTravisPullRequest() { 65 | return System.getenv() 66 | .keySet() 67 | .stream() 68 | .filter(key -> key.endsWith("PULL_REQUEST")) 69 | .findAny() 70 | .map(System::getenv) 71 | .map(value -> value.length() > 0 && !"false".equals(value)) 72 | .orElse(false); 73 | } 74 | 75 | private SyntaxException createSyntaxException(AnnotationNode annotation, String message) { 76 | return new SyntaxException(message, annotation.getLineNumber(), annotation.getColumnNumber(), annotation.getColumnNumber(), annotation.getLastColumnNumber()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /libs/remember/src/main/groovy/com/agorapulse/remember/Remember.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.agorapulse.remember; 19 | 20 | import org.codehaus.groovy.transform.GroovyASTTransformationClass; 21 | 22 | import java.lang.annotation.*; 23 | 24 | @Documented 25 | @Retention(RetentionPolicy.SOURCE) 26 | @Target({ 27 | ElementType.TYPE, 28 | ElementType.FIELD, 29 | ElementType.METHOD, 30 | ElementType.PARAMETER, 31 | ElementType.CONSTRUCTOR, 32 | ElementType.LOCAL_VARIABLE, 33 | ElementType.ANNOTATION_TYPE, 34 | ElementType.PACKAGE, 35 | ElementType.TYPE_PARAMETER, 36 | ElementType.TYPE_USE 37 | }) 38 | @GroovyASTTransformationClass("com.agorapulse.remember.RememberTransformation") 39 | /** 40 | * @Rememberis an annotation which helps you not to forget any temporary solution (aka hacks or quick wins) 41 | * you have introduced into your code base. You specify the date in the future when you want to revisit the code, e.g. @Remember('2018-12-24). 42 | * After this date the code no longer compiles forcing you to re-evaluate if the code is still required or to find 43 | * more permanent solution. 44 | */ 45 | public @interface Remember { 46 | 47 | /** 48 | * @return date when the annotated element should be revisited 49 | */ 50 | String value(); 51 | 52 | /** 53 | * @return format to be used when parsing value 54 | */ 55 | String format() default RememberTransformation.DEFAULT_FORMAT; 56 | 57 | /** 58 | * @return description to be shown by the compilation error when the value date is already in the past 59 | */ 60 | String description() default RememberTransformation.DEFAULT_DESCRIPTION; 61 | 62 | /** 63 | * @return developer responsible of resoliving the issues associated with this annotation 64 | */ 65 | String owner() default ""; 66 | 67 | /** 68 | * @return whether the annotation should fail during the CI execution, defaults to false 69 | */ 70 | boolean ci() default false; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /libs/remember/src/main/groovy/com/agorapulse/remember/RememberTransformation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.agorapulse.remember; 19 | 20 | import org.codehaus.groovy.ast.ASTNode; 21 | import org.codehaus.groovy.ast.AnnotationNode; 22 | import org.codehaus.groovy.ast.expr.Expression; 23 | import org.codehaus.groovy.control.CompilePhase; 24 | import org.codehaus.groovy.control.SourceUnit; 25 | import org.codehaus.groovy.syntax.SyntaxException; 26 | import org.codehaus.groovy.transform.ASTTransformation; 27 | import org.codehaus.groovy.transform.GroovyASTTransformation; 28 | 29 | import java.text.DateFormat; 30 | import java.text.ParseException; 31 | import java.text.SimpleDateFormat; 32 | import java.util.Date; 33 | 34 | /** 35 | * AST Transformation for {@link Remember} annotation. 36 | */ 37 | @GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS) 38 | public class RememberTransformation implements ASTTransformation { 39 | 40 | static final String DEFAULT_FORMAT = "yyyy-MM-dd"; 41 | static final String DEFAULT_DESCRIPTION = "Please, make sure the annotated element is still valid for your codebase"; 42 | 43 | private static final String CI_ENV_VAR = "CI"; 44 | private static final String CI_SYSTEM_PROPERTY = "ci"; 45 | private static final String GITHUB_WORKFLOW_ENV_VAR = "GITHUB_WORKFLOW"; 46 | 47 | @Override 48 | public void visit(ASTNode[] nodes, SourceUnit source) { 49 | AnnotationNode annotation = (AnnotationNode) nodes[0]; 50 | 51 | Expression valueExpression = annotation.getMember("value"); 52 | String value = valueExpression.getText(); 53 | 54 | Expression formatExpression = annotation.getMember("format"); 55 | String format = formatExpression != null ? formatExpression.getText() : DEFAULT_FORMAT; 56 | 57 | Expression descriptionExpression = annotation.getMember("description"); 58 | String description = descriptionExpression != null ? descriptionExpression.getText() : DEFAULT_DESCRIPTION; 59 | 60 | Expression ciExpression = annotation.getMember("ci"); 61 | boolean ci = ciExpression != null && Boolean.TRUE.toString().equals(ciExpression.getText()); 62 | 63 | if (!ci && isRunningCI()) { 64 | return; 65 | } 66 | 67 | try { 68 | DateFormat dateFormat = new SimpleDateFormat(format); 69 | Date dateToRemember = dateFormat.parse(value); 70 | if (dateToRemember.getTime() < System.currentTimeMillis()) { 71 | source.addError(createSyntaxException(annotation, description)); 72 | } 73 | } catch (ParseException e) { 74 | source.addError(createSyntaxException(annotation, String.format("Unable to parse date '%s' using format '%s':%n%s", value, format, e.toString()))); 75 | } 76 | } 77 | 78 | private boolean isRunningCI() { 79 | return Boolean.TRUE.toString().equals(System.getenv(CI_ENV_VAR)) 80 | || System.getenv(GITHUB_WORKFLOW_ENV_VAR) != null 81 | || Boolean.TRUE.toString().equals(System.getProperty(CI_SYSTEM_PROPERTY)); 82 | } 83 | 84 | private SyntaxException createSyntaxException(AnnotationNode annotation, String message) { 85 | return new SyntaxException(message, annotation.getLineNumber(), annotation.getColumnNumber(), annotation.getColumnNumber(), annotation.getLastColumnNumber()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /libs/remember/src/test/groovy/com/agorapulse/remember/DoNotMergeSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.agorapulse.remember 19 | 20 | import groovy.test.GroovyAssert 21 | import org.codehaus.groovy.control.MultipleCompilationErrorsException 22 | import org.codehaus.groovy.control.messages.SyntaxErrorMessage 23 | import org.codehaus.groovy.syntax.SyntaxException 24 | import spock.lang.Specification 25 | 26 | import static com.github.stefanbirkner.systemlambda.SystemLambda.* 27 | 28 | @SuppressWarnings('TrailingWhitespace') 29 | class DoNotMergeSpec extends Specification { 30 | 31 | public static final String PR_ENV_VAR_NAME = 'GITHUB_REF' 32 | 33 | void 'the annotation is ignored by default'() { 34 | when: 35 | withEnvironmentVariable(PR_ENV_VAR_NAME, null).execute { 36 | // language=Groovy 37 | GroovyAssert.assertScript ''' 38 | import com.agorapulse.remember.DoNotMerge 39 | 40 | @DoNotMerge 41 | class Subject { } 42 | 43 | true 44 | ''' 45 | } 46 | 47 | then: 48 | noExceptionThrown() 49 | } 50 | 51 | void 'the annotation is ignored of the pull request env var is false'() { 52 | when: 53 | // to pass PR build for this library 54 | withEnvironmentVariable(PR_ENV_VAR_NAME, null).execute { 55 | // language=Groovy 56 | GroovyAssert.assertScript ''' 57 | import com.agorapulse.remember.DoNotMerge 58 | 59 | @DoNotMerge 60 | class Subject { } 61 | 62 | true 63 | ''' 64 | } 65 | 66 | then: 67 | noExceptionThrown() 68 | } 69 | 70 | void 'error is reported on PR build'() { 71 | when: 72 | withEnvironmentVariable(PR_ENV_VAR_NAME, 'refs/pull/123456').execute { 73 | // language=Groovy 74 | GroovyAssert.assertScript ''' 75 | import com.agorapulse.remember.DoNotMerge 76 | 77 | @DoNotMerge 78 | class Subject { } 79 | 80 | true 81 | ''' 82 | } 83 | then: 84 | MultipleCompilationErrorsException e = thrown(MultipleCompilationErrorsException) 85 | assertMessage(e, 'Do not merge @ line 4, column 21.') 86 | } 87 | 88 | void 'error is reported on PR build - with details'() { 89 | when: 90 | withEnvironmentVariable(PR_ENV_VAR_NAME, 'refs/pull/123456').execute { 91 | // language=Groovy 92 | GroovyAssert.assertScript """ 93 | import com.agorapulse.remember.DoNotMerge 94 | 95 | @DoNotMerge('This will break everything!') 96 | class Subject { } 97 | 98 | true 99 | """ 100 | } 101 | then: 102 | MultipleCompilationErrorsException e = thrown(MultipleCompilationErrorsException) 103 | assertMessage(e, 'This will break everything! @ line 4, column 21.') 104 | } 105 | 106 | @SuppressWarnings('Instanceof') 107 | private static boolean assertMessage(MultipleCompilationErrorsException multipleCompilationErrorsException, String message) { 108 | assert multipleCompilationErrorsException.errorCollector 109 | assert multipleCompilationErrorsException.errorCollector.errorCount == 1 110 | assert multipleCompilationErrorsException.errorCollector.errors.first() instanceof SyntaxErrorMessage 111 | 112 | SyntaxException exception = multipleCompilationErrorsException.errorCollector.errors.first().cause 113 | assert exception.message == message 114 | 115 | return true 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /libs/remember/src/test/groovy/com/agorapulse/remember/RememberSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.agorapulse.remember 19 | 20 | import groovy.test.GroovyAssert 21 | import org.codehaus.groovy.control.MultipleCompilationErrorsException 22 | import org.codehaus.groovy.control.messages.SyntaxErrorMessage 23 | import org.codehaus.groovy.syntax.SyntaxException 24 | import spock.lang.Specification 25 | import spock.util.environment.RestoreSystemProperties 26 | 27 | import static com.github.stefanbirkner.systemlambda.SystemLambda.* 28 | 29 | @SuppressWarnings('TrailingWhitespace') 30 | class RememberSpec extends Specification { 31 | 32 | void 'remember in future is ignored'() { 33 | when: 34 | withEnvironmentVariable('GITHUB_WORKFLOW', null).and('CI', null).execute { 35 | // language=Groovy 36 | GroovyAssert.assertScript ''' 37 | import com.agorapulse.remember.Remember 38 | 39 | @Remember('2999-01-01') 40 | class Subject { } 41 | 42 | true 43 | ''' 44 | } 45 | then: 46 | noExceptionThrown() 47 | } 48 | 49 | void 'remember in past raises exception'() { 50 | when: 51 | withEnvironmentVariable('GITHUB_WORKFLOW', null).and('CI', null).execute { 52 | // language=Groovy 53 | GroovyAssert.assertScript ''' 54 | import com.agorapulse.remember.Remember 55 | 56 | @Remember('1999-01-01') 57 | class Subject { } 58 | 59 | true 60 | ''' 61 | } 62 | then: 63 | MultipleCompilationErrorsException e = thrown(MultipleCompilationErrorsException) 64 | assertMessage(e, 'Please, make sure the annotated element is still valid for your codebase @ line 4, column 21.') 65 | } 66 | 67 | @RestoreSystemProperties 68 | void 'remember in past does not raises exception on ci'() { 69 | given: 70 | System.setProperty('ci', 'true') 71 | when: 72 | withEnvironmentVariable('GITHUB_WORKFLOW', null).and('CI', null).execute { 73 | // language=Groovy 74 | GroovyAssert.assertScript ''' 75 | import com.agorapulse.remember.Remember 76 | 77 | @Remember('1999-01-01') 78 | class Subject { } 79 | 80 | true 81 | ''' 82 | } 83 | then: 84 | noExceptionThrown() 85 | } 86 | 87 | @RestoreSystemProperties 88 | void 'remember in past raises exception on ci when ci is set to true'() { 89 | given: 90 | System.setProperty('ci', 'true') 91 | when: 92 | withEnvironmentVariable('GITHUB_WORKFLOW', null).and('CI', null).execute { 93 | // language=Groovy 94 | GroovyAssert.assertScript ''' 95 | import com.agorapulse.remember.Remember 96 | 97 | @Remember( 98 | value = '1999-01-01', 99 | ci = true 100 | ) 101 | class Subject { } 102 | 103 | true 104 | ''' 105 | } 106 | then: 107 | MultipleCompilationErrorsException e = thrown(MultipleCompilationErrorsException) 108 | assertMessage(e, 'Please, make sure the annotated element is still valid for your codebase @ line 4, column 21.') 109 | } 110 | 111 | void 'remember in past raises exception (different format)'() { 112 | when: 113 | withEnvironmentVariable('GITHUB_WORKFLOW', null).and('CI', null).execute { 114 | // language=Groovy 115 | GroovyAssert.assertScript ''' 116 | import com.agorapulse.remember.Remember 117 | 118 | @Remember(value = '19990101', format = 'yyyyMMdd') 119 | class Subject { } 120 | 121 | true 122 | ''' 123 | } 124 | then: 125 | MultipleCompilationErrorsException e = thrown(MultipleCompilationErrorsException) 126 | assertMessage(e, 'Please, make sure the annotated element is still valid for your codebase @ line 4, column 21.') 127 | } 128 | 129 | void 'remember in past raises exception (different description)'() { 130 | when: 131 | withEnvironmentVariable('GITHUB_WORKFLOW', null).and('CI', null).execute { 132 | // language=Groovy 133 | GroovyAssert.assertScript ''' 134 | import com.agorapulse.remember.Remember 135 | 136 | @Remember( 137 | value = '2000', 138 | description = 'This method should be already removed', 139 | format = 'yyyy', 140 | owner = 'musketyr' 141 | ) 142 | class Subject { } 143 | 144 | true 145 | ''' 146 | } 147 | then: 148 | MultipleCompilationErrorsException e = thrown(MultipleCompilationErrorsException) 149 | assertMessage(e, 'This method should be already removed @ line 4, column 21.') 150 | } 151 | 152 | @SuppressWarnings('LineLength') 153 | void 'remember wrong date'() { 154 | when: 155 | withEnvironmentVariable('GITHUB_WORKFLOW', null).and('CI', null).execute { 156 | // language=Groovy 157 | GroovyAssert.assertScript ''' 158 | import com.agorapulse.remember.Remember 159 | 160 | @Remember('the milk') 161 | class Subject { } 162 | 163 | true 164 | ''' 165 | } 166 | then: 167 | MultipleCompilationErrorsException e = thrown(MultipleCompilationErrorsException) 168 | assertMessage(e, 'Unable to parse date \'the milk\' using format \'yyyy-MM-dd\':\njava.text.ParseException: Unparseable date: "the milk" @ line 4, column 21.') 169 | } 170 | 171 | private static boolean assertMessage(MultipleCompilationErrorsException multipleCompilationErrorsException, String message) { 172 | assert multipleCompilationErrorsException.errorCollector 173 | assert multipleCompilationErrorsException.errorCollector.errorCount == 1 174 | assert multipleCompilationErrorsException.errorCollector.errors.first() instanceof SyntaxErrorMessage 175 | 176 | SyntaxException exception = multipleCompilationErrorsException.errorCollector.errors.first().cause 177 | assert exception.message == message 178 | 179 | return true 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | * 4 | * Copyright 2019-2021 Agorapulse. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * https://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | buildscript { 19 | repositories { 20 | jcenter() 21 | mavenCentral() 22 | gradlePluginPortal() 23 | } 24 | dependencies { 25 | classpath group: 'org.kordamp.gradle', name: 'settings-gradle-plugin', version: kordampPluginVersion 26 | classpath group: 'org.kordamp.gradle', name: 'groovy-project-gradle-plugin', version: kordampPluginVersion 27 | classpath group: 'org.kordamp.gradle', name: 'bintray-gradle-plugin', version: kordampPluginVersion 28 | classpath group: 'org.kordamp.gradle', name: 'checkstyle-gradle-plugin', version: kordampPluginVersion 29 | classpath group: 'org.kordamp.gradle', name: 'codenarc-gradle-plugin', version: kordampPluginVersion 30 | classpath group: 'org.kordamp.gradle', name: 'guide-gradle-plugin', version: kordampPluginVersion 31 | classpath group: 'org.kordamp.gradle', name: 'coveralls-gradle-plugin', version: kordampPluginVersion 32 | classpath group: 'org.ajoberstar', name: 'gradle-git-publish', version: gitPublishPluginVersion 33 | } 34 | } 35 | 36 | apply plugin: 'org.kordamp.gradle.settings' 37 | 38 | rootProject.name = 'remember-root' 39 | 40 | projects { 41 | directories = ['libs', 'docs', 'examples'] 42 | 43 | plugins { 44 | dir('docs') { 45 | id 'org.kordamp.gradle.guide' 46 | id 'org.ajoberstar.git-publish' 47 | } 48 | dirs(['libs', 'examples']) { 49 | id 'java-library' 50 | id 'groovy' 51 | } 52 | } 53 | } 54 | --------------------------------------------------------------------------------