Skip to content

Commit 7f998fa

Browse files
authored
Merge pull request #1 from aepfli/feature/gitlab-ci-compatibility
Feature/gitlab ci compatibility
2 parents 84d7e18 + 50ff280 commit 7f998fa

File tree

9 files changed

+247
-18
lines changed

9 files changed

+247
-18
lines changed

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__tests__
2+
.github

.github/workflows/ci.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ on: # rebuild any PRs and main branch changes
66
- master
77
- 'releases/*'
88

9+
env:
10+
IMAGE_NAME: wrapper-validation
11+
912
jobs:
1013
build: # make sure build/ci work properly
1114
runs-on: ubuntu-latest
@@ -22,3 +25,42 @@ jobs:
2225
with:
2326
# to allow the invalid wrapper jar present in test data
2427
allow-checksums: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
28+
29+
push:
30+
runs-on: ubuntu-latest
31+
permissions:
32+
packages: write
33+
contents: read
34+
35+
steps:
36+
- uses: actions/checkout@v2
37+
38+
- name: Build image
39+
run: docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}"
40+
41+
- name: Test image
42+
run: |
43+
npm install -g gitlab-ci-local
44+
gitlab-ci-local --file __tests__/.gitlab-ci.yml
45+
46+
- name: Log in to registry
47+
# This is where you will update the PAT to GITHUB_TOKEN
48+
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
49+
if: github.event_name != 'pull_request'
50+
- name: Push image
51+
run: |
52+
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
53+
54+
# Change all uppercase to lowercase
55+
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
56+
# Strip git ref prefix from version
57+
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
58+
# Strip "v" prefix from tag name
59+
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
60+
# Use Docker `latest` tag convention
61+
[ "$VERSION" == "master" ] && VERSION=latest
62+
echo IMAGE_ID=$IMAGE_ID
63+
echo VERSION=$VERSION
64+
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
65+
docker push $IMAGE_ID:$VERSION
66+
if: github.event_name != 'pull_request'

.gitlab-ci.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
2+
3+
4+
# This is a GitLab CI configuration to build the project as a docker image
5+
# The file is generic enough to be dropped in a project containing a working Dockerfile
6+
# Author: Florent CHAUVEAU <[email protected]>
7+
# Mentioned here: https://blog.callr.tech/building-docker-images-with-gitlab-ci-best-practices/
8+
9+
10+
11+
stages:
12+
- build
13+
- test
14+
- push
15+
16+
.docker:
17+
# do not use "latest" here, if you want this to work in the future
18+
image: docker:20
19+
services:
20+
- docker:20-dind
21+
# Use this if your GitLab runner does not use socket binding
22+
# services:
23+
# - docker:dind
24+
25+
before_script:
26+
# docker login asks for the password to be passed through stdin for security
27+
# we use $CI_REGISTRY_PASSWORD here which is a special variable provided by GitLab
28+
# https://docs.gitlab.com/ce/ci/variables/predefined_variables.html
29+
- echo -n $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
30+
31+
Build:
32+
extends: .docker
33+
stage: build
34+
script:
35+
# fetches the latest image (not failing if image is not found)
36+
- docker pull $CI_REGISTRY_IMAGE:latest || true
37+
# builds the project, passing proxy variables, using OCI labels
38+
# notice the cache-from, which is going to use the image we just pulled locally
39+
# the built image is tagged locally with the commit SHA, and then pushed to
40+
# the GitLab registry
41+
- >
42+
docker build
43+
--pull
44+
--cache-from $CI_REGISTRY_IMAGE:latest
45+
--label "org.opencontainers.image.title=$CI_PROJECT_TITLE"
46+
--label "org.opencontainers.image.url=$CI_PROJECT_URL"
47+
--label "org.opencontainers.image.created=$CI_JOB_STARTED_AT"
48+
--label "org.opencontainers.image.revision=$CI_COMMIT_SHA"
49+
--label "org.opencontainers.image.version=$CI_COMMIT_REF_NAME"
50+
--tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
51+
.
52+
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
53+
54+
include:
55+
- local: __tests__/.gitlab-ci.yml
56+
57+
validate-wrapper:
58+
image:
59+
name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
60+
entrypoint: [""]
61+
62+
# Here, the goal is to tag the "master" branch as "latest"
63+
Push latest:
64+
extends: .docker
65+
variables:
66+
# We are just playing with Docker here.
67+
# We do not need GitLab to clone the source code.
68+
GIT_STRATEGY: none
69+
stage: push
70+
only:
71+
# Only "master" should be tagged "latest"
72+
- master
73+
script:
74+
# Because we have no guarantee that this job will be picked up by the same runner
75+
# that built the image in the previous step, we pull it again locally
76+
- docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
77+
# Then we tag it "latest"
78+
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
79+
# Annnd we push it.
80+
- docker push $CI_REGISTRY_IMAGE:latest
81+
82+
# Finally, the goal here is to Docker tag any Git tag
83+
# GitLab will start a new pipeline everytime a Git tag is created, which is pretty awesome
84+
Push tag:
85+
extends: .docker
86+
variables:
87+
# Again, we do not need the source code here. Just playing with Docker.
88+
GIT_STRATEGY: none
89+
stage: push
90+
only:
91+
# We want this job to be run on tags only.
92+
- tags
93+
script:
94+
- docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
95+
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
96+
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM node:12-slim
2+
3+
WORKDIR /app
4+
5+
COPY . .
6+
7+
RUN npm install && npm run-script build && npm install -g
8+
9+
ENTRYPOINT [ "wrapper-validation" ]

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,11 @@ Regardless of what you find, we still kindly request that you reach out to us an
104104

105105
To learn more about verifying the Gradle Wrapper JAR locally, see our
106106
[guide on the topic](https://docs.gradle.org/current/userguide/gradle_wrapper.html#wrapper_checksum_verification).
107+
108+
109+
## Usage in GitLab CI
110+
111+
```yaml
112+
include:
113+
- remote: https://raw.githubusercontent.com/gradle/wrapper-validation-action/master/WrapperValidation.gitlab-ci.yml
114+
```

WrapperValidation.gitlab-ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
validate-wrapper:
2+
stage: .pre
3+
image:
4+
name: ghcr.io/aepfli/wrapper-validation:latest
5+
entrypoint: [""]
6+
script:
7+
- wrapper-validation

package-lock.json

Lines changed: 14 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
"private": true,
55
"description": "Gradle Wrapper Validation Action",
66
"main": "lib/main.js",
7+
"bin": {
8+
"wrapper-validation": "lib/main.js"
9+
},
710
"scripts": {
811
"build": "tsc",
912
"format": "prettier --write **/*.ts",
@@ -26,22 +29,24 @@
2629
"license": "MIT",
2730
"dependencies": {
2831
"@actions/core": "1.4.0",
32+
"commander": "^8.2.0",
2933
"typed-rest-client": "1.8.4",
3034
"unhomoglyph": "1.0.6"
3135
},
3236
"devDependencies": {
33-
"@types/node": "12.20.16",
37+
"@types/js-yaml": "^4.0.3",
38+
"@types/node": "^12.20.33",
3439
"@typescript-eslint/parser": "4.28.4",
3540
"@vercel/ncc": "0.29.0",
3641
"eslint": "7.31.0",
3742
"eslint-plugin-github": "4.1.5",
3843
"eslint-plugin-jest": "24.4.0",
44+
"glob-parent": ">=5.1.2",
3945
"jest": "27.0.6",
40-
"js-yaml": "4.1.0",
46+
"js-yaml": "^4.1.0",
4147
"nock": "13.1.1",
4248
"prettier": "2.3.2",
4349
"ts-jest": "27.0.4",
44-
"typescript": "4.0.8",
45-
"glob-parent": ">=5.1.2"
50+
"typescript": "4.0.8"
4651
}
4752
}

src/main.ts

100644100755
Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,74 @@
1-
import * as path from 'path'
2-
import * as core from '@actions/core'
1+
#!/usr/bin/env node
32

4-
import * as validate from './validate'
3+
import { resolve, dirname } from 'path'
4+
import { promises as fs } from 'fs'
5+
import { setFailed, getInput, info } from '@actions/core'
6+
7+
import { findInvalidWrapperJars } from './validate'
8+
import { Command, Option } from 'commander'
9+
import jsyaml from 'js-yaml'
10+
11+
interface Action {
12+
name: string;
13+
description: string;
14+
author: string;
15+
inputs: Map<string, Input>;
16+
}
17+
18+
interface Input {
19+
description: string;
20+
required?: boolean;
21+
default?: string;
22+
}
523

624
export async function run(): Promise<void> {
725
try {
8-
const result = await validate.findInvalidWrapperJars(
9-
path.resolve('.'),
10-
+core.getInput('min-wrapper-count'),
11-
core.getInput('allow-snapshots') === 'true',
12-
core.getInput('allow-checksums').split(',')
26+
let minWrapperCount: number
27+
let allowSnapshots: string
28+
let allowChecksums: string
29+
30+
if (process.env.GITHUB_ACTION) {
31+
minWrapperCount = +getInput('min-wrapper-count')
32+
allowSnapshots = getInput('allow-snapshots')
33+
allowChecksums = getInput('allow-checksums')
34+
35+
} else {
36+
const program = new Command()
37+
const actionYaml = jsyaml.load(await fs.readFile(dirname(require.main?.filename ??'') + '/../action.yml', 'utf8')) as Action
38+
39+
program
40+
.description(actionYaml.description)
41+
42+
Object.entries(actionYaml.inputs).forEach(([key, value]) => {
43+
program.addOption(
44+
new Option(`--${key} <value>`, value.description)
45+
.default(value.default)
46+
.env(key.toLocaleUpperCase().replace(/-/g, '_')))
47+
})
48+
49+
program.parse(process.argv)
50+
const options = program.opts()
51+
minWrapperCount = +options.minWrapperCount
52+
allowSnapshots = options.allowSnapshots
53+
allowChecksums = options.allowChecksums
54+
}
55+
56+
const result = await findInvalidWrapperJars(
57+
resolve('.'),
58+
minWrapperCount,
59+
allowSnapshots === 'true',
60+
allowChecksums.split(',')
1361
)
1462
if (result.isValid()) {
15-
core.info(result.toDisplayString())
63+
info(result.toDisplayString())
1664
} else {
17-
core.setFailed(
65+
setFailed(
1866
`Gradle Wrapper Validation Failed!\n See https://github.com/gradle/wrapper-validation-action#reporting-failures\n${result.toDisplayString()}`
1967
)
2068
}
2169
} catch (error) {
22-
core.setFailed(error.message)
70+
if (error instanceof Error)
71+
setFailed(error.message)
2372
}
2473
}
2574

0 commit comments

Comments
 (0)