diff mbox series

[v2,1/1] ci: Add hook to mirror docparse to homepage

Message ID 20221209141002.15551-1-pvorel@suse.cz
State Changes Requested
Headers show
Series [v2,1/1] ci: Add hook to mirror docparse to homepage | expand

Commit Message

Petr Vorel Dec. 9, 2022, 2:10 p.m. UTC
GitHub Actions git push hook generates metadata HTML and push it
to LTP homepage.

Hook pushes only if there are actual changes in generated doc.

NOTE: this change requires to add:

1) Personal Access Token (PAT) to any developer which has write access
to homepage git repository [3]. In Developer settings -> Personal access
tokens -> Tokens (classic) [4]), where set:
Note: GH_PERSONAL_ACCESS_TOKEN
Select scopes: public_repo (minimal permission)
Expiration: either never or regularly renew.

2) Allow PAT in LTP organisation (I dared to already set it)
Iin linux-test-project group -> Settings -> Third-party Access -> Personal
access tokens -> Settings [5]
select:
Allow access via personal access tokens (classic)
API and Git access will be allowed using an organization member's personal access token (classic)

3) Add repository action secret to ltp repository
IN Settings -> Actions -> New repository secret [6]:
name: GH_PERSONAL_ACCESS_TOKEN
value: the value of previously created token.

Because using token, default permission is just read.

Reviewed-by: Aleks L <aleksandrosansan@gmail.com>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
Changes v1->v2:
* permission write => read (the real permission is done with token)
* remove unused env

Testing:
https://github.com/foo-pevik/ltp_foo/actions/runs/3656966820
https://github.com/foo-pevik/linux-test-project.github.com_foo/commit/785150ba13a9934d6ce7325abecd05e3643a00ed

No generation with irrelevant change:
https://github.com/foo-pevik/ltp_foo/actions/runs/3656968653

 .github/workflows/metadata-mirror.yml | 139 ++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)
 create mode 100644 .github/workflows/metadata-mirror.yml

Comments

Petr Vorel Dec. 9, 2022, 9:17 p.m. UTC | #1
Hi,

...
> +          printf "metadata.nightly.html: Update to $commit\n\nUpdate metadata.nightly.html to $commit_desc\n" > /tmp/msg
> +          git commit -F /tmp/msg .
> +
> +          echo "::notice::GH_PERSONAL_ACCESS_TOKEN: $GH_PERSONAL_ACCESS_TOKEN"
> +          git push https://${GH_PERSONAL_ACCESS_TOKEN}@github.com/linux-test-project/linux-test-project.github.com.git
I'll also add here:
echo "::notice::pushed $commit_desc"

So that it's obvious in github actions that commit was pushed.

Because github action does not allow to add exit code for "cancel"
- any non-zero exit code means failure:
https://docs.github.com/en/actions/creating-actions/setting-exit-codes-for-actions

"skip" due if: (e.g. if: ${{ github.repository == 'linux-test-project/ltp' }})
would allow it, but we have no way to exit like this.

Thus even nothing is pushed the result is always "green".

Kind regards,
Petr
Petr Vorel Dec. 12, 2022, 7:54 a.m. UTC | #2
Hi all,

after this is merged I'll add functionality to generate file for git tags.
(simple change, but I'd prefer to add it separately as it requires additional
testing).

Kind regards,
Petr
Richard Palethorpe Dec. 13, 2022, 9:59 a.m. UTC | #3
Hello,

Petr Vorel <pvorel@suse.cz> writes:

> GitHub Actions git push hook generates metadata HTML and push it
> to LTP homepage.
>
> Hook pushes only if there are actual changes in generated doc.

IIUC we have to do most of the work to generate the meta data, but then
don't push it if there is no diff?

What are we saving with this optimisation?

>
> NOTE: this change requires to add:
>
> 1) Personal Access Token (PAT) to any developer which has write access
> to homepage git repository [3]. In Developer settings -> Personal access
> tokens -> Tokens (classic) [4]), where set:
> Note: GH_PERSONAL_ACCESS_TOKEN
> Select scopes: public_repo (minimal permission)
> Expiration: either never or regularly renew.
>
> 2) Allow PAT in LTP organisation (I dared to already set it)
> Iin linux-test-project group -> Settings -> Third-party Access -> Personal
> access tokens -> Settings [5]
> select:
> Allow access via personal access tokens (classic)
> API and Git access will be allowed using an organization member's personal access token (classic)
>
> 3) Add repository action secret to ltp repository
> IN Settings -> Actions -> New repository secret [6]:
> name: GH_PERSONAL_ACCESS_TOKEN
> value: the value of previously created token.
>
> Because using token, default permission is just read.

This seems like a very convoluted process. Can't we just put the
metadata generation in the docs build and upload the assets as usual?
I've never had to use a PAT to deploy a github page.

>
> Reviewed-by: Aleks L <aleksandrosansan@gmail.com>
> Signed-off-by: Petr Vorel <pvorel@suse.cz>
> ---
> Changes v1->v2:
> * permission write => read (the real permission is done with token)
> * remove unused env
>
> Testing:
> https://github.com/foo-pevik/ltp_foo/actions/runs/3656966820
> https://github.com/foo-pevik/linux-test-project.github.com_foo/commit/785150ba13a9934d6ce7325abecd05e3643a00ed
>
> No generation with irrelevant change:
> https://github.com/foo-pevik/ltp_foo/actions/runs/3656968653
>
>  .github/workflows/metadata-mirror.yml | 139 ++++++++++++++++++++++++++
>  1 file changed, 139 insertions(+)
>  create mode 100644 .github/workflows/metadata-mirror.yml
>
> diff --git a/.github/workflows/metadata-mirror.yml b/.github/workflows/metadata-mirror.yml
> new file mode 100644
> index 000000000..296b3286c
> --- /dev/null
> +++ b/.github/workflows/metadata-mirror.yml
> @@ -0,0 +1,139 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2022 Petr Vorel <pvorel@suse.cz>
> +
> +name: "Mirror metadata doc to homepage"
> +
> +on:
> +  push:
> +    branches:
> +      - master
> +
> +permissions: {}
> +jobs:
> +  metadata-mirror:
> +    permissions:
> +      contents: read
> +
> +    runs-on: ubuntu-latest
> +    if: ${{ github.repository == 'linux-test-project/ltp' }}
> +    steps:
> +      - name: Check secret
> +        env:
> +          GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
> +        run: |
> +          if [ -z "$GH_PERSONAL_ACCESS_TOKEN" ]; then
> +            echo "::error::GH_PERSONAL_ACCESS_TOKEN environment variable is not set"
> +            exit 1
> +          fi

Do we not trust Github to set an env variable?

> +
> +      - name: Checkout LTP
> +        uses: actions/checkout@v3
> +        with:
> +          path: ltp
> +          # we need to fetch whole history to get 'git describe' working for correct version in docs
> +          fetch-depth: 0
> +
> +      - name: Checkout LTP homepage
> +        uses: actions/checkout@v3
> +        with:
> +          repository: "linux-test-project/linux-test-project.github.com"
> +          path: linux-test-project.github.com
> +          persist-credentials: false
> +
> +      - name: Check metadata need to be updated
> +        run: |
> +          cd "$GITHUB_WORKSPACE/ltp/testcases/"
> +
> +          # check for changes
> +          cd "$GITHUB_WORKSPACE/linux-test-project.github.com"
> +          git grep '<p><strong>Version</strong>:' metadata/metadata.nightly.html
> +          sed -ne 's/.*<p><strong>Version<\/strong>: \(.*\)<\/p>/\1/p' metadata/metadata.nightly.html
> +          old_commit=$(sed -ne 's/.*<p><strong>Version<\/strong>: \(.*\)<\/p>/\1/p' metadata/metadata.nightly.html)
> +          old_commit=$(echo "$old_commit" | sed 's/.*-g\(.*\)/\1/')
> +          echo "::notice::old commit in linux-test-project.github.com: '$old_commit'"
> +
> +          echo "git log $old_commit..HEAD testcases/ | wc -l"
> +          git log $old_commit..HEAD testcases/ | wc -l
> +
> +          echo "git log $old_commit..HEAD testcases/ 2>&1 | wc -l"
> +          git log $old_commit..HEAD testcases/ 2>&1 | wc -l
> +
> +          if [ "$(git log $old_commit..HEAD testcases/ 2>&1 | wc -l)" = 0 ]; then
> +            echo "::notice::no file changes in testcases/ directory since '$old_commit' => exit without commit and push"
> +            exit 0
> +          fi
> +
> +      - name: Install dependencies
> +        run: |
> +          apt="apt install -y --no-install-recommends"
> +          sudo $apt asciidoctor autoconf automake libjson-perl libwww-perl make
> +
> +          echo "which asciidoctor"
> +          which asciidoctor || { echo "::error::missing asciidoctor"; exit 1; }
> +
> +      - name: Configure LTP
> +        run: |
> +          cd "$GITHUB_WORKSPACE/ltp/"
> +          make autotools && ./configure --with-metadata-generator=asciidoctor && make Version || { echo "::error::LTP configure failed"; exit 1; }
> +
> +      - name: Generate html metadata doc
> +        run: |
> +          cd "$GITHUB_WORKSPACE/ltp/metadata/"
> +          echo "going to generate metadata"
> +          make -j$(nproc)
> +
> +      - name: Check possible LTP homepage update
> +        run: |
> +          cd "$GITHUB_WORKSPACE/ltp/"
> +          ltp_commit=$(git log --pretty=format:"%h" -1 .)
> +          echo "::notice::Search for $ltp_commit in metadata/metadata.nightly.html"
> +
> +          cd "$GITHUB_WORKSPACE/linux-test-project.github.com"
> +          grep "<p><strong>Version</strong>:" metadata/metadata.nightly.html
> +          git pull
> +          grep "<p><strong>Version</strong>:" metadata/metadata.nightly.html
> +          if grep "<p><strong>Version</strong>: .*${ltp_commit}.*</p>" metadata/metadata.nightly.html; then
> +            echo "::notice::$ltp_commit already in metadata/metadata.nightly.html => exit without commit and push"
> +            exit 0
> +          fi
> +
> +      - name: Push generated html metadata to LTP homepage
> +        env:
> +          GH_PERSONAL_ACCESS_TOKEN: ${{
> secrets.GH_PERSONAL_ACCESS_TOKEN }}

Why put a credential in an env variable anyway? Can we not simply write
${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} below?

> +        run: |
> +          git config --global user.email "actions@github.com"
> +          git config --global user.name "Metadata doc mirror"
> +
> +          cd "$GITHUB_WORKSPACE/ltp/"
> +          commit=$(git log --pretty=format:"%h" -1 .)
> +          commit_desc=$(git log --pretty=format:"%h (\"%s\")" -1 .)
> +          echo "commit_desc: '$commit_desc'"
> +
> +          cd "$GITHUB_WORKSPACE/linux-test-project.github.com"
> +
> +          # pull in case previous hook pushed later than checkout here had started
> +          git pull
> +
> +          cp -v "$GITHUB_WORKSPACE/ltp/docparse/metadata.html" metadata/metadata.nightly.html
> +
> +          # skip if there is only different version and time
> +          echo "Check for changes"
> +          if ! git diff --unified=0 --no-color | grep -Po '(?<=^\+)(?!\+\+).*' | grep -v -e '^<p><strong>Version</strong>:' -e '^Last updated'; then
> +            echo "::notice::No changes in metadata/metadata.nightly.html => exit without commit and push"
> +            exit 0
> +          fi
> +
> +          git add .
> +
> +          # only commit if there are changes
> +          if git pdiff-index --quiet HEAD --; then
> +            echo "::notice::No files changed in $GITHUB_WORKSPACE/linux-test-project.github.com => exit without commit and push"
> +            git status
> +            exit 0
> +          fi
> +
> +          printf "metadata.nightly.html: Update to $commit\n\nUpdate metadata.nightly.html to $commit_desc\n" > /tmp/msg
> +          git commit -F /tmp/msg .
> +
> +          echo "::notice::GH_PERSONAL_ACCESS_TOKEN: $GH_PERSONAL_ACCESS_TOKEN"

Won't this print your PAT for the world to use?

> +          git push
> https://${GH_PERSONAL_ACCESS_TOKEN}@github.com/linux-test-project/linux-test-project.github.com.git
Petr Vorel Dec. 13, 2022, 7:18 p.m. UTC | #4
Hi Richie,

first, thank you for your review!

> Hello,

> Petr Vorel <pvorel@suse.cz> writes:

> > GitHub Actions git push hook generates metadata HTML and push it
> > to LTP homepage.

> > Hook pushes only if there are actual changes in generated doc.

> IIUC we have to do most of the work to generate the meta data, but then
> don't push it if there is no diff?

> What are we saving with this optimisation?

This saves number of commits which will change nothing.
Because the page itself has also other changes for the web page itself,
which will be buried with these changes.
But sure, I'll remove this check, if considered useless.

If your comment is about to do the detection earlier,
I'd have to do some smart 'git diff'. Could be done with:
git diff $old_commit testcases/ | grep '^+ \* '
in step "Check metadata need to be updated"
(i.e. after both checkouts).


> > NOTE: this change requires to add:

> > 1) Personal Access Token (PAT) to any developer which has write access
> > to homepage git repository [3]. In Developer settings -> Personal access
> > tokens -> Tokens (classic) [4]), where set:
> > Note: GH_PERSONAL_ACCESS_TOKEN
> > Select scopes: public_repo (minimal permission)
> > Expiration: either never or regularly renew.

> > 2) Allow PAT in LTP organisation (I dared to already set it)
> > Iin linux-test-project group -> Settings -> Third-party Access -> Personal
> > access tokens -> Settings [5]
> > select:
> > Allow access via personal access tokens (classic)
> > API and Git access will be allowed using an organization member's personal access token (classic)

> > 3) Add repository action secret to ltp repository
> > IN Settings -> Actions -> New repository secret [6]:
> > name: GH_PERSONAL_ACCESS_TOKEN
> > value: the value of previously created token.

> > Because using token, default permission is just read.

> This seems like a very convoluted process. Can't we just put the
> metadata generation in the docs build and upload the assets as usual?
> I've never had to use a PAT to deploy a github page.

Do you mean to have this Action in linux-test-project.github.com git repo?
What would trigger the build? Some kind of cron behavior?
Using PAT is a weak point thus I'm really open to other solutions.

...
> > +++ b/.github/workflows/metadata-mirror.yml
...
> > +    steps:
> > +      - name: Check secret
> > +        env:
> > +          GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
> > +        run: |
> > +          if [ -z "$GH_PERSONAL_ACCESS_TOKEN" ]; then
> > +            echo "::error::GH_PERSONAL_ACCESS_TOKEN environment variable is not set"
> > +            exit 1
> > +          fi

> Do we not trust Github to set an env variable?
If I delete my PAT, this will catch it. Of course error message could be
improved.

...
> > +      - name: Push generated html metadata to LTP homepage
> > +        env:
> > +          GH_PERSONAL_ACCESS_TOKEN: ${{
> > secrets.GH_PERSONAL_ACCESS_TOKEN }}

> Why put a credential in an env variable anyway? Can we not simply write
> ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} below?
I can test if it's supported inside "run:", but github hides env content,
thus no big deal to use env. See:
https://github.com/foo-pevik/ltp_foo/actions/runs/3660784474
GH_PERSONAL_ACCESS_TOKEN: ***

https://github.com/foo-pevik/ltp_foo/actions/runs/3660784474/jobs/6188315802
GH_PERSONAL_ACCESS_TOKEN: ***

(Hidden on all places.)

> > +        run: |
...
> > +          printf "metadata.nightly.html: Update to $commit\n\nUpdate metadata.nightly.html to $commit_desc\n" > /tmp/msg
> > +          git commit -F /tmp/msg .
> > +
> > +          echo "::notice::GH_PERSONAL_ACCESS_TOKEN: $GH_PERSONAL_ACCESS_TOKEN"

> Won't this print your PAT for the world to use?
No (described above, see the links of actual run).
> > +          git push
> > https://${GH_PERSONAL_ACCESS_TOKEN}@github.com/linux-test-project/linux-test-project.github.com.git

Kind regards,
Petr
Richard Palethorpe Dec. 15, 2022, 8:45 a.m. UTC | #5
Hello,

Petr Vorel <pvorel@suse.cz> writes:

> Hi Richie,
>
> first, thank you for your review!
>
>> Hello,
>
>> Petr Vorel <pvorel@suse.cz> writes:
>
>> > GitHub Actions git push hook generates metadata HTML and push it
>> > to LTP homepage.
>
>> > Hook pushes only if there are actual changes in generated doc.
>
>> IIUC we have to do most of the work to generate the meta data, but then
>> don't push it if there is no diff?
>
>> What are we saving with this optimisation?
>
> This saves number of commits which will change nothing.
> Because the page itself has also other changes for the web page itself,
> which will be buried with these changes.
> But sure, I'll remove this check, if considered useless.

I think the root of the problem is that we are publishing to a branch
which makes sense if we write the HTML by hand.

However we are generating it from multiples sources. So this doesn't
work well with Git.

Why not use the upload assets method?:

https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#creating-a-custom-github-actions-workflow-to-publish-your-site

>
> If your comment is about to do the detection earlier,
> I'd have to do some smart 'git diff'. Could be done with:
> git diff $old_commit testcases/ | grep '^+ \* '
> in step "Check metadata need to be updated"
> (i.e. after both checkouts).
>
>
>> > NOTE: this change requires to add:
>
>> > 1) Personal Access Token (PAT) to any developer which has write access
>> > to homepage git repository [3]. In Developer settings -> Personal access
>> > tokens -> Tokens (classic) [4]), where set:
>> > Note: GH_PERSONAL_ACCESS_TOKEN
>> > Select scopes: public_repo (minimal permission)
>> > Expiration: either never or regularly renew.
>
>> > 2) Allow PAT in LTP organisation (I dared to already set it)
>> > Iin linux-test-project group -> Settings -> Third-party Access -> Personal
>> > access tokens -> Settings [5]
>> > select:
>> > Allow access via personal access tokens (classic)
>> > API and Git access will be allowed using an organization member's personal access token (classic)
>
>> > 3) Add repository action secret to ltp repository
>> > IN Settings -> Actions -> New repository secret [6]:
>> > name: GH_PERSONAL_ACCESS_TOKEN
>> > value: the value of previously created token.
>
>> > Because using token, default permission is just read.
>
>> This seems like a very convoluted process. Can't we just put the
>> metadata generation in the docs build and upload the assets as usual?
>> I've never had to use a PAT to deploy a github page.
>
> Do you mean to have this Action in linux-test-project.github.com git repo?
> What would trigger the build? Some kind of cron behavior?
> Using PAT is a weak point thus I'm really open to other solutions.

I guess a github action can be triggered by multiple sources, including
other actions and the assets from one action should be available in the
next.

I'm more familiar with GitLab, but this is basic build pipeline stuff,
so GitHub should support it.
Petr Vorel March 23, 2023, 7:30 a.m. UTC | #6
Hi Richie, Cyril,

> Hello,

> Petr Vorel <pvorel@suse.cz> writes:

> > Hi Richie,

> > first, thank you for your review!

> >> Hello,

> >> Petr Vorel <pvorel@suse.cz> writes:

> >> > GitHub Actions git push hook generates metadata HTML and push it
> >> > to LTP homepage.

> >> > Hook pushes only if there are actual changes in generated doc.

> >> IIUC we have to do most of the work to generate the meta data, but then
> >> don't push it if there is no diff?

> >> What are we saving with this optimisation?

> > This saves number of commits which will change nothing.
> > Because the page itself has also other changes for the web page itself,
> > which will be buried with these changes.
> > But sure, I'll remove this check, if considered useless.

> I think the root of the problem is that we are publishing to a branch
> which makes sense if we write the HTML by hand.

> However we are generating it from multiples sources. So this doesn't
> work well with Git.

> Why not use the upload assets method?:

> https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#creating-a-custom-github-actions-workflow-to-publish-your-site

Thanks for a hint, actions/checkout [1] looks useful.

@Cyril We currently have github pages uploaded within separate repository [2],
we'd need to convert it to Publishing with a custom GitHub Actions workflow [3].
That would include to migrate the necessary content (index.html and assets
directory) to ltp repository (put into new web directory) and create new GitHub
Actions workflow (examples [4] [5]).

This would help that 1) we'd not need Personal Access Token (everything is in
single repository) 2) only a real sources would be stored in git, not generated
files. It's not a high priority for me, but I'm willing to implement everything,
if I got ack from you.

> > If your comment is about to do the detection earlier,
> > I'd have to do some smart 'git diff'. Could be done with:
> > git diff $old_commit testcases/ | grep '^+ \* '
> > in step "Check metadata need to be updated"
> > (i.e. after both checkouts).


> >> > NOTE: this change requires to add:

> >> > 1) Personal Access Token (PAT) to any developer which has write access
> >> > to homepage git repository [3]. In Developer settings -> Personal access
> >> > tokens -> Tokens (classic) [4]), where set:
> >> > Note: GH_PERSONAL_ACCESS_TOKEN
> >> > Select scopes: public_repo (minimal permission)
> >> > Expiration: either never or regularly renew.

> >> > 2) Allow PAT in LTP organisation (I dared to already set it)
> >> > Iin linux-test-project group -> Settings -> Third-party Access -> Personal
> >> > access tokens -> Settings [5]
> >> > select:
> >> > Allow access via personal access tokens (classic)
> >> > API and Git access will be allowed using an organization member's personal access token (classic)

> >> > 3) Add repository action secret to ltp repository
> >> > IN Settings -> Actions -> New repository secret [6]:
> >> > name: GH_PERSONAL_ACCESS_TOKEN
> >> > value: the value of previously created token.

> >> > Because using token, default permission is just read.

> >> This seems like a very convoluted process. Can't we just put the
> >> metadata generation in the docs build and upload the assets as usual?
> >> I've never had to use a PAT to deploy a github page.

> > Do you mean to have this Action in linux-test-project.github.com git repo?
> > What would trigger the build? Some kind of cron behavior?
> > Using PAT is a weak point thus I'm really open to other solutions.

> I guess a github action can be triggered by multiple sources, including
> other actions and the assets from one action should be available in the
> next.

> I'm more familiar with GitLab, but this is basic build pipeline stuff,
> so GitHub should support it.

FYI I find hint to use workflow_dispatch [6], but doc states [7] that for
triggering a workflow from a workflow (our case) secrets.GITHUB_TOKEN (IMHO
within repository) cannot be used. Instead, personal access token must be set
(in one of the developers account), store it in your repo or orgs secrets and
reference that instead. i.e. the same approach I already implemented.  Maybe
this reversed approach would be cleaner, but as they both require PATH, from the
security point they are the same.

=> Using actions/checkout is better solution for us anyway. But it's good to
know, that any actions between repos requires Personal access token (fortunately
we will never need to some triggering between subprojects). I'm not sure gitlab
would be easier on this, but we're not going to migrate to gitlab anyway.

Kind regards,
Petr

[1] https://github.com/actions/upload-pages-artifact
[2] https://github.com/linux-test-project/linux-test-project.github.com
[3] https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow
[4] https://github.com/jendrikseipp/rednotebook/blob/master/.github/workflows/web.yml
[5] https://github.com/conda/conda-package-streaming/blob/main/.github/workflows/sphinx.yml
[6] https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
[7] https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
diff mbox series

Patch

diff --git a/.github/workflows/metadata-mirror.yml b/.github/workflows/metadata-mirror.yml
new file mode 100644
index 000000000..296b3286c
--- /dev/null
+++ b/.github/workflows/metadata-mirror.yml
@@ -0,0 +1,139 @@ 
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2022 Petr Vorel <pvorel@suse.cz>
+
+name: "Mirror metadata doc to homepage"
+
+on:
+  push:
+    branches:
+      - master
+
+permissions: {}
+jobs:
+  metadata-mirror:
+    permissions:
+      contents: read
+
+    runs-on: ubuntu-latest
+    if: ${{ github.repository == 'linux-test-project/ltp' }}
+    steps:
+      - name: Check secret
+        env:
+          GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
+        run: |
+          if [ -z "$GH_PERSONAL_ACCESS_TOKEN" ]; then
+            echo "::error::GH_PERSONAL_ACCESS_TOKEN environment variable is not set"
+            exit 1
+          fi
+
+      - name: Checkout LTP
+        uses: actions/checkout@v3
+        with:
+          path: ltp
+          # we need to fetch whole history to get 'git describe' working for correct version in docs
+          fetch-depth: 0
+
+      - name: Checkout LTP homepage
+        uses: actions/checkout@v3
+        with:
+          repository: "linux-test-project/linux-test-project.github.com"
+          path: linux-test-project.github.com
+          persist-credentials: false
+
+      - name: Check metadata need to be updated
+        run: |
+          cd "$GITHUB_WORKSPACE/ltp/testcases/"
+
+          # check for changes
+          cd "$GITHUB_WORKSPACE/linux-test-project.github.com"
+          git grep '<p><strong>Version</strong>:' metadata/metadata.nightly.html
+          sed -ne 's/.*<p><strong>Version<\/strong>: \(.*\)<\/p>/\1/p' metadata/metadata.nightly.html
+          old_commit=$(sed -ne 's/.*<p><strong>Version<\/strong>: \(.*\)<\/p>/\1/p' metadata/metadata.nightly.html)
+          old_commit=$(echo "$old_commit" | sed 's/.*-g\(.*\)/\1/')
+          echo "::notice::old commit in linux-test-project.github.com: '$old_commit'"
+
+          echo "git log $old_commit..HEAD testcases/ | wc -l"
+          git log $old_commit..HEAD testcases/ | wc -l
+
+          echo "git log $old_commit..HEAD testcases/ 2>&1 | wc -l"
+          git log $old_commit..HEAD testcases/ 2>&1 | wc -l
+
+          if [ "$(git log $old_commit..HEAD testcases/ 2>&1 | wc -l)" = 0 ]; then
+            echo "::notice::no file changes in testcases/ directory since '$old_commit' => exit without commit and push"
+            exit 0
+          fi
+
+      - name: Install dependencies
+        run: |
+          apt="apt install -y --no-install-recommends"
+          sudo $apt asciidoctor autoconf automake libjson-perl libwww-perl make
+
+          echo "which asciidoctor"
+          which asciidoctor || { echo "::error::missing asciidoctor"; exit 1; }
+
+      - name: Configure LTP
+        run: |
+          cd "$GITHUB_WORKSPACE/ltp/"
+          make autotools && ./configure --with-metadata-generator=asciidoctor && make Version || { echo "::error::LTP configure failed"; exit 1; }
+
+      - name: Generate html metadata doc
+        run: |
+          cd "$GITHUB_WORKSPACE/ltp/metadata/"
+          echo "going to generate metadata"
+          make -j$(nproc)
+
+      - name: Check possible LTP homepage update
+        run: |
+          cd "$GITHUB_WORKSPACE/ltp/"
+          ltp_commit=$(git log --pretty=format:"%h" -1 .)
+          echo "::notice::Search for $ltp_commit in metadata/metadata.nightly.html"
+
+          cd "$GITHUB_WORKSPACE/linux-test-project.github.com"
+          grep "<p><strong>Version</strong>:" metadata/metadata.nightly.html
+          git pull
+          grep "<p><strong>Version</strong>:" metadata/metadata.nightly.html
+          if grep "<p><strong>Version</strong>: .*${ltp_commit}.*</p>" metadata/metadata.nightly.html; then
+            echo "::notice::$ltp_commit already in metadata/metadata.nightly.html => exit without commit and push"
+            exit 0
+          fi
+
+      - name: Push generated html metadata to LTP homepage
+        env:
+          GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
+        run: |
+          git config --global user.email "actions@github.com"
+          git config --global user.name "Metadata doc mirror"
+
+          cd "$GITHUB_WORKSPACE/ltp/"
+          commit=$(git log --pretty=format:"%h" -1 .)
+          commit_desc=$(git log --pretty=format:"%h (\"%s\")" -1 .)
+          echo "commit_desc: '$commit_desc'"
+
+          cd "$GITHUB_WORKSPACE/linux-test-project.github.com"
+
+          # pull in case previous hook pushed later than checkout here had started
+          git pull
+
+          cp -v "$GITHUB_WORKSPACE/ltp/docparse/metadata.html" metadata/metadata.nightly.html
+
+          # skip if there is only different version and time
+          echo "Check for changes"
+          if ! git diff --unified=0 --no-color | grep -Po '(?<=^\+)(?!\+\+).*' | grep -v -e '^<p><strong>Version</strong>:' -e '^Last updated'; then
+            echo "::notice::No changes in metadata/metadata.nightly.html => exit without commit and push"
+            exit 0
+          fi
+
+          git add .
+
+          # only commit if there are changes
+          if git diff-index --quiet HEAD --; then
+            echo "::notice::No files changed in $GITHUB_WORKSPACE/linux-test-project.github.com => exit without commit and push"
+            git status
+            exit 0
+          fi
+
+          printf "metadata.nightly.html: Update to $commit\n\nUpdate metadata.nightly.html to $commit_desc\n" > /tmp/msg
+          git commit -F /tmp/msg .
+
+          echo "::notice::GH_PERSONAL_ACCESS_TOKEN: $GH_PERSONAL_ACCESS_TOKEN"
+          git push https://${GH_PERSONAL_ACCESS_TOKEN}@github.com/linux-test-project/linux-test-project.github.com.git