1# This action looks at the commit history since the last release, and uses
2# this to decide which submodules require an update:
3on:
4  push:
5    branches:
6      - master
7name: release-please-submodule
8jobs:
9  # This logic looks at commits that have occurred since GitHub's magic
10  # latestRelease:
11  # https://developer.github.com/v3/repos/releases/#get-the-latest-release
12  # TODO: it would be better if we retrieved a list of all prior releases,
13  # and found the oldest release within the SUB_MODULES array. We need this
14  # logic for other libraries as well, and would like to pull this logic
15  # into its own action.
16  changeFinder:
17    runs-on: ubuntu-latest
18    outputs:
19      submodules: ${{ steps.interrogate.outputs.submodules }}
20    steps:
21      - uses: actions/checkout@v2
22      - id: interrogate
23        uses: actions/github-script@v3
24        with:
25            github-token: ${{secrets.GITHUB_TOKEN}}
26            script: |
27              const {execSync} = require('child_process');
28              const SUB_MODULES = [
29                'bigtable',
30                'bigquery',
31                'datastore',
32                'firestore',
33                'logging',
34                'pubsub',
35                'pubsublite',
36                'spanner',
37                'storage',
38              ];
39              const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
40              const latestRelease = await github.repos.getLatestRelease({
41                owner,
42                repo
43              });
44              console.info(`latest release: ${latestRelease.data.tag_name}`);
45              // pull all tags, so we can get diff between HEAD and last release:
46              execSync('git pull --tags');
47              execSync(`git reset --hard ${latestRelease.data.tag_name}`);
48              const status = execSync(`git diff --name-only origin/master`, { encoding: 'utf-8'});
49              console.info(status);
50              const changes = status.split('\n');
51              const submodules = new Set();
52              for (const change of changes) {
53                const library = change.split('/')[0];
54                console.info(`update to path ${library}`);
55                if (SUB_MODULES.includes(library)) {
56                  submodules.add(library);
57                }
58              }
59              console.log(`::set-output name=submodules::${JSON.stringify(Array.from(submodules))}`);
60  release-pr: # Create the release PR based on commit history:
61    runs-on: ubuntu-latest
62    needs: changeFinder
63    strategy:
64      fail-fast: false
65      matrix:
66        package: ${{fromJson(needs.changeFinder.outputs.submodules)}}
67    steps:
68      - uses: GoogleCloudPlatform/release-please-action@v2
69        id: release-please
70        with:
71           path: ${{ matrix.package }}
72           token: ${{ secrets.FORKING_TOKEN }}
73           fork: true
74           release-type: go
75           bump-minor-pre-major: true
76           package-name: ${{ matrix.package }}
77           monorepo-tags: true
78           command: release-pr
79      - uses: actions/github-script@v3
80        id: label # Adds the "autorelease: pending" label.
81        if: ${{steps.release-please.outputs.pr}}
82        with:
83            github-token: ${{secrets.GITHUB_TOKEN}}
84            script: |
85              const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
86              const latestRelease = await github.issues.addLabels({
87                owner,
88                repo,
89                issue_number: ${{steps.release-please.outputs.pr}},
90                labels: ['autorelease: pending']
91              });
92              console.log(`Tagged ${{steps.release-please.outputs.pr}}`)
93  release-please-release: # Actually create a release tag.
94    runs-on: ubuntu-latest
95    needs: changeFinder
96    strategy:
97      fail-fast: false
98      matrix:
99        package: ${{fromJson(needs.changeFinder.outputs.submodules)}}
100    steps:
101      - uses: GoogleCloudPlatform/release-please-action@v2
102        id: tag-release
103        with:
104          path: ${{ matrix.package }}
105          changelog-path: CHANGES.md
106          token: ${{ secrets.GITHUB_TOKEN }}
107          release-type: go
108          monorepo-tags: true
109          package-name: ${{ matrix.package }}
110          command: github-release
111      # Add the "autorelease: published" and remove tagged, this allows
112      # monitoring to be enabled that detects failed releases:
113      - uses: actions/github-script@v3
114        id: untag-release
115        if: ${{steps.tag-release.outputs.pr}}
116        with:
117          github-token: ${{secrets.GITHUB_TOKEN}}
118          script: |
119            const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
120            await github.issues.addLabels({
121              owner,
122              repo,
123              issue_number: ${{steps.tag-release.outputs.pr}},
124              labels: ['autorelease: published']
125            });
126            github.issues.removeLabel({
127              owner,
128              repo,
129              issue_number: ${{steps.tag-release.outputs.pr}},
130              name: 'autorelease: tagged',
131            });
132            console.log(`Tagged ${{steps.tag-release.outputs.pr}}`)
133