bitwarden_workflow_linter 0.0.3__tar.gz → 0.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/CODEOWNERS +1 -1
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/renovate.json +1 -0
- bitwarden_workflow_linter-0.0.4/.github/workflows/_version_type.yml +57 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/workflows/cd.yml +35 -48
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/workflows/ci.yml +2 -2
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/workflows/enforce-labels.yml +1 -2
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/workflows/scan.yml +5 -5
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.gitignore +5 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/PKG-INFO +5 -1
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/README.md +4 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/package-lock.json +8 -8
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/package.json +2 -2
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/settings.yaml +1 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/__about__.py +1 -1
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/actions.py +0 -2
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/cli.py +0 -3
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/default_settings.yaml +1 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/lint.py +0 -1
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/load.py +0 -5
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/models/job.py +2 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rule.py +0 -2
- bitwarden_workflow_linter-0.0.4/src/bitwarden_workflow_linter/rules/underscore_outputs.py +111 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/utils.py +0 -9
- bitwarden_workflow_linter-0.0.4/tests/fixtures/test-outputs-incorrect.yml +45 -0
- bitwarden_workflow_linter-0.0.4/tests/rules/test_underscore_output.py +259 -0
- bitwarden_workflow_linter-0.0.3/.github/workflows/_version_type.yml +0 -60
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.editorconfig +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.gitattributes +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.husky/pre-commit +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.python-version +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/CONTRIBUTING.md +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/LICENSE.txt +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/Pipfile +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/Pipfile.lock +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/SECURITY.md +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/Taskfile.yml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/pylintrc +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/pyproject.toml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/pyproject.toml.tpl +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/__init__.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/default_actions.json +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/models/__init__.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/models/step.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/models/workflow.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rules/__init__.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rules/job_environment_prefix.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rules/name_capitalized.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rules/name_exists.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rules/pinned_job_runner.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rules/step_approved.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/src/bitwarden_workflow_linter/rules/step_pinned.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/__init__.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/conftest.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test-alt.yml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test-min-incorrect.yaml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test-min.yaml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test.yml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test_a.yaml +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/__init__.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_job_environment_prefix.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_name_capitalized.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_name_exists.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_pinned_job_runner.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_step_approved.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_step_pinned.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/test_job.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/test_lint.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/test_load.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/test_rule.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/test_step.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/test_utils.py +0 -0
- {bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/test_workflow.py +0 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
name: _version_type
|
2
|
+
run-name: Get version type
|
3
|
+
|
4
|
+
on:
|
5
|
+
workflow_call:
|
6
|
+
outputs:
|
7
|
+
version_bump_type:
|
8
|
+
description: "version to be built"
|
9
|
+
value: ${{ jobs.version.outputs.bump_type }}
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
version:
|
13
|
+
name: Calculate Version
|
14
|
+
runs-on: ubuntu-22.04
|
15
|
+
outputs:
|
16
|
+
bump_type: ${{ steps.bump-type.outputs.type }}
|
17
|
+
steps:
|
18
|
+
- name: Get PR ID
|
19
|
+
id: pr
|
20
|
+
env:
|
21
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
22
|
+
run: |
|
23
|
+
commit_message=$(
|
24
|
+
curl -s -L \
|
25
|
+
-H "Accept: application/vnd.github+json" \
|
26
|
+
-H "Authorization: Bearer $GH_TOKEN" \
|
27
|
+
-H "X-GitHub-Api-Version: 2022-11-28" \
|
28
|
+
https://api.github.com/repos/${{ github.repository }}/commits/${{ github.sha }} | \
|
29
|
+
jq -r ".commit.message"
|
30
|
+
)
|
31
|
+
ID=$(echo "$commit_message" | head -1 | grep -o "(#.*)" | grep -o "[0-9]*")
|
32
|
+
echo "id=$ID" >> $GITHUB_OUTPUT
|
33
|
+
|
34
|
+
- name: Get version bump type
|
35
|
+
id: bump-type
|
36
|
+
env:
|
37
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
38
|
+
PR_NUMBER: ${{ steps.pr.outputs.id }}
|
39
|
+
run: |
|
40
|
+
version_tag=$(
|
41
|
+
curl -s -L \
|
42
|
+
-H "Accept: application/vnd.github+json" \
|
43
|
+
-H "Authorization: Bearer $GH_TOKEN" \
|
44
|
+
-H "X-GitHub-Api-Version: 2022-11-28" \
|
45
|
+
https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels | \
|
46
|
+
jq -r ".[].name" | grep "version"
|
47
|
+
)
|
48
|
+
|
49
|
+
# Single Version label Enforcement (should go in CI...)
|
50
|
+
if [[ $(echo $version_tag | wc -w) -gt 1 ]]; then
|
51
|
+
echo "[!] multiple version labels found!"
|
52
|
+
exit 1
|
53
|
+
fi
|
54
|
+
|
55
|
+
version_type=$(echo $version_tag | cut -d ":" -f 2)
|
56
|
+
echo "Version Bump Type: $version_type"
|
57
|
+
echo "type=$version_type" >> $GITHUB_OUTPUT
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/workflows/cd.yml
RENAMED
@@ -1,40 +1,50 @@
|
|
1
|
-
---
|
2
1
|
name: CD
|
3
|
-
run-name: CD ${{ inputs.release_type }}
|
4
2
|
|
5
3
|
on:
|
6
|
-
|
4
|
+
pull_request:
|
5
|
+
types:
|
6
|
+
- closed
|
7
7
|
branches:
|
8
8
|
- main
|
9
9
|
paths:
|
10
10
|
- "src/**"
|
11
|
-
workflow_dispatch:
|
12
|
-
inputs:
|
13
|
-
release_type:
|
14
|
-
description: 'Release type'
|
15
|
-
required: true
|
16
|
-
type: choice
|
17
|
-
default: 'Dry Run'
|
18
|
-
options:
|
19
|
-
- 'Dry Run'
|
20
|
-
- 'Release'
|
21
11
|
|
22
12
|
jobs:
|
23
13
|
version-type:
|
14
|
+
name: Get version type
|
15
|
+
if: github.event.pull_request.merged == true
|
24
16
|
uses: ./.github/workflows/_version_type.yml
|
25
17
|
|
26
18
|
version-bump:
|
27
19
|
name: Version bump
|
20
|
+
if: github.event.pull_request.merged == true
|
28
21
|
runs-on: ubuntu-22.04
|
29
22
|
needs: version-type
|
30
23
|
outputs:
|
31
24
|
version: ${{ steps.get-version.outputs.version }}
|
32
25
|
steps:
|
26
|
+
- name: Login to Azure - CI Subscription
|
27
|
+
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
28
|
+
with:
|
29
|
+
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
30
|
+
|
31
|
+
- name: Retrieve secrets
|
32
|
+
id: retrieve-secrets
|
33
|
+
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
34
|
+
with:
|
35
|
+
keyvault: "bitwarden-ci"
|
36
|
+
secrets: "github-gpg-private-key,
|
37
|
+
github-gpg-private-key-passphrase,
|
38
|
+
github-pat-bitwarden-devops-bot-repo-scope"
|
39
|
+
|
33
40
|
- name: Check out repo
|
34
|
-
uses: actions/checkout@
|
41
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
42
|
+
with:
|
43
|
+
fetch-depth: 0
|
44
|
+
token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
35
45
|
|
36
46
|
- name: Set up Python
|
37
|
-
uses: actions/setup-python@
|
47
|
+
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
38
48
|
with:
|
39
49
|
python-version-file: ".python-version"
|
40
50
|
|
@@ -53,22 +63,8 @@ jobs:
|
|
53
63
|
VERSION=$(hatch version)
|
54
64
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
55
65
|
|
56
|
-
- name: Login to Azure - CI Subscription
|
57
|
-
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
58
|
-
with:
|
59
|
-
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
60
|
-
|
61
|
-
- name: Retrieve secrets
|
62
|
-
id: retrieve-secrets
|
63
|
-
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
64
|
-
with:
|
65
|
-
keyvault: "bitwarden-ci"
|
66
|
-
secrets: "github-gpg-private-key,
|
67
|
-
github-gpg-private-key-passphrase,
|
68
|
-
github-pat-bitwarden-devops-bot-repo-scope"
|
69
|
-
|
70
66
|
- name: Import GPG key
|
71
|
-
uses: crazy-max/ghaction-import-gpg@
|
67
|
+
uses: crazy-max/ghaction-import-gpg@cb9bde2e2525e640591a934b1fd28eef1dcaf5e5 # v6.2.0
|
72
68
|
with:
|
73
69
|
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
|
74
70
|
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
|
@@ -84,41 +80,41 @@ jobs:
|
|
84
80
|
env:
|
85
81
|
OLD_VERSION: ${{ env.OLD_VERSION }}
|
86
82
|
VERSION: ${{ steps.get-version.outputs.version }}
|
87
|
-
if: ${{ github.event_name == 'push' }} || ${{ inputs.release_type != 'Dry Run' }}
|
88
83
|
run: |
|
89
84
|
git commit -am "Bump version from $OLD_VERSION to $VERSION"
|
90
|
-
git tag $VERSION
|
85
|
+
git tag v$VERSION
|
91
86
|
git push
|
92
87
|
git push --tags
|
93
88
|
|
94
89
|
release:
|
95
90
|
name: GitHub release
|
91
|
+
if: github.event.pull_request.merged == true
|
96
92
|
runs-on: ubuntu-22.04
|
97
93
|
needs: version-bump
|
98
|
-
if: ${{ github.event_name == 'push' }} || ${{ inputs.release_type != 'Dry Run' }}
|
99
94
|
steps:
|
100
95
|
- name: Check out repo
|
101
|
-
uses: actions/checkout@
|
96
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
102
97
|
|
103
98
|
- name: Create GitHub release
|
104
99
|
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
|
105
100
|
with:
|
106
101
|
commit: ${{ github.sha }}
|
107
|
-
tag: v${{ steps.version
|
108
|
-
name:
|
102
|
+
tag: v${{ steps.get-version.outputs.version }}
|
103
|
+
name: v${{ steps.get-version.outputs.version }}
|
109
104
|
token: ${{ secrets.GITHUB_TOKEN }}
|
110
105
|
draft: false
|
111
106
|
|
112
107
|
deploy:
|
113
108
|
name: Deploy workflow-linter (v2)
|
109
|
+
if: github.event.pull_request.merged == true
|
114
110
|
runs-on: ubuntu-22.04
|
115
111
|
needs: version-bump
|
116
112
|
steps:
|
117
113
|
- name: Check out repo
|
118
|
-
uses: actions/checkout@
|
114
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
119
115
|
|
120
116
|
- name: Set up Python
|
121
|
-
uses: actions/setup-python@
|
117
|
+
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
122
118
|
with:
|
123
119
|
python-version-file: ".python-version"
|
124
120
|
|
@@ -135,22 +131,13 @@ jobs:
|
|
135
131
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
136
132
|
with:
|
137
133
|
keyvault: "bitwarden-ci"
|
138
|
-
secrets: "pypi-api-token
|
139
|
-
pypi-test-api-token"
|
134
|
+
secrets: "pypi-api-token"
|
140
135
|
|
141
136
|
- name: Build
|
142
137
|
run: hatch build
|
143
138
|
|
144
139
|
- name: Publish
|
145
|
-
if: ${{ github.event_name == 'push' }} || ${{ inputs.release_type != 'Dry Run' }}
|
146
140
|
env:
|
147
141
|
HATCH_INDEX_USER: __token__
|
148
142
|
HATCH_INDEX_AUTH: ${{ steps.retrieve-secret.outputs.pypi-api-token }}
|
149
143
|
run: hatch publish
|
150
|
-
|
151
|
-
- name: Dry Run - Publish
|
152
|
-
if: ${{ github.event_name == 'workflow_dispatch' }} && ${{ inputs.release_type == 'Dry Run' }}
|
153
|
-
env:
|
154
|
-
HATCH_INDEX_USER: __token__
|
155
|
-
HATCH_INDEX_AUTH: ${{ steps.retrieve-secret.outputs.pypi-test-api-token }}
|
156
|
-
run: hatch publish -r test
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/workflows/ci.yml
RENAMED
@@ -13,10 +13,10 @@ jobs:
|
|
13
13
|
runs-on: ubuntu-22.04
|
14
14
|
steps:
|
15
15
|
- name: Check out repo
|
16
|
-
uses: actions/checkout@
|
16
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
17
17
|
|
18
18
|
- name: Set up Python
|
19
|
-
uses: actions/setup-python@
|
19
|
+
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
20
20
|
with:
|
21
21
|
python-version-file: ".python-version"
|
22
22
|
|
@@ -1,4 +1,3 @@
|
|
1
|
-
---
|
2
1
|
name: Enforce PR labels
|
3
2
|
|
4
3
|
on:
|
@@ -9,7 +8,7 @@ jobs:
|
|
9
8
|
uses: bitwarden/gh-actions/.github/workflows/_enforce-labels.yml@main
|
10
9
|
|
11
10
|
enforce-version-label:
|
12
|
-
if:
|
11
|
+
if: "!(contains(github.event.pull_request.labels.*.name, 'version:major') || contains(github.event.pull_request.labels.*.name, 'version:minor') || contains(github.event.pull_request.labels.*.name, 'version:patch'))"
|
13
12
|
name: Enforce version label
|
14
13
|
runs-on: ubuntu-22.04
|
15
14
|
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/workflows/scan.yml
RENAMED
@@ -26,12 +26,12 @@ jobs:
|
|
26
26
|
|
27
27
|
steps:
|
28
28
|
- name: Check out repo
|
29
|
-
uses: actions/checkout@
|
29
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
30
30
|
with:
|
31
31
|
ref: ${{ github.event.pull_request.head.sha }}
|
32
32
|
|
33
33
|
- name: Scan with Checkmarx
|
34
|
-
uses: checkmarx/ast-github-action@
|
34
|
+
uses: checkmarx/ast-github-action@f0869bd1a37fddc06499a096101e6c900e815d81 # 2.0.36
|
35
35
|
env:
|
36
36
|
INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}"
|
37
37
|
with:
|
@@ -46,7 +46,7 @@ jobs:
|
|
46
46
|
--output-path . ${{ env.INCREMENTAL }}
|
47
47
|
|
48
48
|
- name: Upload Checkmarx results to GitHub
|
49
|
-
uses: github/codeql-action/upload-sarif@
|
49
|
+
uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
50
50
|
with:
|
51
51
|
sarif_file: cx_result.sarif
|
52
52
|
|
@@ -60,13 +60,13 @@ jobs:
|
|
60
60
|
|
61
61
|
steps:
|
62
62
|
- name: Check out repo
|
63
|
-
uses: actions/checkout@
|
63
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
64
64
|
with:
|
65
65
|
fetch-depth: 0
|
66
66
|
ref: ${{ github.event.pull_request.head.sha }}
|
67
67
|
|
68
68
|
- name: Scan with SonarCloud
|
69
|
-
uses: sonarsource/sonarcloud-github-action@
|
69
|
+
uses: sonarsource/sonarcloud-github-action@383f7e52eae3ab0510c3cb0e7d9d150bbaeab838 # v3.1.0
|
70
70
|
env:
|
71
71
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
72
72
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: bitwarden_workflow_linter
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.4
|
4
4
|
Summary: Custom GitHub Action Workflow Linter
|
5
5
|
Project-URL: Homepage, https://github.com/bitwarden/workflow-linter
|
6
6
|
Project-URL: Issues, https://github.com/bitwarden/workflow-linter/issues
|
@@ -66,6 +66,7 @@ enabled_rules:
|
|
66
66
|
- bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
|
67
67
|
- bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
|
68
68
|
- bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
|
69
|
+
- bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
|
69
70
|
|
70
71
|
approved_actions_path: default_actions.json
|
71
72
|
```
|
@@ -177,6 +178,9 @@ By default, a new Rule needs five things:
|
|
177
178
|
not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or
|
178
179
|
two empty lines between each job)
|
179
180
|
|
181
|
+
To activate a rule after implementing it, add it to `settings.yaml` in the project's base folder
|
182
|
+
and `src/bitwarden_workflow_linter/default_settings.yaml` to make the rule default
|
183
|
+
|
180
184
|
### ToDo
|
181
185
|
|
182
186
|
- [ ] Add Rule to assert correct format for single line run
|
@@ -40,6 +40,7 @@ enabled_rules:
|
|
40
40
|
- bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
|
41
41
|
- bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
|
42
42
|
- bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
|
43
|
+
- bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
|
43
44
|
|
44
45
|
approved_actions_path: default_actions.json
|
45
46
|
```
|
@@ -151,6 +152,9 @@ By default, a new Rule needs five things:
|
|
151
152
|
not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or
|
152
153
|
two empty lines between each job)
|
153
154
|
|
155
|
+
To activate a rule after implementing it, add it to `settings.yaml` in the project's base folder
|
156
|
+
and `src/bitwarden_workflow_linter/default_settings.yaml` to make the rule default
|
157
|
+
|
154
158
|
### ToDo
|
155
159
|
|
156
160
|
- [ ] Add Rule to assert correct format for single line run
|
@@ -10,8 +10,8 @@
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE.txt",
|
11
11
|
"devDependencies": {
|
12
12
|
"husky": "9.0.11",
|
13
|
-
"lint-staged": "15.2.
|
14
|
-
"prettier": "3.2
|
13
|
+
"lint-staged": "15.2.7",
|
14
|
+
"prettier": "3.3.2"
|
15
15
|
}
|
16
16
|
},
|
17
17
|
"node_modules/ansi-escapes": {
|
@@ -322,9 +322,9 @@
|
|
322
322
|
}
|
323
323
|
},
|
324
324
|
"node_modules/lint-staged": {
|
325
|
-
"version": "15.2.
|
326
|
-
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.
|
327
|
-
"integrity": "sha512
|
325
|
+
"version": "15.2.7",
|
326
|
+
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz",
|
327
|
+
"integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==",
|
328
328
|
"dev": true,
|
329
329
|
"license": "MIT",
|
330
330
|
"dependencies": {
|
@@ -543,9 +543,9 @@
|
|
543
543
|
}
|
544
544
|
},
|
545
545
|
"node_modules/prettier": {
|
546
|
-
"version": "3.2
|
547
|
-
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.
|
548
|
-
"integrity": "sha512-
|
546
|
+
"version": "3.3.2",
|
547
|
+
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
|
548
|
+
"integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
|
549
549
|
"dev": true,
|
550
550
|
"license": "MIT",
|
551
551
|
"bin": {
|
@@ -14,8 +14,8 @@
|
|
14
14
|
"homepage": "https://bitwarden.com",
|
15
15
|
"devDependencies": {
|
16
16
|
"husky": "9.0.11",
|
17
|
-
"lint-staged": "15.2.
|
18
|
-
"prettier": "3.2
|
17
|
+
"lint-staged": "15.2.7",
|
18
|
+
"prettier": "3.3.2"
|
19
19
|
},
|
20
20
|
"lint-staged": {
|
21
21
|
"!(*.py)": "prettier --cache --write --ignore-unknown",
|
@@ -4,5 +4,6 @@ enabled_rules:
|
|
4
4
|
- bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
|
5
5
|
- bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
|
6
6
|
- bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
|
7
|
+
- bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
|
7
8
|
|
8
9
|
approved_actions_path: default_actions.json
|
@@ -11,13 +11,11 @@ from typing import Optional, Union
|
|
11
11
|
|
12
12
|
from .utils import Colors, Settings, Action
|
13
13
|
|
14
|
-
|
15
14
|
class GitHubApiSchemaError(Exception):
|
16
15
|
"""A generic Exception to catch redefinitions of GitHub Api Schema changes."""
|
17
16
|
|
18
17
|
pass
|
19
18
|
|
20
|
-
|
21
19
|
class ActionsCmd:
|
22
20
|
"""Command to manage the pre-approved list of Actions
|
23
21
|
|
@@ -9,10 +9,8 @@ from .actions import ActionsCmd
|
|
9
9
|
from .lint import LinterCmd
|
10
10
|
from .utils import Settings
|
11
11
|
|
12
|
-
|
13
12
|
local_settings = Settings.factory()
|
14
13
|
|
15
|
-
|
16
14
|
def main(input_args: Optional[List[str]] = None) -> int:
|
17
15
|
"""CLI utility to lint GitHub Action Workflows.
|
18
16
|
|
@@ -50,6 +48,5 @@ def main(input_args: Optional[List[str]] = None) -> int:
|
|
50
48
|
|
51
49
|
return -1
|
52
50
|
|
53
|
-
|
54
51
|
if __name__ == "__main__":
|
55
52
|
sys.exit(main())
|
@@ -4,5 +4,6 @@ enabled_rules:
|
|
4
4
|
- bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
|
5
5
|
- bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
|
6
6
|
- bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
|
7
|
+
- bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
|
7
8
|
|
8
9
|
approved_actions_path: default_actions.json
|
@@ -13,16 +13,13 @@ from .models.workflow import Workflow
|
|
13
13
|
from .rule import Rule
|
14
14
|
from .utils import Settings
|
15
15
|
|
16
|
-
|
17
16
|
yaml = YAML()
|
18
17
|
|
19
|
-
|
20
18
|
class WorkflowBuilderError(Exception):
|
21
19
|
"""Exception to indicate an error with the WorkflowBuilder."""
|
22
20
|
|
23
21
|
pass
|
24
22
|
|
25
|
-
|
26
23
|
class WorkflowBuilder:
|
27
24
|
"""Collection of methods to build Workflow objects."""
|
28
25
|
|
@@ -85,13 +82,11 @@ class WorkflowBuilder:
|
|
85
82
|
"The workflow must either be built from a file or from a CommentedMap"
|
86
83
|
)
|
87
84
|
|
88
|
-
|
89
85
|
class LoadRulesError(Exception):
|
90
86
|
"""Exception to indicate an error with loading rules."""
|
91
87
|
|
92
88
|
pass
|
93
89
|
|
94
|
-
|
95
90
|
class Rules:
|
96
91
|
"""A collection of all of the types of rules.
|
97
92
|
|
@@ -30,6 +30,7 @@ class Job:
|
|
30
30
|
uses_with: Optional[CommentedMap] = field(
|
31
31
|
metadata=config(field_name="with"), default=None
|
32
32
|
)
|
33
|
+
outputs: Optional[CommentedMap] = None
|
33
34
|
|
34
35
|
@classmethod
|
35
36
|
def init(cls: Self, key: str, data: CommentedMap) -> Self:
|
@@ -39,6 +40,7 @@ class Job:
|
|
39
40
|
"name": data["name"] if "name" in data else None,
|
40
41
|
"runs-on": data["runs-on"] if "runs-on" in data else None,
|
41
42
|
"env": data["env"] if "env" in data else None,
|
43
|
+
"outputs": data["outputs"] if "outputs" in data else None,
|
42
44
|
}
|
43
45
|
|
44
46
|
new_job = cls.from_dict(init_data)
|
@@ -7,13 +7,11 @@ from .models.job import Job
|
|
7
7
|
from .models.step import Step
|
8
8
|
from .utils import LintFinding, LintLevels, Settings
|
9
9
|
|
10
|
-
|
11
10
|
class RuleExecutionException(Exception):
|
12
11
|
"""Exception for the Base Rule class."""
|
13
12
|
|
14
13
|
pass
|
15
14
|
|
16
|
-
|
17
15
|
class Rule:
|
18
16
|
"""Base class of a Rule to extend to create a linting Rule."""
|
19
17
|
|
@@ -0,0 +1,111 @@
|
|
1
|
+
import re
|
2
|
+
|
3
|
+
from typing import Optional, Union, Tuple
|
4
|
+
|
5
|
+
from ..models.job import Job
|
6
|
+
from ..rule import Rule
|
7
|
+
from ..models.workflow import Workflow
|
8
|
+
from ..models.step import Step
|
9
|
+
from ..utils import LintLevels, Settings
|
10
|
+
|
11
|
+
|
12
|
+
class RuleUnderscoreOutputs(Rule):
|
13
|
+
"""Rule to enforce all GitHub 'outputs' more than one words contain an underscore.
|
14
|
+
|
15
|
+
A simple standard to ensure uniformity in naming.
|
16
|
+
"""
|
17
|
+
|
18
|
+
def __init__(self, settings: Optional[Settings] = None) -> None:
|
19
|
+
"""Constructor for RuleUnderscoreOutputs to override the Rule class.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
settings:
|
23
|
+
A Settings object that contains any default, overridden, or custom settings
|
24
|
+
required anywhere in the application.
|
25
|
+
"""
|
26
|
+
self.message = "outputs with more than one word must use an underscore"
|
27
|
+
self.on_fail = LintLevels.WARNING
|
28
|
+
self.compatibility = [Workflow, Job, Step]
|
29
|
+
self.settings = settings
|
30
|
+
|
31
|
+
def fn(self, obj: Union[Workflow, Job, Step]) -> Tuple[bool, str]:
|
32
|
+
"""Enforces all outputs to have an underscore in the key name.
|
33
|
+
|
34
|
+
This Rule checks all outputs in a Workflow, Job, or Step to ensure that
|
35
|
+
the key name contains an underscore. This is to ensure that the naming
|
36
|
+
convention is consistent across all outputs in the workflow configuration
|
37
|
+
|
38
|
+
Example:
|
39
|
+
---
|
40
|
+
on:
|
41
|
+
workflow_dispatch:
|
42
|
+
outputs:
|
43
|
+
registry:
|
44
|
+
value: 'Test Value'
|
45
|
+
some_registry:
|
46
|
+
value: 'Test Value'
|
47
|
+
workflow_call:
|
48
|
+
outputs:
|
49
|
+
registry:
|
50
|
+
value: 'Test Value'
|
51
|
+
some_registry:
|
52
|
+
value: 'Test Value'
|
53
|
+
jobs:
|
54
|
+
job-key:
|
55
|
+
runs-on: ubuntu-22.04
|
56
|
+
outputs:
|
57
|
+
test_key_job: ${{ steps.test_output_1.outputs.test_key }}
|
58
|
+
steps:
|
59
|
+
- name: Test output in one-line run step
|
60
|
+
id: test_output_1
|
61
|
+
run: echo "test_key_1=Test-Value1" >> $GITHUB_OUTPUT
|
62
|
+
|
63
|
+
- name: Test output in multi-line run step
|
64
|
+
id: test_output_2
|
65
|
+
run: |
|
66
|
+
echo
|
67
|
+
fake-command=Test-Value2
|
68
|
+
echo "test_key_2=$REF" >> $GITHUB_OUTPUT
|
69
|
+
echo "deployed_ref=$DEPLOYED_REF" >> $GITHUB_OUTPUT
|
70
|
+
|
71
|
+
- name: Test step with no run
|
72
|
+
id: test_output_3
|
73
|
+
uses: actions/checkout@v2
|
74
|
+
with:
|
75
|
+
ref: ${{ github.ref }}
|
76
|
+
fetch-depth: 0
|
77
|
+
|
78
|
+
In this example, in workflow level 'registry' and 'some_registry' are outputs
|
79
|
+
that satisfy the rule in both 'workflow_dispatch' and 'workflow_call' events.
|
80
|
+
In job level 'test_key_job' satisfies the rule.
|
81
|
+
In step level 'test_key_1', 'test_key_2', and 'deployed_ref' satisfy the rule.
|
82
|
+
|
83
|
+
See tests/rules/test_underscore_outputs.py for incorrect examples.
|
84
|
+
"""
|
85
|
+
|
86
|
+
outputs = []
|
87
|
+
|
88
|
+
if isinstance(obj, Workflow):
|
89
|
+
if obj.on.get("workflow_dispatch"):
|
90
|
+
outputs.extend(obj.on["workflow_dispatch"]["outputs"].keys())
|
91
|
+
|
92
|
+
if obj.on.get("workflow_call"):
|
93
|
+
outputs.extend(obj.on["workflow_call"]["outputs"].keys())
|
94
|
+
|
95
|
+
if isinstance(obj, Job):
|
96
|
+
if obj.outputs:
|
97
|
+
outputs.extend(obj.outputs.keys())
|
98
|
+
|
99
|
+
if isinstance(obj, Step):
|
100
|
+
if obj.run:
|
101
|
+
outputs.extend(re.findall(
|
102
|
+
r"\b([a-zA-Z0-9_-]+)\s*=\s*[^=]*>>\s*\$GITHUB_OUTPUT",
|
103
|
+
obj.run))
|
104
|
+
|
105
|
+
for output_name in outputs:
|
106
|
+
if "-" in output_name:
|
107
|
+
return False, (
|
108
|
+
f"Hyphen found in {obj.__class__.__name__} output: {output_name}"
|
109
|
+
)
|
110
|
+
|
111
|
+
return True, ""
|
@@ -10,10 +10,8 @@ from typing import Optional, Self, TypeVar
|
|
10
10
|
|
11
11
|
from ruamel.yaml import YAML
|
12
12
|
|
13
|
-
|
14
13
|
yaml = YAML()
|
15
14
|
|
16
|
-
|
17
15
|
@dataclass
|
18
16
|
class Colors:
|
19
17
|
"""Class containing color codes for printing strings to output."""
|
@@ -27,7 +25,6 @@ class Colors:
|
|
27
25
|
cyan = "36m"
|
28
26
|
white = "37m"
|
29
27
|
|
30
|
-
|
31
28
|
@dataclass
|
32
29
|
class LintLevel:
|
33
30
|
"""Class to contain the numeric level and color of linting."""
|
@@ -35,7 +32,6 @@ class LintLevel:
|
|
35
32
|
code: int
|
36
33
|
color: Colors
|
37
34
|
|
38
|
-
|
39
35
|
class LintLevels(LintLevel, Enum):
|
40
36
|
"""Collection of the different types of LintLevels available."""
|
41
37
|
|
@@ -43,7 +39,6 @@ class LintLevels(LintLevel, Enum):
|
|
43
39
|
WARNING = 1, Colors.yellow
|
44
40
|
ERROR = 2, Colors.red
|
45
41
|
|
46
|
-
|
47
42
|
class LintFinding:
|
48
43
|
"""Represents a problem detected by linting."""
|
49
44
|
|
@@ -62,7 +57,6 @@ class LintFinding:
|
|
62
57
|
f"{self.description}"
|
63
58
|
)
|
64
59
|
|
65
|
-
|
66
60
|
@dataclass
|
67
61
|
class Action:
|
68
62
|
"""Collection of the metadata associated with a GitHub Action."""
|
@@ -99,16 +93,13 @@ class Action:
|
|
99
93
|
"""
|
100
94
|
return not self.__eq__(other)
|
101
95
|
|
102
|
-
|
103
96
|
class SettingsError(Exception):
|
104
97
|
"""Custom Exception to indicate an error with loading Settings."""
|
105
98
|
|
106
99
|
pass
|
107
100
|
|
108
|
-
|
109
101
|
SettingsFromFactory = TypeVar("SettingsFromFactory", bound="Settings")
|
110
102
|
|
111
|
-
|
112
103
|
class Settings:
|
113
104
|
"""Class that contains configuration-as-code for any portion of the app."""
|
114
105
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
---
|
2
|
+
name: Test Incorrect Workflow
|
3
|
+
on:
|
4
|
+
workflow_dispatch:
|
5
|
+
outputs:
|
6
|
+
registry-1:
|
7
|
+
value: 'Test Value'
|
8
|
+
some_registry-1:
|
9
|
+
value: 'Test Value'
|
10
|
+
workflow-call:
|
11
|
+
outputs:
|
12
|
+
registry-2:
|
13
|
+
value: 'Test Value'
|
14
|
+
push: {}
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
job-key:
|
18
|
+
name: Test Incorrect Job
|
19
|
+
runs-on: ubuntu-22.04
|
20
|
+
outputs:
|
21
|
+
test-key-1: ${{ steps.test_output_1.outputs.test_key }}
|
22
|
+
steps:
|
23
|
+
- name: Test output in one-line run step
|
24
|
+
id: test_output_1
|
25
|
+
run: echo "test-key-1=Test-Value1" >> $GITHUB_OUTPUT
|
26
|
+
|
27
|
+
- name: Test output in multi-line run step
|
28
|
+
id: test_output_2
|
29
|
+
run: |
|
30
|
+
echo
|
31
|
+
fake-command
|
32
|
+
echo "test-key-2=$REF" >> $GITHUB_OUTPUT
|
33
|
+
echo "deployed-ref=$DEPLOYED_REF" >> $GITHUB_OUTPUT
|
34
|
+
|
35
|
+
- name: Test step with one-line run and no Output
|
36
|
+
id: test_output_3
|
37
|
+
run: echo "test-key-3"
|
38
|
+
|
39
|
+
- name: Test step with multi-line run and no Output
|
40
|
+
id: test_output_4
|
41
|
+
run: |
|
42
|
+
echo
|
43
|
+
fake-command=Test-Value4
|
44
|
+
echo "test-key-4"
|
45
|
+
echo "deployed-ref"
|
@@ -0,0 +1,259 @@
|
|
1
|
+
"""Test src/bitwarden_workflow_linter/rules/underscore_outputs.py."""
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ruamel.yaml import YAML
|
6
|
+
|
7
|
+
from src.bitwarden_workflow_linter.load import WorkflowBuilder
|
8
|
+
from src.bitwarden_workflow_linter.rules.underscore_outputs import RuleUnderscoreOutputs
|
9
|
+
|
10
|
+
yaml = YAML()
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture(name="correct_workflow")
|
14
|
+
def fixture_correct_workflow():
|
15
|
+
workflow = """\
|
16
|
+
---
|
17
|
+
name: Test Correct Workflow
|
18
|
+
on:
|
19
|
+
workflow_dispatch:
|
20
|
+
outputs:
|
21
|
+
registry:
|
22
|
+
value: 'Test Value'
|
23
|
+
some_registry:
|
24
|
+
value: 'Test Value'
|
25
|
+
workflow_call:
|
26
|
+
outputs:
|
27
|
+
registry:
|
28
|
+
value: 'Test Value'
|
29
|
+
some_registry:
|
30
|
+
value: 'Test Value'
|
31
|
+
push: {}
|
32
|
+
|
33
|
+
jobs:
|
34
|
+
job-key:
|
35
|
+
name: Test Correct Job
|
36
|
+
runs-on: ubuntu-22.04
|
37
|
+
outputs:
|
38
|
+
test_key_job: ${{ steps.test_output_1.outputs.test_key }}
|
39
|
+
steps:
|
40
|
+
- name: Test output in one-line run step
|
41
|
+
id: test_output_1
|
42
|
+
run: echo "test_key_1=Test-Value1" >> $GITHUB_OUTPUT
|
43
|
+
|
44
|
+
- name: Test output in multi-line run step
|
45
|
+
id: test_output_2
|
46
|
+
run: |
|
47
|
+
echo
|
48
|
+
fake-command=Test-Value2
|
49
|
+
echo "test_key_2=$REF" >> $GITHUB_OUTPUT
|
50
|
+
echo "deployed_ref=$DEPLOYED_REF" >> $GITHUB_OUTPUT
|
51
|
+
|
52
|
+
- name: Test step with one-line run and no Output
|
53
|
+
id: test_output_3
|
54
|
+
run: echo "test_key_3"
|
55
|
+
|
56
|
+
- name: Test step with multi-line run and no Output
|
57
|
+
id: test_output_4
|
58
|
+
run: |
|
59
|
+
echo
|
60
|
+
fake-command=Test-Value4
|
61
|
+
echo "test_key_4"
|
62
|
+
echo "deployed_ref"
|
63
|
+
|
64
|
+
- name: Test step with no run
|
65
|
+
id: test_output_5
|
66
|
+
uses: actions/checkout@v2
|
67
|
+
with:
|
68
|
+
ref: ${{ github.ref }}
|
69
|
+
fetch-depth: 0
|
70
|
+
"""
|
71
|
+
return WorkflowBuilder.build(workflow=yaml.load(workflow), from_file=False)
|
72
|
+
|
73
|
+
|
74
|
+
@pytest.fixture(name="incorrect_workflow")
|
75
|
+
def fixture_incorrect_workflow():
|
76
|
+
workflow = """\
|
77
|
+
---
|
78
|
+
name: Test Incorrect Workflow
|
79
|
+
on:
|
80
|
+
workflow_dispatch:
|
81
|
+
outputs:
|
82
|
+
registry-1:
|
83
|
+
value: 'Test Value'
|
84
|
+
some_registry-1:
|
85
|
+
value: 'Test Value'
|
86
|
+
workflow_call:
|
87
|
+
outputs:
|
88
|
+
registry-2:
|
89
|
+
value: 'Test Value'
|
90
|
+
push: {}
|
91
|
+
|
92
|
+
jobs:
|
93
|
+
job-key:
|
94
|
+
name: Test Incorrect Job
|
95
|
+
runs-on: ubuntu-22.04
|
96
|
+
outputs:
|
97
|
+
test-key-1: ${{ steps.test_output_1.outputs.test_key }}
|
98
|
+
steps:
|
99
|
+
- name: Test output in one-line run step
|
100
|
+
id: test_output_1
|
101
|
+
run: echo "test-key-1=Test-Value1" >> $GITHUB_OUTPUT
|
102
|
+
|
103
|
+
- name: Test output in multi-line run step
|
104
|
+
id: test_output_2
|
105
|
+
run: |
|
106
|
+
echo
|
107
|
+
fake-command
|
108
|
+
echo "test-key-2=$REF" >> $GITHUB_OUTPUT
|
109
|
+
echo "deployed-ref=$DEPLOYED_REF" >> $GITHUB_OUTPUT
|
110
|
+
|
111
|
+
- name: Test step with one-line run and no Output
|
112
|
+
id: test_output_3
|
113
|
+
run: echo "test-key-3"
|
114
|
+
|
115
|
+
- name: Test step with multi-line run and no Output
|
116
|
+
id: test_output_4
|
117
|
+
run: |
|
118
|
+
echo
|
119
|
+
fake-command=Test-Value4
|
120
|
+
echo "test-key-4"
|
121
|
+
echo "deployed-ref"
|
122
|
+
"""
|
123
|
+
return WorkflowBuilder.build(workflow=yaml.load(workflow), from_file=False)
|
124
|
+
|
125
|
+
|
126
|
+
@pytest.fixture(name="push_only_workflow")
|
127
|
+
def fixture_push_only_workflow():
|
128
|
+
workflow = """\
|
129
|
+
---
|
130
|
+
name: Push Only
|
131
|
+
on:
|
132
|
+
push: {}
|
133
|
+
|
134
|
+
jobs:
|
135
|
+
job-key:
|
136
|
+
name: Test
|
137
|
+
runs-on: ubuntu-latest
|
138
|
+
steps:
|
139
|
+
- run: echo test
|
140
|
+
|
141
|
+
"""
|
142
|
+
return WorkflowBuilder.build(workflow=yaml.load(workflow), from_file=False)
|
143
|
+
|
144
|
+
@pytest.fixture(name="misc_workflow")
|
145
|
+
def fixture_misc_workflow():
|
146
|
+
workflow = """\
|
147
|
+
---
|
148
|
+
name: Misc Workflow
|
149
|
+
on:
|
150
|
+
push: {}
|
151
|
+
|
152
|
+
jobs:
|
153
|
+
job-key:
|
154
|
+
runs-on: ubuntu-22.04
|
155
|
+
steps:
|
156
|
+
- name: Test Step
|
157
|
+
run: |
|
158
|
+
echo "test_value=$does_it_break" >> /tmp/test
|
159
|
+
|
160
|
+
- name: Test Step 2
|
161
|
+
run: |
|
162
|
+
TEST_FILE=/tmp/test2
|
163
|
+
echo "test_value=$does_it_break" >> $TEST_FILE
|
164
|
+
"""
|
165
|
+
return WorkflowBuilder.build(workflow=yaml.load(workflow), from_file=False)
|
166
|
+
|
167
|
+
@pytest.fixture(name="no_output_workflow")
|
168
|
+
def fixture_no_output_workflow():
|
169
|
+
workflow = """\
|
170
|
+
---
|
171
|
+
name: No Output Workflow
|
172
|
+
on:
|
173
|
+
workflow_dispatch: {}
|
174
|
+
workflow_call: {}
|
175
|
+
|
176
|
+
jobs:
|
177
|
+
job-key:
|
178
|
+
name: Test
|
179
|
+
runs-on: ubuntu-latest
|
180
|
+
steps:
|
181
|
+
- run: echo test
|
182
|
+
"""
|
183
|
+
return WorkflowBuilder.build(workflow=yaml.load(workflow), from_file=False)
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
@pytest.fixture(name="rule")
|
188
|
+
def fixture_rule():
|
189
|
+
return RuleUnderscoreOutputs()
|
190
|
+
|
191
|
+
|
192
|
+
def test_rule_on_correct_workflow(rule, correct_workflow):
|
193
|
+
result, _ = rule.fn(correct_workflow)
|
194
|
+
assert result is True
|
195
|
+
|
196
|
+
|
197
|
+
def test_rule_on_incorrect_workflow(rule, incorrect_workflow):
|
198
|
+
result, _ = rule.fn(incorrect_workflow)
|
199
|
+
assert result is False
|
200
|
+
|
201
|
+
|
202
|
+
def test_rule_on_correct_job(rule, correct_workflow):
|
203
|
+
result, _ = rule.fn(correct_workflow.jobs["job-key"])
|
204
|
+
assert result is True
|
205
|
+
|
206
|
+
|
207
|
+
def test_rule_on_incorrect_job(rule, incorrect_workflow):
|
208
|
+
result, _ = rule.fn(incorrect_workflow.jobs["job-key"])
|
209
|
+
assert result is False
|
210
|
+
|
211
|
+
|
212
|
+
def test_rule_on_correct_step(rule, correct_workflow):
|
213
|
+
result, _ = rule.fn(correct_workflow.jobs["job-key"].steps[0])
|
214
|
+
assert result is True
|
215
|
+
|
216
|
+
result, _ = rule.fn(correct_workflow.jobs["job-key"].steps[1])
|
217
|
+
assert result is True
|
218
|
+
|
219
|
+
result, _ = rule.fn(correct_workflow.jobs["job-key"].steps[2])
|
220
|
+
assert result is True
|
221
|
+
|
222
|
+
result, _ = rule.fn(correct_workflow.jobs["job-key"].steps[3])
|
223
|
+
assert result is True
|
224
|
+
|
225
|
+
result, _ = rule.fn(correct_workflow.jobs["job-key"].steps[4])
|
226
|
+
assert result is True
|
227
|
+
|
228
|
+
|
229
|
+
def test_rule_on_incorrect_step(rule, incorrect_workflow):
|
230
|
+
result, _ = rule.fn(incorrect_workflow.jobs["job-key"].steps[0])
|
231
|
+
assert result is False
|
232
|
+
|
233
|
+
result, message = rule.fn(incorrect_workflow.jobs["job-key"].steps[1])
|
234
|
+
assert result is False
|
235
|
+
assert message == "Hyphen found in Step output: test-key-2"
|
236
|
+
|
237
|
+
result, _ = rule.fn(incorrect_workflow.jobs["job-key"].steps[2])
|
238
|
+
assert result is True
|
239
|
+
|
240
|
+
result, _ = rule.fn(incorrect_workflow.jobs["job-key"].steps[3])
|
241
|
+
assert result is True
|
242
|
+
|
243
|
+
|
244
|
+
def test_rule_on_push_only_workflow(rule, push_only_workflow):
|
245
|
+
result, _ = rule.fn(push_only_workflow)
|
246
|
+
assert result is True
|
247
|
+
|
248
|
+
|
249
|
+
def test_rule_on_misc_workflow(rule, misc_workflow):
|
250
|
+
result, _ = rule.fn(misc_workflow.jobs["job-key"].steps[0])
|
251
|
+
assert result is True
|
252
|
+
|
253
|
+
result, _ = rule.fn(misc_workflow.jobs["job-key"].steps[1])
|
254
|
+
assert result is True
|
255
|
+
|
256
|
+
|
257
|
+
def test_rule_on_no_output_workflow(rule, no_output_workflow):
|
258
|
+
result, _ = rule.fn(no_output_workflow)
|
259
|
+
assert result is True
|
@@ -1,60 +0,0 @@
|
|
1
|
-
---
|
2
|
-
name: _version_type
|
3
|
-
run-name: Get version type
|
4
|
-
|
5
|
-
on:
|
6
|
-
workflow_call:
|
7
|
-
outputs:
|
8
|
-
version_bump_type:
|
9
|
-
description: "version to be built"
|
10
|
-
value: ${{ jobs.version.outputs.bump_type }}
|
11
|
-
|
12
|
-
jobs:
|
13
|
-
version:
|
14
|
-
name: Calculate Version
|
15
|
-
runs-on: ubuntu-22.04
|
16
|
-
outputs:
|
17
|
-
bump_type: ${{ steps.bump-type.outputs.type }}
|
18
|
-
steps:
|
19
|
-
# - name: Get PR ID
|
20
|
-
# id: pr
|
21
|
-
# env:
|
22
|
-
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
23
|
-
# run: |
|
24
|
-
# commit_message=$(
|
25
|
-
# curl -s -L \
|
26
|
-
# -H "Accept: application/vnd.github+json" \
|
27
|
-
# -H "Authorization: Bearer $GH_TOKEN" \
|
28
|
-
# -H "X-GitHub-Api-Version: 2022-11-28" \
|
29
|
-
# https://api.github.com/repos/${{ github.repository }}/commits/${{ github.sha }} | \
|
30
|
-
# jq -r ".commit.message"
|
31
|
-
# )
|
32
|
-
# ID=$(echo "$commit_message" | head -1 | grep -o "(#.*)" | grep -o "[0-9]*")
|
33
|
-
# echo "id=$ID" >> $GITHUB_OUTPUT
|
34
|
-
|
35
|
-
- name: Get version bump type
|
36
|
-
id: bump-type
|
37
|
-
env:
|
38
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
39
|
-
PR_NUMBER: ${{ steps.pr.outputs.id }}
|
40
|
-
run: |
|
41
|
-
# version_tag=$(
|
42
|
-
# curl -s -L \
|
43
|
-
# -H "Accept: application/vnd.github+json" \
|
44
|
-
# -H "Authorization: Bearer $GH_TOKEN" \
|
45
|
-
# -H "X-GitHub-Api-Version: 2022-11-28" \
|
46
|
-
# https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels | \
|
47
|
-
# jq -r ".[].name" | grep "version"
|
48
|
-
# )
|
49
|
-
|
50
|
-
version_tag="version:patch"
|
51
|
-
|
52
|
-
# Single Version label Enforcement (should go in CI...)
|
53
|
-
if [[ $(echo $version_tag | wc -w) -gt 1 ]]; then
|
54
|
-
echo "[!] multiple version labels found!"
|
55
|
-
exit 1
|
56
|
-
fi
|
57
|
-
|
58
|
-
version_type=$(echo $version_tag | cut -d ":" -f 2)
|
59
|
-
echo "Version Bump Type: $version_type"
|
60
|
-
echo "type=$version_type" >> $GITHUB_OUTPUT
|
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/.github/PULL_REQUEST_TEMPLATE.md
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test-alt.yml
RENAMED
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test-min.yaml
RENAMED
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/fixtures/test_a.yaml
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_name_exists.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.0.3 → bitwarden_workflow_linter-0.0.4}/tests/rules/test_step_pinned.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|