mirror of
https://github.com/actions/setup-java.git
synced 2026-08-05 12:59:28 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 08bc85dc59 |
@@ -12,6 +12,9 @@ updates:
|
||||
# Check the npm registry for updates every day (weekdays)
|
||||
schedule:
|
||||
interval: 'weekly'
|
||||
ignore:
|
||||
- dependency-name: 'typescript'
|
||||
update-types: ['version-update:semver-major']
|
||||
|
||||
# Enable version updates for GitHub Actions
|
||||
- package-ecosystem: 'github-actions'
|
||||
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: "@oozcitak/dom"
|
||||
version: 2.0.2
|
||||
type: npm
|
||||
summary: A modern DOM implementation
|
||||
homepage: http://github.com/oozcitak/dom
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Ozgur Ozcitak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: "@oozcitak/infra"
|
||||
version: 2.0.2
|
||||
type: npm
|
||||
summary: An implementation of the Infra Living Standard
|
||||
homepage: http://github.com/oozcitak/infra
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Ozgur Ozcitak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: "@oozcitak/url"
|
||||
version: 3.0.0
|
||||
type: npm
|
||||
summary: An implementation of the URL Living Standard
|
||||
homepage: http://github.com/oozcitak/url
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Ozgur Ozcitak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: "@oozcitak/util"
|
||||
version: 10.0.0
|
||||
type: npm
|
||||
summary: Utility functions
|
||||
homepage: http://github.com/oozcitak/util
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Ozgur Ozcitak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
||||
Generated
+265
@@ -0,0 +1,265 @@
|
||||
---
|
||||
name: argparse
|
||||
version: 2.0.1
|
||||
type: npm
|
||||
summary: CLI arguments parser. Native port of python's argparse.
|
||||
homepage:
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
A. HISTORY OF THE SOFTWARE
|
||||
==========================
|
||||
|
||||
Python was created in the early 1990s by Guido van Rossum at Stichting
|
||||
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
|
||||
as a successor of a language called ABC. Guido remains Python's
|
||||
principal author, although it includes many contributions from others.
|
||||
|
||||
In 1995, Guido continued his work on Python at the Corporation for
|
||||
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
|
||||
in Reston, Virginia where he released several versions of the
|
||||
software.
|
||||
|
||||
In May 2000, Guido and the Python core development team moved to
|
||||
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
|
||||
year, the PythonLabs team moved to Digital Creations, which became
|
||||
Zope Corporation. In 2001, the Python Software Foundation (PSF, see
|
||||
https://www.python.org/psf/) was formed, a non-profit organization
|
||||
created specifically to own Python-related Intellectual Property.
|
||||
Zope Corporation was a sponsoring member of the PSF.
|
||||
|
||||
All Python releases are Open Source (see http://www.opensource.org for
|
||||
the Open Source Definition). Historically, most, but not all, Python
|
||||
releases have also been GPL-compatible; the table below summarizes
|
||||
the various releases.
|
||||
|
||||
Release Derived Year Owner GPL-
|
||||
from compatible? (1)
|
||||
|
||||
0.9.0 thru 1.2 1991-1995 CWI yes
|
||||
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
|
||||
1.6 1.5.2 2000 CNRI no
|
||||
2.0 1.6 2000 BeOpen.com no
|
||||
1.6.1 1.6 2001 CNRI yes (2)
|
||||
2.1 2.0+1.6.1 2001 PSF no
|
||||
2.0.1 2.0+1.6.1 2001 PSF yes
|
||||
2.1.1 2.1+2.0.1 2001 PSF yes
|
||||
2.1.2 2.1.1 2002 PSF yes
|
||||
2.1.3 2.1.2 2002 PSF yes
|
||||
2.2 and above 2.1.1 2001-now PSF yes
|
||||
|
||||
Footnotes:
|
||||
|
||||
(1) GPL-compatible doesn't mean that we're distributing Python under
|
||||
the GPL. All Python licenses, unlike the GPL, let you distribute
|
||||
a modified version without making your changes open source. The
|
||||
GPL-compatible licenses make it possible to combine Python with
|
||||
other software that is released under the GPL; the others don't.
|
||||
|
||||
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
|
||||
because its license has a choice of law clause. According to
|
||||
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
|
||||
is "not incompatible" with the GPL.
|
||||
|
||||
Thanks to the many outside volunteers who have worked under Guido's
|
||||
direction to make these releases possible.
|
||||
|
||||
|
||||
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
|
||||
===============================================================
|
||||
|
||||
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||
--------------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") in source or binary form and
|
||||
its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, PSF hereby
|
||||
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
|
||||
analyze, test, perform and/or display publicly, prepare derivative works,
|
||||
distribute, and otherwise use Python alone or in any derivative version,
|
||||
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
||||
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
|
||||
All Rights Reserved" are retained in Python alone or in any derivative version
|
||||
prepared by Licensee.
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python.
|
||||
|
||||
4. PSF is making Python available to Licensee on an "AS IS"
|
||||
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. Nothing in this License Agreement shall be deemed to create any
|
||||
relationship of agency, partnership, or joint venture between PSF and
|
||||
Licensee. This License Agreement does not grant permission to use PSF
|
||||
trademarks or trade name in a trademark sense to endorse or promote
|
||||
products or services of Licensee, or any third party.
|
||||
|
||||
8. By copying, installing or otherwise using Python, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
|
||||
-------------------------------------------
|
||||
|
||||
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
|
||||
|
||||
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
|
||||
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
|
||||
Individual or Organization ("Licensee") accessing and otherwise using
|
||||
this software in source or binary form and its associated
|
||||
documentation ("the Software").
|
||||
|
||||
2. Subject to the terms and conditions of this BeOpen Python License
|
||||
Agreement, BeOpen hereby grants Licensee a non-exclusive,
|
||||
royalty-free, world-wide license to reproduce, analyze, test, perform
|
||||
and/or display publicly, prepare derivative works, distribute, and
|
||||
otherwise use the Software alone or in any derivative version,
|
||||
provided, however, that the BeOpen Python License is retained in the
|
||||
Software, alone or in any derivative version prepared by Licensee.
|
||||
|
||||
3. BeOpen is making the Software available to Licensee on an "AS IS"
|
||||
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
|
||||
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
|
||||
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
|
||||
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
5. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
6. This License Agreement shall be governed by and interpreted in all
|
||||
respects by the law of the State of California, excluding conflict of
|
||||
law provisions. Nothing in this License Agreement shall be deemed to
|
||||
create any relationship of agency, partnership, or joint venture
|
||||
between BeOpen and Licensee. This License Agreement does not grant
|
||||
permission to use BeOpen trademarks or trade names in a trademark
|
||||
sense to endorse or promote products or services of Licensee, or any
|
||||
third party. As an exception, the "BeOpen Python" logos available at
|
||||
http://www.pythonlabs.com/logos.html may be used according to the
|
||||
permissions granted on that web page.
|
||||
|
||||
7. By copying, installing or otherwise using the software, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
|
||||
---------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Corporation for National
|
||||
Research Initiatives, having an office at 1895 Preston White Drive,
|
||||
Reston, VA 20191 ("CNRI"), and the Individual or Organization
|
||||
("Licensee") accessing and otherwise using Python 1.6.1 software in
|
||||
source or binary form and its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, CNRI
|
||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||
license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python 1.6.1
|
||||
alone or in any derivative version, provided, however, that CNRI's
|
||||
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
|
||||
1995-2001 Corporation for National Research Initiatives; All Rights
|
||||
Reserved" are retained in Python 1.6.1 alone or in any derivative
|
||||
version prepared by Licensee. Alternately, in lieu of CNRI's License
|
||||
Agreement, Licensee may substitute the following text (omitting the
|
||||
quotes): "Python 1.6.1 is made available subject to the terms and
|
||||
conditions in CNRI's License Agreement. This Agreement together with
|
||||
Python 1.6.1 may be located on the Internet using the following
|
||||
unique, persistent identifier (known as a handle): 1895.22/1013. This
|
||||
Agreement may also be obtained from a proxy server on the Internet
|
||||
using the following URL: http://hdl.handle.net/1895.22/1013".
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python 1.6.1 or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python 1.6.1.
|
||||
|
||||
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
|
||||
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. This License Agreement shall be governed by the federal
|
||||
intellectual property law of the United States, including without
|
||||
limitation the federal copyright law, and, to the extent such
|
||||
U.S. federal law does not apply, by the law of the Commonwealth of
|
||||
Virginia, excluding Virginia's conflict of law provisions.
|
||||
Notwithstanding the foregoing, with regard to derivative works based
|
||||
on Python 1.6.1 that incorporate non-separable material that was
|
||||
previously distributed under the GNU General Public License (GPL), the
|
||||
law of the Commonwealth of Virginia shall govern this License
|
||||
Agreement only as to issues arising under or with respect to
|
||||
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
|
||||
License Agreement shall be deemed to create any relationship of
|
||||
agency, partnership, or joint venture between CNRI and Licensee. This
|
||||
License Agreement does not grant permission to use CNRI trademarks or
|
||||
trade name in a trademark sense to endorse or promote products or
|
||||
services of Licensee, or any third party.
|
||||
|
||||
8. By clicking on the "ACCEPT" button where indicated, or by copying,
|
||||
installing or otherwise using Python 1.6.1, Licensee agrees to be
|
||||
bound by the terms and conditions of this License Agreement.
|
||||
|
||||
ACCEPT
|
||||
|
||||
|
||||
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
|
||||
The Netherlands. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: brace-expansion
|
||||
version: 5.0.9
|
||||
version: 5.0.8
|
||||
type: npm
|
||||
summary: Brace expansion as known from sh/bash
|
||||
homepage:
|
||||
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: js-yaml
|
||||
version: 4.3.0
|
||||
type: npm
|
||||
summary: YAML 1.2 parser and serializer
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
(The MIT License)
|
||||
|
||||
Copyright (C) 2011-2015 by Vitaly Puzrin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
notices: []
|
||||
Generated
+32
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: xmlbuilder2
|
||||
version: 4.0.3
|
||||
type: npm
|
||||
summary: An XML builder for node.js
|
||||
homepage: https://github.com/oozcitak/xmlbuilder2
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.txt
|
||||
text: |
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Ozgur Ozcitak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices: []
|
||||
@@ -4,344 +4,242 @@
|
||||
[](https://github.com/actions/setup-java/actions/workflows/e2e-versions.yml)
|
||||
[](https://github.com/actions/setup-java/actions/workflows/e2e-cache.yml)
|
||||
|
||||
Set up Java for GitHub Actions workflows. `setup-java` installs a requested Java distribution, adds it to `PATH`, configures `JAVA_HOME`, and can optionally cache build dependencies for Apache Maven, Gradle, and sbt; generate Maven publishing configuration, verify JDK package signatures, manage multiple JDKs, and manage Maven toolchains.
|
||||
The `setup-java` action provides the following functionality for GitHub Actions runners:
|
||||
- Downloading and setting up a requested version of Java. See [Usage](#usage) for a list of supported distributions.
|
||||
- Extracting and caching custom version of Java from a local file.
|
||||
- Configuring runner for publishing using Apache Maven.
|
||||
- Configuring runner for publishing using Gradle.
|
||||
- Configuring runner for using GPG private key.
|
||||
- Registering problem matchers for error output.
|
||||
- Caching dependencies managed by Apache Maven.
|
||||
- Caching dependencies managed by Gradle.
|
||||
- Caching dependencies managed by sbt.
|
||||
- [Maven Toolchains declaration](https://maven.apache.org/guides/mini/guide-using-toolchains.html) for specified JDK versions.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '25'
|
||||
- run: java --version
|
||||
```
|
||||
This action allows you to work with Java and Scala projects.
|
||||
|
||||
## What's new in V6
|
||||
|
||||
> [!NOTE]
|
||||
> V6 is still in development on the `main` branch and is not yet recommended for production workflows. To use it, you must explicitly reference the `main` branch in your workflow, as in
|
||||
>
|
||||
> ```yaml
|
||||
> - uses: actions/setup-java@main
|
||||
> ```
|
||||
>
|
||||
> For production workflows, it is recommended to use the latest stable release `v5`.
|
||||
> V6 is still in development (`main` branch) and is not yet recommended for production workflows.
|
||||
|
||||
## Contents
|
||||
- **Migrated to ESM** to enable support for the latest `@actions/*` package versions. This is an internal implementation change.
|
||||
|
||||
- [What it does](#what-it-does)
|
||||
- [What's new](#whats-new)
|
||||
- [Usage](#usage)
|
||||
- [Inputs](#inputs)
|
||||
- [Supported distributions](#supported-distributions)
|
||||
- [Supported version syntax](#supported-version-syntax)
|
||||
- [Caching](#caching)
|
||||
- [Multiple JDKs and Maven toolchains](#multiple-jdks-and-maven-toolchains)
|
||||
- [Publishing packages](#publishing-packages)
|
||||
- [Advanced usage](#advanced-usage)
|
||||
## Breaking changes in V6
|
||||
|
||||
## What it does
|
||||
- **Renamed inputs that accept environment-variable names** to make it clear that their values are not credentials. Replace `server-username`, `server-password`, and `gpg-passphrase` with `server-username-env-var`, `server-password-env-var`, and `gpg-passphrase-env-var`, respectively. The old names remain as deprecated aliases and emit a warning when used.
|
||||
|
||||
- Downloads and installs Java from a supported distribution.
|
||||
- Uses a requested Java version, a version file, or the `latest` stable release alias.
|
||||
- Extracts and caches a custom JDK archive from a local file.
|
||||
- Configures Maven `settings.xml`, Maven Toolchains, Maven GPG signing inputs, and environment-variable based credentials for publishing workflows.
|
||||
- Registers Java problem matchers for compiler diagnostics and uncaught exceptions.
|
||||
- Caches dependencies for Maven, Gradle, and sbt.
|
||||
- Caches downloaded JDK installations between jobs.
|
||||
- Verifies downloaded archive checksums when a distribution publishes authoritative checksums.
|
||||
- Optionally verifies package signatures for supported distributions.
|
||||
- **The GPG passphrase is now passed to the Maven GPG Plugin through an environment variable (`gpg.passphraseEnvName`) instead of the deprecated `gpg.passphrase` server in `settings.xml`.** Set the environment variable name with `gpg-passphrase-env-var`, which defaults to `GPG_PASSPHRASE`. This requires `maven-gpg-plugin` **3.2.0 or newer**; older versions do not honor `gpg.passphraseEnvName` and, because the `gpg.passphrase` server is no longer written, will not pick up the passphrase. Upgrade the plugin to 3.2.0+.
|
||||
|
||||
`setup-java` works with Java, Scala, Kotlin, Gradle, Maven, and sbt projects.
|
||||
See [GPG](docs/advanced-usage.md#gpg) for details.
|
||||
|
||||
## What's new
|
||||
- **Legacy AdoptOpenJDK distributions were removed.** Replace `adopt` or `adopt-hotspot` with `temurin`, and replace `adopt-openj9` with `semeru`.
|
||||
|
||||
### V6 (in development)
|
||||
## Breaking changes in V5
|
||||
|
||||
- Migrated the action implementation to ESM to support the latest `@actions/*` packages.
|
||||
- Added the `oracle-openjdk` distribution for OpenJDK builds from Oracle.
|
||||
- Added `java-version: latest` to resolve the newest stable GA release from the distribution's remote metadata.
|
||||
- JDK downloads now automatically verify authoritative checksums for [supported distributions](#download-integrity-and-signatures).
|
||||
- Added `force-download: true` to bypass the tool cache and perform a reproducible fresh install.
|
||||
- Dependency caching now supports custom paths with `cache-path` and restore-only operation with `cache-read-only: true`.
|
||||
- Downloaded JDKs are now [cached](#caching-jdk-installations) automatically when `cache` is set; use `cache-jdk` to enable or disable it independently.
|
||||
- Set `problem-matcher: false` to disable Java compiler and uncaught-exception annotations.
|
||||
- GraalVM distributions now set `GRAALVM_HOME` in addition to `JAVA_HOME`.
|
||||
- Invalid boolean values, unsupported distribution/package/platform combinations, and mismatched Maven toolchain ID counts now fail with targeted errors.
|
||||
- Renamed environment-variable-name inputs so they are not mistaken for secret values:
|
||||
- `server-username` -> `server-username-env-var`
|
||||
- `server-password` -> `server-password-env-var`
|
||||
- `gpg-passphrase` -> `gpg-passphrase-env-var`
|
||||
- Deprecated aliases still work, but emit warnings.
|
||||
- Maven GPG passphrases are now passed through `gpg.passphraseEnvName` instead of a deprecated `gpg.passphrase` server entry in `settings.xml`. This requires `maven-gpg-plugin` 3.2.0 or newer. See [GPG](docs/advanced-usage.md#gpg).
|
||||
- Legacy AdoptOpenJDK distributions were removed. Use `temurin` instead of `adopt` or `adopt-hotspot`, and `semeru` instead of `adopt-openj9`.
|
||||
- Upgraded action from node20 to node24
|
||||
> Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release [Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1)
|
||||
|
||||
### V5
|
||||
|
||||
- Upgraded the action runtime from Node 20 to Node 24. Self-hosted runners must use version `v2.327.1` or later. See the [runner release notes](https://github.com/actions/runner/releases/tag/v2.327.1).
|
||||
- Added support for [GraalVM Community](#supported-distributions) and [Tencent Kona](#supported-distributions).
|
||||
- Expanded `java-version-file` support with `.sdkmanrc` files and automatic distribution detection from SDKMAN and asdf vendor identifiers.
|
||||
- Added optional package-signature verification for Eclipse Temurin and Microsoft Build of OpenJDK downloads.
|
||||
- Added `set-default: false` for installing a JDK without changing `JAVA_HOME` or `PATH`.
|
||||
- Improved dependency caching with separate Maven and Gradle wrapper caches, Maven extension-aware cache keys, and the `cache-primary-key` output.
|
||||
- Improved Maven and Java build behavior by preserving toolchain entries across repeated action invocations, suppressing transfer progress by default, generating non-interactive Maven settings, and matching `javac` compiler errors.
|
||||
- Renamed the `jdkFile` input to `jdk-file`; the old name remains available as a deprecated alias.
|
||||
- See the [complete V5 release history](https://github.com/actions/setup-java/releases?q=v5&expanded=true) for enhancements and fixes across all V5 releases.
|
||||
|
||||
### Older versions
|
||||
|
||||
> [!WARNING]
|
||||
> `actions/setup-java` versions `v1` through `v4` are deprecated. Upgrade workflows to `actions/setup-java@v5`, the latest stable release.
|
||||
For more details, see the full release notes on the [releases page](https://github.com/actions/setup-java/releases/tag/v5.0.0)
|
||||
|
||||
## Usage
|
||||
|
||||
### Install Eclipse Temurin
|
||||
- `java-version`: The Java version that is going to be set up. Takes a whole or [semver](#supported-version-syntax) Java version. If not specified, the action will expect `java-version-file` input to be specified.
|
||||
|
||||
- `java-version-file`: The path to a file containing java version. Supported file types are `.java-version`, `.tool-versions`, and `.sdkmanrc`. See more details in [about .java-version-file](docs/advanced-usage.md#Java-version-file).
|
||||
|
||||
- `distribution`: Java [distribution](#supported-distributions). Required unless `java-version-file` points to `.sdkmanrc` with a recognized distribution suffix (for example `java=21.0.5-tem`).
|
||||
|
||||
- `java-package`: The packaging variant of the chosen distribution. Possible values across all distributions are `jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac`, `jdk+jmods`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, and `jre+ft`. Supported values vary by distribution; see the [package compatibility table](docs/advanced-usage.md#package-compatibility). Default value: `jdk`.
|
||||
|
||||
- `architecture`: The target architecture of the package. Canonical values are `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`, `ppc64`, and `s390x`; the aliases `ia32`, `amd64`, `arm`, and `arm64` normalize to `x86`, `x64`, `armv7`, and `aarch64`. Supported values vary by distribution and operating system. Default value: Derived from the runner machine.
|
||||
|
||||
- `jdk-file`: If a use-case requires a custom distribution setup-java uses the compressed JDK from the location pointed by this input and will take care of the installation and caching on the VM. Note: `distribution` must be set to 'jdkfile' (case-sensitive; all lowercase) when using this option. (The camelCase `jdkFile` input is still accepted as a deprecated alias and may be removed in a future release.)
|
||||
|
||||
- `check-latest`: Setting this option makes the action to check for the latest available version for the version spec.
|
||||
|
||||
- `force-download`: Set to `true` to always download Java and replace any matching version in the tool cache. This can help make builds reproducible when a runner image has modified a pre-installed JDK, such as its `cacerts` file. Default value: `false`.
|
||||
|
||||
- `set-default`: Set to `false` to install a JDK without making it the default. When `false`, `JAVA_HOME` and `PATH` are not updated, but `JAVA_HOME_<major>_<arch>` is still set so the JDK remains discoverable. Default value: `true`. See [Installing JDK without setting as default](docs/advanced-usage.md#Installing-JDK-without-setting-as-default) for more details.
|
||||
|
||||
- `problem-matcher`: Set to `false` to disable Java problem matcher annotations (compiler diagnostics and uncaught exceptions). Default value: `true`. See [Java problem matcher](docs/advanced-usage.md#java-problem-matcher-compiler-annotations) for details and annotation limits.
|
||||
|
||||
- `verify-signature`: Verifies downloaded Java package signatures when supported by the selected distribution. Currently supported for `temurin` and `microsoft`. If set to `true` for unsupported distributions, the action fails.
|
||||
|
||||
- `verify-signature-public-key`: ASCII-armored GPG public key used to verify the downloaded package signature. Overrides the default bundled key for the selected distribution.
|
||||
|
||||
- `token`: The token used to authenticate when fetching version manifests hosted on GitHub.com. Defaults to `${{ github.token }}` when running on GitHub.com; defaults to an empty string on GitHub Enterprise Server. On GHES, provide a GitHub.com personal access token if manifest requests are rate-limited. See [Using Microsoft distribution on GHES](docs/advanced-usage.md#using-microsoft-distribution-on-ghes) for more details.
|
||||
|
||||
- `cache`: Quick [setup caching](#caching-packages-dependencies) for the dependencies managed through one of the predefined package managers. It can be one of "maven", "gradle" or "sbt".
|
||||
|
||||
- `cache-dependency-path`: The path to a dependency file: pom.xml, build.gradle, build.sbt, etc. This option can be used with the `cache` option. If this option is omitted, the action searches for the dependency file in the entire repository. This option supports wildcards and a list of file names for caching multiple dependencies.
|
||||
|
||||
- `cache-path`: The dependency cache path to use instead of the default path for the package manager selected by `cache`. This option supports a list of paths and exclusion patterns. The build tool must be configured to use the same location.
|
||||
|
||||
- `cache-read-only`: Restore dependency caches without saving changes in the post action. Defaults to `false`. Use this for pull requests, merge queues, short-lived branches, and fan-out jobs that should consume caches populated by a default-branch or seed job.
|
||||
|
||||
#### Maven options
|
||||
The action has a bunch of inputs to generate maven's [settings.xml](https://maven.apache.org/settings.html) on the fly and pass the values to Apache Maven GPG Plugin as well as Apache Maven Toolchains. See [advanced usage](docs/advanced-usage.md) for more.
|
||||
|
||||
- `overwrite-settings`: By default action overwrites the settings.xml. In order to skip generation of file if it exists, set this to `false`.
|
||||
|
||||
- `server-id`: ID of the distributionManagement repository in the pom.xml file. Default is `github`.
|
||||
|
||||
- `server-username-env-var`: Environment variable name for the username for authentication to the Apache Maven repository. Default is GITHUB\_ACTOR.
|
||||
|
||||
- `server-password-env-var`: Environment variable name for password or token for authentication to the Apache Maven repository. Default is GITHUB\_TOKEN.
|
||||
|
||||
- `settings-path`: Maven related setting to point to the directory where the settings.xml file will be written. Default is \~/.m2.
|
||||
|
||||
- `gpg-private-key`: GPG private key to import. Default is empty string.
|
||||
|
||||
- `gpg-passphrase-env-var`: Environment variable name for the GPG private key passphrase. Default is GPG\_PASSPHRASE.
|
||||
|
||||
- `mvn-toolchain-id`: Name of Maven Toolchain ID if the default name of `${distribution}_${java-version}` is not wanted. When supplied, the number of IDs must match the number of Java versions.
|
||||
|
||||
- `mvn-toolchain-vendor`: Name of Maven Toolchain Vendor if the default name of `${distribution}` is not wanted.
|
||||
|
||||
- `show-download-progress`: Set to `true` to keep Maven artifact download and transfer progress in build logs. Default value: `false`. By default, the action adds `-ntp` (`--no-transfer-progress`) to `MAVEN_ARGS`. This input has no effect on non-Maven builds. See [Maven transfer progress](docs/advanced-usage.md#maven-transfer-progress-download-logs) for more details.
|
||||
|
||||
### Download integrity verification
|
||||
|
||||
When a selected distribution publishes an authoritative checksum for an archive, `setup-java` automatically verifies each downloaded JDK, JRE, or JMOD archive before extraction and caching. No input is required. Automatic checksum verification is currently available for `temurin`, `semeru`, `corretto`, `dragonwell`, `kona`, `sapmachine`, `graalvm`, `graalvm-community`, `zulu`, `oracle`, `oracle-openjdk`, `microsoft`, and `jetbrains`.
|
||||
|
||||
Distributions or individual releases without an authoritative checksum continue to install normally, with the omission reported only in debug logs. Archives resolved directly from the runner tool cache are not downloaded again and therefore are not reverified.
|
||||
|
||||
Checksums detect corrupted or unexpectedly modified downloads before they are persisted in the runner tool cache.
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
#### Eclipse Temurin
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||
java-version: '25'
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
### Install Microsoft Build of OpenJDK
|
||||
|
||||
#### Azul Zulu OpenJDK
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: microsoft
|
||||
distribution: 'zulu' # See 'Supported distributions' for available options
|
||||
java-version: '25'
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
### Read the version from a file
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version-file: .java-version
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
Supported version files are `.java-version`, `.tool-versions`, and `.sdkmanrc`. A `.sdkmanrc` file can also provide the distribution when it contains a recognized suffix, such as `java=21.0.5-tem`.
|
||||
|
||||
### Use the newest stable Java
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: latest
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
`latest` resolves the newest stable GA release from remote metadata rather than from the runner tool cache. Distributions that do not publish a release listing (such as `oracle` and `graalvm`) resolve the newest GA feature version from the Adoptium available-releases API and then request that version from their own catalog. `latest` is not supported with `java-version-file`, early-access versions, or `distribution: jdkfile`.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Description | Default |
|
||||
| --- | --- | --- |
|
||||
| `java-version` | Java version to install. Supports whole versions, semver ranges, early-access versions, and `latest`. Required unless `java-version-file` is set. | |
|
||||
| `java-version-file` | Path to `.java-version`, `.tool-versions`, or `.sdkmanrc`. Used when `java-version` is not set. | |
|
||||
| `distribution` | Java distribution keyword. Values are case-sensitive and must match one of the supported keywords below. Required unless `java-version-file` points to `.sdkmanrc` with a recognized distribution suffix. | |
|
||||
| `java-package` | Package variant such as `jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac`, `jdk+jmods`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, or `jre+ft`. Support varies by distribution. | `jdk` |
|
||||
| `architecture` | Package architecture. Canonical values are `x86`, `x64`, `armv7`, `aarch64`, `ppc64le`, `ppc64`, and `s390x`. Aliases `ia32`, `amd64`, `arm`, and `arm64` are normalized. | Runner architecture |
|
||||
| `jdk-file` | Local compressed JDK archive. Requires `distribution: jdkfile`. | |
|
||||
| `check-latest` | Check remote metadata for the latest version satisfying the version spec before using the runner tool cache. | `false` |
|
||||
| `force-download` | Always download Java and replace any matching version in the tool cache. | `false` |
|
||||
| `set-default` | Add Java to `PATH` and set `JAVA_HOME`. When `false`, only version-specific `JAVA_HOME_<major>_<arch>` variables are set. | `true` |
|
||||
| `problem-matcher` | Register Java compiler and uncaught exception problem matchers. | `true` |
|
||||
| `verify-signature` | Verify downloaded Java package signatures when supported. Currently supported for `temurin` and `microsoft`. | `false` |
|
||||
| `verify-signature-public-key` | ASCII-armored GPG public key to use for signature verification. Overrides the bundled key. | |
|
||||
| `token` | Token for fetching GitHub.com-hosted version manifests, useful on GitHub Enterprise Server when unauthenticated requests are rate-limited. | `${{ github.token }}` on GitHub.com; empty string on GHES |
|
||||
| `cache` | Enable dependency caching for `maven`, `gradle`, or `sbt`. | |
|
||||
| `cache-jdk` | Cache downloaded JDK installations between jobs. When omitted, JDK caching is enabled only if `cache` is set. Set explicitly to `true` or `false` to override. | Enabled when `cache` is set |
|
||||
| `cache-dependency-path` | Dependency file paths used for cache key hashing. Supports globs and multiline values. | Auto-detected by package manager |
|
||||
| `cache-path` | Cache paths to use instead of the package manager's default dependency cache path. Supports multiline values and exclusions. | |
|
||||
| `cache-read-only` | Restore dependency, wrapper, and JDK caches without saving changes in the post step. | `false` |
|
||||
| `server-id` | Maven repository ID used in generated `settings.xml`. | `github` |
|
||||
| `server-username-env-var` | Environment variable name for Maven repository username. | `GITHUB_ACTOR` |
|
||||
| `server-password-env-var` | Environment variable name for Maven repository password or token. | `GITHUB_TOKEN` |
|
||||
| `settings-path` | Directory where `settings.xml` is written. | `~/.m2` |
|
||||
| `overwrite-settings` | Overwrite an existing `settings.xml`. | `true` |
|
||||
| `gpg-private-key` | GPG private key to import. | |
|
||||
| `gpg-passphrase-env-var` | Environment variable name for the GPG private key passphrase. | `GPG_PASSPHRASE` when a key is set |
|
||||
| `mvn-toolchain-id` | Maven Toolchain ID. When multiple Java versions are installed, the number of IDs must match the number of versions. | `${mvn-toolchain-vendor}_${java-version}` |
|
||||
| `mvn-toolchain-vendor` | Maven Toolchain vendor value. | `${distribution}` |
|
||||
| `show-download-progress` | Keep Maven artifact download and transfer progress in logs. When `false`, the action adds `-ntp` to `MAVEN_ARGS`. | `false` |
|
||||
|
||||
- `java-package`: Supported package types are `jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac`, `jdk+jmods`, `jdk+jcef`, `jre+jcef`, `jdk+ft`, and `jre+ft`. Availability varies by distribution.
|
||||
|
||||
Deprecated aliases `jdkFile`, `server-username`, `server-password`, and `gpg-passphrase` remain accepted for compatibility, but should be replaced with the current input names.
|
||||
|
||||
## Outputs
|
||||
|
||||
| Output | Description |
|
||||
| --- | --- |
|
||||
| `distribution` | Distribution that was installed. |
|
||||
| `version` | Actual Java version that was installed. |
|
||||
| `path` | Installation path, also used for `JAVA_HOME` when `set-default` is enabled. |
|
||||
| `cache-hit` | Whether an exact dependency cache match was restored. |
|
||||
| `cache-primary-key` | Primary cache key computed for the selected package manager. Empty when caching is disabled or skipped. |
|
||||
|
||||
## Supported distributions
|
||||
|
||||
| Keyword | Distribution | License |
|
||||
| --- | --- | --- |
|
||||
| `corretto` | [Amazon Corretto](https://aws.amazon.com/corretto/) | [License](https://aws.amazon.com/corretto/faqs/) |
|
||||
| `dragonwell` | [Alibaba Dragonwell JDK](https://dragonwell-jdk.io/) | [License](https://www.aliyun.com/product/dragonwell/) |
|
||||
| `graalvm` | [Oracle GraalVM](https://www.graalvm.org/) | [License](https://www.oracle.com/downloads/licenses/graal-free-license.html) |
|
||||
| `graalvm-community` | [GraalVM Community](https://github.com/graalvm/graalvm-ce-builds/releases) | [License](https://github.com/oracle/graal/blob/master/LICENSE) |
|
||||
| `jetbrains` | [JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/) | [License](https://github.com/JetBrains/JetBrainsRuntime/blob/main/LICENSE) |
|
||||
| `kona` | [Tencent Kona JDK](https://tencent.github.io/konajdk/) | [License](https://tencent.github.io/konajdk/LICENSE.txt) |
|
||||
| `liberica` | [Liberica JDK](https://bell-sw.com/) | [License](https://bell-sw.com/liberica_eula/) |
|
||||
| `liberica-nik` | [Liberica Native Image Kit](https://bell-sw.com/pages/downloads/native-image-kit/) | [License](https://bell-sw.com/liberica_nik_eula/) |
|
||||
| `microsoft` | [Microsoft Build of OpenJDK](https://www.microsoft.com/openjdk) | [License](https://docs.microsoft.com/java/openjdk/faq) |
|
||||
| `oracle` | [Oracle JDK](https://www.oracle.com/java/technologies/downloads/) | [License](https://java.com/freeuselicense) |
|
||||
| `oracle-openjdk` | [Oracle OpenJDK](https://jdk.java.net/) | [License](https://openjdk.org/legal/gplv2+ce.html) |
|
||||
| `sapmachine` | [SAP SapMachine JDK/JRE](https://sapmachine.io/) | [License](https://github.com/SAP/SapMachine/blob/sapmachine/LICENSE) |
|
||||
| `semeru` | [IBM Semeru Runtime Open Edition](https://developer.ibm.com/languages/java/semeru-runtimes/downloads/) | [License](https://openjdk.java.net/legal/gplv2+ce.html) |
|
||||
| `temurin` | [Eclipse Temurin](https://adoptium.net/) | [License](https://adoptium.net/about.html) |
|
||||
| `zulu` | [Azul Zulu OpenJDK](https://www.azul.com/downloads/zulu-community/?package=jdk) | [License](https://www.azul.com/products/zulu-and-zulu-enterprise/zulu-terms-of-use/) |
|
||||
| `jdkfile` | Custom JDK archive | |
|
||||
#### Supported version syntax
|
||||
The `java-version` input supports an exact version or a version range using [SemVer](https://semver.org/) notation. The values below are examples, not an exhaustive list:
|
||||
- major versions, such as: `8`, `11`, `16`, `17`, `21`, `25`
|
||||
- more specific versions: `8.0.282+8`, `8.0.232`, `11.0`, `11.0.4`, `17.0`
|
||||
- multi-field Java versions (JEP 322), such as: `11.0.9.1`, `18.0.1.1`
|
||||
- early access (EA) versions: `15-ea`, `15.0.0-ea`
|
||||
- the `latest` alias, which floats to the newest available stable (GA) release
|
||||
|
||||
> [!NOTE]
|
||||
> Distribution availability, package variants, architectures, and version metadata differ by vendor. Check the vendor documentation when a specific version or platform matters.
|
||||
> - `latest` always resolves the newest version from the distribution's remote metadata (it behaves like `check-latest: true`), so it ignores any older version already present in the runner tool cache. This has the same performance trade-off described in [Check latest](#check-latest).
|
||||
> - `latest` is only supported through the `java-version` input, not through `java-version-file`, and it resolves stable (GA) releases only — it cannot be combined with `-ea`.
|
||||
> - The `jdkfile` distribution does not support `latest`, as it installs from a local file.
|
||||
> - For `oracle` and `graalvm` (Oracle GraalVM), `latest` uses the Adoptium API only to determine the newest GA **major version number** — the JDK binary itself is still downloaded from the Oracle / GraalVM servers for that major. Because these distributions have no endpoint to list their own releases, if their servers haven't published the resolved major yet, the action fails and asks you to specify a concrete version. Note the Oracle JDK license caveat below still applies to a floating `latest`.
|
||||
> - For `graalvm-community`, `latest` floats to the newest GA release published on GitHub, so it never depends on the Adoptium API and always resolves to the newest major that GraalVM Community actually ships.
|
||||
|
||||
Additional distribution notes:
|
||||
#### Supported distributions
|
||||
Currently, the following distributions are supported:
|
||||
| Keyword | Distribution / Official site | License
|
||||
|-|-|-|
|
||||
| `temurin` | [Eclipse Temurin](https://adoptium.net/) | [`temurin` license](https://adoptium.net/about.html)
|
||||
| `zulu` | [Azul Zulu OpenJDK](https://www.azul.com/downloads/zulu-community/?package=jdk) | [`zulu` license](https://www.azul.com/products/zulu-and-zulu-enterprise/zulu-terms-of-use/) |
|
||||
| `liberica` | [Liberica JDK](https://bell-sw.com/) | [`liberica` license](https://bell-sw.com/liberica_eula/) |
|
||||
| `liberica-nik` | [Liberica Native Image Kit](https://bell-sw.com/pages/downloads/native-image-kit/) | [`liberica-nik` license](https://bell-sw.com/liberica_nik_eula/) |
|
||||
| `microsoft` | [Microsoft Build of OpenJDK](https://www.microsoft.com/openjdk) | [`microsoft` license](https://docs.microsoft.com/java/openjdk/faq)
|
||||
| `corretto` | [Amazon Corretto Build of OpenJDK](https://aws.amazon.com/corretto/) | [`corretto` license](https://aws.amazon.com/corretto/faqs/)
|
||||
| `semeru` | [IBM Semeru Runtime Open Edition](https://developer.ibm.com/languages/java/semeru-runtimes/downloads/) | [`semeru` license](https://openjdk.java.net/legal/gplv2+ce.html) |
|
||||
| `oracle` | [Oracle JDK](https://www.oracle.com/java/technologies/downloads/) | [`oracle` license](https://java.com/freeuselicense)
|
||||
| `oracle-openjdk` | [Oracle OpenJDK](https://jdk.java.net/) | [`oracle-openjdk` license](https://openjdk.org/legal/gplv2+ce.html)
|
||||
| `dragonwell` | [Alibaba Dragonwell JDK](https://dragonwell-jdk.io/) | [`dragonwell` license](https://www.aliyun.com/product/dragonwell/)
|
||||
| `sapmachine` | [SAP SapMachine JDK/JRE](https://sapmachine.io/) | [`sapmachine` license](https://github.com/SAP/SapMachine/blob/sapmachine/LICENSE)
|
||||
| `graalvm` | [Oracle GraalVM](https://www.graalvm.org/) | [`graalvm` license](https://www.oracle.com/downloads/licenses/graal-free-license.html)
|
||||
| `graalvm-community` | [GraalVM Community](https://github.com/graalvm/graalvm-ce-builds/releases) | [`graalvm-community` license](https://github.com/oracle/graal/blob/master/LICENSE)
|
||||
| `jetbrains` | [JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/) | [`jetbrains` license](https://github.com/JetBrains/JetBrainsRuntime/blob/main/LICENSE)
|
||||
| `kona` | [Tencent Kona JDK](https://tencent.github.io/konajdk/) | [`kona` license](https://tencent.github.io/konajdk/LICENSE.txt)
|
||||
| `jdkfile` | Custom JDK Installation | |
|
||||
|
||||
- Oracle OpenJDK builds are archived after a limited number of releases and no longer receive security updates. To continue receiving security patches, use Oracle JDK or another vendor.
|
||||
- Azul Zulu maps `arm64` to `aarch64` when querying the Azul Metadata API.
|
||||
- GraalVM Community is available as `distribution: graalvm-community` for stable JDK 17 and later releases.
|
||||
- On Ubuntu runners, commands executed with `sudo` do not inherit the `JAVA_HOME` and `PATH` set by `setup-java` and may fall back to the system-default JDK.
|
||||
> [!NOTE]
|
||||
> - The different distributors can provide discrepant list of available versions / supported configurations. Please refer to the official documentation to see the list of supported versions.
|
||||
> - Oracle OpenJDK builds are created and hosted by Oracle. After a limited number of releases, Oracle archives these builds and no longer provides security updates. To continue receiving security patches, users must move to Oracle JDK or choose a different vendor.
|
||||
> - For Azul Zulu OpenJDK, architecture `arm64` is mapped to `aarch64` when querying the Azul Metadata API.
|
||||
> - To comply with the GraalVM Free Terms and Conditions (GFTC) license, it is recommended to use GraalVM JDK 17 version 17.0.12, as this is the only version of GraalVM JDK 17 available under the GFTC license. Additionally, it is encouraged to consider upgrading to GraalVM JDK 21, which offers the latest features and improvements.
|
||||
> - GraalVM Community is available as `distribution: 'graalvm-community'` for stable JDK 17 and later releases published on GitHub.
|
||||
|
||||
## Supported version syntax
|
||||
**NOTE:** Oracle JDK 17 licensing varies by patch level. As shown on the [JDK 17 Archive](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) (versions up to 17.0.12 are under the [NFTC](https://www.oracle.com/downloads/licenses/no-fee-license.html) license) and the [JDK 17.0.13+ Archive](https://www.oracle.com/java/technologies/javase/jdk17-0-13-later-archive-downloads.html) (versions 17.0.13 and later are under the [OTN](https://www.oracle.com/downloads/licenses/javase-license1.html) license). To stay on the free NFTC license, use `distribution: 'oracle'` with `java-version: '17.0.12'` (or earlier) instead of the floating `'17'`. Alternatively, upgrade to Oracle JDK 21+, which remains under the NFTC license.
|
||||
|
||||
`java-version` accepts exact versions, version ranges, early-access versions, and `latest`.
|
||||
**NOTE:** On Ubuntu runners, commands executed via `sudo` do not inherit the `JAVA_HOME` and `PATH` set by `setup-java` and will fall back to the runner image's system-default JDK.
|
||||
|
||||
| Syntax | Examples |
|
||||
| --- | --- |
|
||||
| Major version | `8`, `11`, `17`, `21`, `25` |
|
||||
| Specific feature or patch version | `11.0`, `11.0.4`, `17.0`, `8.0.282+8` |
|
||||
| JEP 322 multi-field versions | `11.0.9.1`, `18.0.1.1` |
|
||||
| Early access | `15-ea`, `15.0.0-ea`, `27-ea` |
|
||||
| Latest stable GA release | `latest` |
|
||||
### Caching packages dependencies
|
||||
The action has a built-in functionality for caching and restoring dependencies. It uses [toolkit/cache](https://github.com/actions/toolkit/tree/main/packages/cache) under hood for caching dependencies but requires less configuration settings. Supported package managers are gradle, maven and sbt. The format of the used cache key is `setup-java-${{ platform }}-${{ packageManager }}-${{ fileHash }}`, where the hash is based on the following files:
|
||||
|
||||
When `check-latest` is `false`, the action first tries the runner tool cache for the requested distribution, package type, architecture, and version range. It downloads Java only when no matching cached version is found. When `check-latest` is `true`, the action checks remote metadata first and downloads if the cached version is not current.
|
||||
- gradle: `**/*.gradle*`, `**/gradle-wrapper.properties`, `buildSrc/**/Versions.kt`, `buildSrc/**/Dependencies.kt`, `gradle/*.versions.toml`, and `**/versions.properties`
|
||||
- maven: `**/pom.xml`, `**/.mvn/wrapper/maven-wrapper.properties`, and `**/.mvn/extensions.xml`
|
||||
- sbt: all sbt build definition files `**/*.sbt`, `**/project/build.properties`, `**/project/**.scala`, `**/project/**.sbt`
|
||||
|
||||
GitHub-hosted runners primarily pre-cache Eclipse Temurin JDKs. See the installed Java versions for [Ubuntu](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md#java), [Windows](https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md#java), and [macOS](https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#java). On a fresh GitHub-hosted runner, requests for other distributions usually miss the tool cache and resolve from remote metadata. For broad version ranges such as a major version (`21`, `25`), this often behaves similarly to `check-latest: true` because the action downloads the latest available release that satisfies the range.
|
||||
When the option `cache-dependency-path` is specified, the hash is based on the matching file. This option supports wildcards and a list of file names, and is especially useful for monorepos.
|
||||
|
||||
## Download integrity and signatures
|
||||
|
||||
`setup-java` automatically verifies downloaded archive checksums when a selected distribution publishes an authoritative checksum. Automatic checksum verification currently applies to `temurin`, `semeru`, `corretto`, `dragonwell`, `kona`, `sapmachine`, `graalvm`, `graalvm-community`, `zulu`, `oracle`, `oracle-openjdk`, `microsoft`, and `jetbrains`.
|
||||
|
||||
Distributions or individual releases without an authoritative checksum continue to install normally, with the omission reported in debug logs. Installations resolved directly from the runner tool cache — including JDKs preinstalled on the runner image and JDKs installed by an earlier step of the same job — are not downloaded again and are not reverified, even when `verify-signature: true` is set. Use `force-download: true` to always download and verify the archive.
|
||||
|
||||
Use `verify-signature: true` to verify package signatures for distributions that support it. Currently supported distributions are `temurin` and `microsoft`; setting it for an unsupported distribution fails the workflow.
|
||||
|
||||
## Caching
|
||||
|
||||
`setup-java` manages three kinds of caches. Each one is restored and saved as a separate cache entry.
|
||||
|
||||
| Cache | What it stores | Key based on | How it is enabled |
|
||||
| --- | --- | --- | --- |
|
||||
| Dependency cache | Downloaded dependencies, such as `~/.m2/repository`, `~/.gradle/caches`, or the sbt cache paths | Runner OS, architecture, package manager, and a hash of the dependency files | Set `cache` to `maven`, `gradle`, or `sbt` |
|
||||
| Wrapper caches | Maven and Gradle wrapper distributions (`~/.m2/wrapper/dists`, `~/.gradle/wrapper`) | Runner OS, architecture, wrapper cache name, and a hash of the wrapper properties | Set `cache` to `maven` or `gradle` |
|
||||
| JDK cache | The downloaded JDK installation | Runner OS, architecture, distribution, package type, resolved version, release identity, and signature-verification identity | Enabled implicitly whenever `cache` is set, or explicitly with `cache-jdk: true`. Opt out with `cache-jdk: false` |
|
||||
|
||||
Set `cache` to `maven`, `gradle`, or `sbt` to cache dependencies with minimal configuration.
|
||||
Use `cache-path` to replace the selected package manager's default dependency
|
||||
cache paths. Each non-empty line is passed to `actions/cache`, including
|
||||
supported exclusion patterns. `setup-java` does not configure the build tool,
|
||||
so the build must use the same paths:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '25'
|
||||
cache: maven
|
||||
- run: mvn verify
|
||||
```
|
||||
|
||||
The primary dependency cache key is `setup-java-<runner-os>-<node-arch>-<package-manager>-<file-hash>`, where `<node-arch>` is the runner's Node.js process architecture. The primary cache stores dependency directories such as `~/.m2/repository`, `~/.gradle/caches`, or the sbt cache paths. Its file hash is based on these files by default:
|
||||
|
||||
| Package manager | Files used for the primary dependency-cache key |
|
||||
| --- | --- |
|
||||
| Gradle | `**/*.gradle*`, `**/gradle-wrapper.properties`, `buildSrc/**/Versions.kt`, `buildSrc/**/Dependencies.kt`, `gradle/*.versions.toml`, `**/versions.properties` |
|
||||
| Maven | `**/pom.xml`, `**/.mvn/wrapper/maven-wrapper.properties`, `**/.mvn/extensions.xml` |
|
||||
| sbt | `**/*.sbt`, `**/project/build.properties`, `**/project/**.scala`, `**/project/**.sbt` |
|
||||
|
||||
Use `cache-dependency-path` to override the files used for key hashing, especially in monorepos:
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: gradle
|
||||
cache-dependency-path: |
|
||||
sub-project/*.gradle*
|
||||
sub-project/**/gradle-wrapper.properties
|
||||
```
|
||||
|
||||
Use `cache-path` when the build tool stores dependencies outside the default location:
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '25'
|
||||
cache: maven
|
||||
cache: 'maven'
|
||||
cache-path: |
|
||||
/custom/maven/repository
|
||||
!/custom/maven/repository/**/*.lastUpdated
|
||||
- run: mvn -Dmaven.repo.local=/custom/maven/repository verify
|
||||
```
|
||||
|
||||
`cache-path` changes what is restored and saved, but not the cache key. Jobs that should share a cache key must use the same OS, architecture, package manager, dependency files, and cache paths.
|
||||
`cache-path` does not change the cache key. The key continues to use the runner
|
||||
OS, architecture, selected package manager, and dependency-file hash described
|
||||
above. Jobs intended to share a cache key must therefore use the same
|
||||
`cache-path` values so that they restore and save the same filesystem
|
||||
locations.
|
||||
|
||||
### Wrapper caches
|
||||
The Maven and Gradle wrapper caches remain at their documented default paths
|
||||
and are managed independently of `cache-path`. For advanced keying, fallback
|
||||
keys, or cache topologies that do not map to one package manager's dependency
|
||||
paths, use [`actions/cache`](https://github.com/actions/cache) directly.
|
||||
|
||||
Maven and Gradle wrapper distributions are restored and saved as additional cache entries, separate from the primary dependency cache. These entries have their own keys in the form `setup-java-<runner-os>-<node-arch>-<wrapper-cache-name>-<file-hash>`.
|
||||
The workflow output `cache-hit` is set to indicate if an exact match was found for the key [as actions/cache does](https://github.com/actions/cache/tree/main#outputs).
|
||||
|
||||
| Package manager | Wrapper cache name | Cached path | Files used for wrapper-cache key |
|
||||
| --- | --- | --- | --- |
|
||||
| Maven | `maven-wrapper` | `~/.m2/wrapper/dists` | `**/.mvn/wrapper/maven-wrapper.properties` |
|
||||
| Gradle | `gradle-wrapper` | `~/.gradle/wrapper` | `**/gradle-wrapper.properties` |
|
||||
The workflow output `cache-primary-key` exposes the primary cache key computed by the action for the configured build tool. It is useful for composing with [`actions/cache`](https://github.com/actions/cache) or [`actions/cache/restore`](https://github.com/actions/cache/tree/main/restore) in later steps or dependent jobs that need to reuse the exact same key. It is empty when caching is not enabled or when caching is skipped (for example, when the cache service is unavailable).
|
||||
|
||||
These wrapper caches are independent from dependency caches, so they remain useful even when dependency files change frequently. The wrapper properties are also part of the Maven and Gradle primary dependency-cache key because wrapper changes can affect how dependencies are resolved, but the wrapper distribution files themselves are stored in the separate wrapper cache entries above.
|
||||
The cache input is optional, and caching is turned off by default.
|
||||
|
||||
For advanced Gradle caching features such as build output caching, configuration cache support, encrypted cache storage, cleanup, and fine-grained cache control, consider [`gradle/actions/setup-gradle`](https://github.com/gradle/actions/tree/main/setup-gradle).
|
||||
|
||||
### Caching JDK installations
|
||||
|
||||
The JDK cache stores the downloaded JDK installation so later runs skip the download. It is enabled implicitly whenever dependency `cache` is set, so most workflows that cache dependencies are already caching the JDK. Set `cache-jdk: true` to enable it without dependency caching, or `cache-jdk: false` to opt out while keeping dependency caching. With neither `cache` nor `cache-jdk` set, nothing is cached.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Because JDK caching is on by default whenever `cache` is set, review [Caching JDK installations](docs/advanced-usage.md#caching-jdk-installations)
|
||||
> for the full `cache`/`cache-jdk` matrix, cache identity and storage impact.
|
||||
|
||||
### Read-only caches
|
||||
|
||||
Set `cache-read-only: true` to restore dependency, wrapper, and JDK caches without saving changes in the post action. This is useful for pull requests, merge queues, short-lived branches, and matrix fan-out jobs that should only consume caches produced elsewhere.
|
||||
Set `cache-read-only: true` to restore the main dependency cache and any Maven
|
||||
or Gradle wrapper cache without archiving or uploading changes after the job.
|
||||
For example, a workflow can allow only the default branch to write caches while
|
||||
pull requests, merge queues, and short-lived branches remain read-only:
|
||||
|
||||
```yaml
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: maven
|
||||
cache: 'maven'
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
```
|
||||
|
||||
For matrix fan-out, seed the cache once and make matrix jobs read-only consumers:
|
||||
For a fan-out matrix, use one seed job to populate a complete cache and make
|
||||
every matrix job a read-only consumer. The seed and consumers must use the same
|
||||
runner OS and cache dependency inputs so they compute the same key:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
@@ -349,11 +247,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: maven
|
||||
cache: 'maven'
|
||||
- run: mvn dependency:go-offline dependency:resolve-plugins
|
||||
|
||||
build:
|
||||
@@ -364,111 +262,178 @@ jobs:
|
||||
goal: [test, verify, package]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: maven
|
||||
cache: 'maven'
|
||||
cache-read-only: true
|
||||
- run: mvn ${{ matrix.goal }}
|
||||
```
|
||||
|
||||
### Cache segment restore timeout
|
||||
**Maven Wrapper:** when `cache: 'maven'` is enabled, the action also caches and restores the Maven Wrapper distribution downloaded to `~/.m2/wrapper/dists` (in addition to the local repository), so wrapper-based (`./mvnw`) builds don't re-download the Maven distribution. The wrapper distribution is stored in a **separate** cache entry keyed only on `**/.mvn/wrapper/maven-wrapper.properties`, so it stays cached across the frequent `pom.xml` changes that rotate the main dependency cache key.
|
||||
|
||||
Cache downloads are split into segments. To reduce the chance of a stuck segment blocking a workflow, set `SEGMENT_DOWNLOAD_TIMEOUT_MINS`:
|
||||
#### Caching gradle dependencies
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'gradle'
|
||||
cache-dependency-path: | # optional
|
||||
sub-project/*.gradle*
|
||||
sub-project/**/gradle-wrapper.properties
|
||||
- run: ./gradlew build --no-daemon
|
||||
```
|
||||
Using the `cache: gradle` provides a simple and effective way to cache Gradle dependencies with minimal configuration.
|
||||
|
||||
**Gradle Wrapper:** when `cache: 'gradle'` is enabled, the action also caches and restores the Gradle Wrapper distribution downloaded to `~/.gradle/wrapper` (in addition to the Gradle caches), so wrapper-based (`./gradlew`) builds don't re-download the Gradle distribution. The wrapper distribution is stored in a **separate** cache entry keyed only on `**/gradle-wrapper.properties`, so it stays cached across the frequent `*.gradle*` changes that rotate the main dependency cache key.
|
||||
|
||||
For projects that require more advanced `Gradle` caching features, such as caching build outputs, support for Gradle configuration cache, encrypted cache storage, fine-grained cache control (including options to enable or disable the cache, set it to read-only or write-only, perform automated cleanup, and define custom cache rules), or optimized performance for complex CI workflows, consider using [`gradle/actions/setup-gradle`](https://github.com/gradle/actions/tree/main/setup-gradle).
|
||||
|
||||
For setup details and a comprehensive overview of all available features, visit the [setup-gradle documentation](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md).
|
||||
|
||||
#### Caching maven dependencies
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'maven'
|
||||
cache-dependency-path: 'sub-project/pom.xml' # optional
|
||||
- name: Build with Maven
|
||||
run: mvn package --file pom.xml
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Maven resolves plugin dependencies lazily, so a cache created by a "thin" goal
|
||||
> (e.g. `mvn compile`) can be missing plugin dependencies that later
|
||||
> `test`/`verify`/`package` jobs then re-download on every run. See
|
||||
> [Ensuring the Maven cache is complete](docs/advanced-usage.md#ensuring-the-maven-cache-is-complete-plugin-dependencies)
|
||||
> for how to seed a complete cache.
|
||||
|
||||
#### Caching sbt dependencies
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: 'sbt'
|
||||
cache-dependency-path: | # optional
|
||||
sub-project/build.sbt
|
||||
sub-project/project/build.properties
|
||||
- name: Build with SBT
|
||||
run: sbt package
|
||||
```
|
||||
|
||||
#### Cache segment restore timeout
|
||||
Usually, cache gets downloaded in multiple segments of fixed sizes. Sometimes, a segment download gets stuck, which causes the workflow job to be stuck. The cache segment download timeout [was introduced](https://github.com/actions/toolkit/tree/main/packages/cache#cache-segment-restore-timeout) to solve this issue as it allows the segment download to get aborted and hence allows the job to proceed with a cache miss. The default value of the cache segment download timeout is set to 10 minutes and can be customized by specifying an environment variable named `SEGMENT_DOWNLOAD_TIMEOUT_MINS` with a timeout value in minutes.
|
||||
|
||||
```yaml
|
||||
env:
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: '5'
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
cache: gradle
|
||||
cache: 'gradle'
|
||||
- run: ./gradlew build --no-daemon
|
||||
```
|
||||
|
||||
## Multiple JDKs and Maven toolchains
|
||||
### Check latest
|
||||
|
||||
In the basic examples above, the `check-latest` flag defaults to `false`. When set to `false`, the action tries to first resolve a version of Java from the local tool cache on the runner. If unable to find a specific version in the cache, the action will download a version of Java. Use the default or set `check-latest` to `false` if you prefer a faster more consistent setup experience that prioritizes trying to use the cached versions at the expense of newer versions sometimes being available for download.
|
||||
|
||||
If `check-latest` is set to `true`, the action first checks if the cached version is the latest one. If the locally cached version is not the most up-to-date, the latest version of Java will be downloaded. Set `check-latest` to `true` if you want the most up-to-date version of Java to always be used. Setting `check-latest` to `true` has performance implications as downloading versions of Java is slower than using cached versions.
|
||||
|
||||
[GitHub-hosted runners](https://github.com/actions/runner-images) include Eclipse Temurin JDKs in their tool cache. Selecting Eclipse Temurin (`distribution: 'temurin'`) can save setup time by using a pre-installed JDK instead of downloading one. See the installed Java versions for [Ubuntu](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md#java), [Windows](https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md#java), and [macOS](https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#java).
|
||||
|
||||
For Java distributions that are not cached on Hosted images, `check-latest` always behaves as `true` and downloads Java on the fly. Check out [Hosted Tool Cache](docs/advanced-usage.md#Hosted-Tool-Cache) for more details about pre-cached Java versions.
|
||||
|
||||
Install multiple Java versions by providing a multiline `java-version` value. All configured JDKs are installed. The last one added to `PATH` becomes the default.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: |
|
||||
8
|
||||
11
|
||||
17
|
||||
21
|
||||
25
|
||||
distribution: 'temurin'
|
||||
java-version: '25'
|
||||
check-latest: true
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
Other installed JDKs are available through version-specific variables such as `JAVA_HOME_17_X64`. To use a specific version later in the job, set `JAVA_HOME` and prepend its `bin` directory to `PATH`.
|
||||
|
||||
`setup-java` writes a Maven Toolchains declaration for each installed JDK. When multiple JDKs are installed, the declaration contains all of them. Customize the generated toolchain values with `mvn-toolchain-id` and `mvn-toolchain-vendor`.
|
||||
|
||||
## Testing with a Java matrix
|
||||
|
||||
### Testing against different Java versions
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
java: ['8', '11', '17', '21', '25']
|
||||
name: Java ${{ matrix.java }}
|
||||
java: [ '8', '11', '17', '21', '25' ]
|
||||
name: Java ${{ matrix.Java }} sample
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
- name: Setup java
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: temurin
|
||||
distribution: '<distribution>'
|
||||
java-version: ${{ matrix.java }}
|
||||
- run: java --version
|
||||
- run: mvn verify
|
||||
```
|
||||
|
||||
## Publishing packages
|
||||
### Install multiple JDKs
|
||||
|
||||
`setup-java` generates Maven `settings.xml` and Maven Toolchains configuration. For Gradle publishing, it installs Java for the workflow; the Gradle build file remains responsible for reading credentials from environment variables.
|
||||
|
||||
### Maven
|
||||
All configured Java versions are added to the PATH. The last one added to the PATH (i.e., the last JDK set up by this action) will be used as the default and available globally. Other Java versions can be accessed through environment variables such as 'JAVA\_HOME\_{{ MAJOR\_VERSION }}\_{{ ARCHITECTURE }}'. To use a specific Java version, set the JAVA\_HOME environment variable accordingly and prepend its bin directory to the PATH to ensure it takes priority during execution.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '25'
|
||||
server-id: github
|
||||
server-username-env-var: GITHUB_ACTOR
|
||||
server-password-env-var: GITHUB_TOKEN
|
||||
- run: mvn --batch-mode deploy
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: '<distribution>'
|
||||
java-version: |
|
||||
8
|
||||
11
|
||||
15
|
||||
```
|
||||
|
||||
### GPG signing
|
||||
### Using Maven Toolchains
|
||||
In the example above multiple JDKs are installed for the same job. The result after the last JDK is installed is a Maven Toolchains declaration containing references to all three JDKs. The values for `id`, `version`, and `vendor` of the individual Toolchain entries are the given input values for `distribution` and `java-version` (`vendor` being the combination of `${distribution}_${java-version}`) by default.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '25'
|
||||
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
gpg-passphrase-env-var: GPG_PASSPHRASE
|
||||
- run: mvn --batch-mode deploy
|
||||
env:
|
||||
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||
```
|
||||
### Advanced Configuration
|
||||
|
||||
Maven GPG signing requires `maven-gpg-plugin` 3.2.0 or newer because `setup-java` passes the passphrase through `gpg.passphraseEnvName`.
|
||||
- [Selecting a Java distribution](docs/advanced-usage.md#Selecting-a-Java-distribution)
|
||||
- [Eclipse Temurin](docs/advanced-usage.md#Eclipse-Temurin)
|
||||
- [Adopt](docs/advanced-usage.md#Adopt)
|
||||
- [Zulu](docs/advanced-usage.md#Zulu)
|
||||
- [Liberica](docs/advanced-usage.md#Liberica)
|
||||
- [Liberica Native Image Kit](docs/advanced-usage.md#Liberica-Native-Image-Kit)
|
||||
- [Microsoft](docs/advanced-usage.md#Microsoft)
|
||||
- [Amazon Corretto](docs/advanced-usage.md#Amazon-Corretto)
|
||||
- [Oracle](docs/advanced-usage.md#Oracle)
|
||||
- [Alibaba Dragonwell](docs/advanced-usage.md#Alibaba-Dragonwell)
|
||||
- [SapMachine](docs/advanced-usage.md#SapMachine)
|
||||
- [GraalVM](docs/advanced-usage.md#GraalVM)
|
||||
- [JetBrains](docs/advanced-usage.md#JetBrains)
|
||||
- [Tencent Kona](docs/advanced-usage.md#Tencent-Kona)
|
||||
- [Installing custom Java package type](docs/advanced-usage.md#Installing-custom-Java-package-type)
|
||||
- [Installing custom Java architecture](docs/advanced-usage.md#Installing-custom-Java-architecture)
|
||||
- [Installing custom Java distribution from local file](docs/advanced-usage.md#Installing-Java-from-local-file)
|
||||
- [Testing against different Java distributions](docs/advanced-usage.md#Testing-against-different-Java-distributions)
|
||||
- [Testing against different platforms](docs/advanced-usage.md#Testing-against-different-platforms)
|
||||
- [Publishing using Apache Maven](docs/advanced-usage.md#Publishing-using-Apache-Maven)
|
||||
- [Maven transfer progress (download logs)](docs/advanced-usage.md#maven-transfer-progress-download-logs)
|
||||
- [Publishing using Gradle](docs/advanced-usage.md#Publishing-using-Gradle)
|
||||
- [Hosted Tool Cache](docs/advanced-usage.md#Hosted-Tool-Cache)
|
||||
- [Modifying Maven Toolchains](docs/advanced-usage.md#Modifying-Maven-Toolchains)
|
||||
- [Java Version File](docs/advanced-usage.md#Java-version-file)
|
||||
|
||||
## Recommended permissions
|
||||
|
||||
@@ -479,41 +444,10 @@ permissions:
|
||||
contents: read # access to check out code and install dependencies
|
||||
```
|
||||
|
||||
Publishing workflows may require additional permissions depending on the target registry.
|
||||
|
||||
## Advanced usage
|
||||
|
||||
See [advanced usage](docs/advanced-usage.md) for detailed examples:
|
||||
|
||||
- [Selecting a Java distribution](docs/advanced-usage.md#selecting-a-java-distribution)
|
||||
- [Installing custom Java package types](docs/advanced-usage.md#installing-custom-java-package-type)
|
||||
- [Package compatibility](docs/advanced-usage.md#package-compatibility)
|
||||
- [Ensuring the Maven cache is complete](docs/advanced-usage.md#ensuring-the-maven-cache-is-complete-plugin-dependencies)
|
||||
- [Caching JDK installations](docs/advanced-usage.md#caching-jdk-installations)
|
||||
- [Platform and architecture compatibility](docs/advanced-usage.md#platform-and-architecture-compatibility)
|
||||
- [Installing custom Java architecture](docs/advanced-usage.md#installing-custom-java-architecture)
|
||||
- [Installing a JDK without setting it as default](docs/advanced-usage.md#installing-jdk-without-setting-as-default)
|
||||
- [Installing Java from a local file](docs/advanced-usage.md#installing-java-from-local-file)
|
||||
- [Testing against different Java distributions](docs/advanced-usage.md#testing-against-different-java-distributions)
|
||||
- [Testing against different platforms](docs/advanced-usage.md#testing-against-different-platforms)
|
||||
- [Publishing using Apache Maven](docs/advanced-usage.md#publishing-using-apache-maven)
|
||||
- [Apache Maven with a settings path](docs/advanced-usage.md#apache-maven-with-a-settings-path)
|
||||
- [Maven transfer progress](docs/advanced-usage.md#maven-transfer-progress-download-logs)
|
||||
- [Java problem matcher](docs/advanced-usage.md#java-problem-matcher-compiler-annotations)
|
||||
- [Publishing using Gradle](docs/advanced-usage.md#publishing-using-gradle)
|
||||
- [Hosted tool cache](docs/advanced-usage.md#hosted-tool-cache)
|
||||
- [Modifying Maven Toolchains](docs/advanced-usage.md#modifying-maven-toolchains)
|
||||
- [Java version files](docs/advanced-usage.md#java-version-file)
|
||||
- [Self-signed certificates and internal CAs on GitHub Enterprise](docs/advanced-usage.md#self-signed-certificates-and-internal-cas-github-enterprise)
|
||||
|
||||
## License
|
||||
|
||||
The scripts and documentation in this project are released under the [MIT License](LICENSE).
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributions are welcome. See our [Contributor's Guide](docs/contributors.md).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
:wave: Be nice. See [our code of conduct](CODE_OF_CONDUCT.md)
|
||||
Contributions are welcome! See [Contributor's Guide](docs/contributors.md)
|
||||
|
||||
@@ -8,9 +8,6 @@ import {
|
||||
beforeAll,
|
||||
afterAll
|
||||
} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
// Mock @actions/cache before importing source modules
|
||||
const real_cache_module = await import('@actions/cache');
|
||||
@@ -63,9 +60,6 @@ const core = await import('@actions/core');
|
||||
const cache = await import('@actions/cache');
|
||||
const {run: cleanup} = await import('../src/cleanup-java.js');
|
||||
const util = await import('../src/util.js');
|
||||
const {registerJdk, buildJdkCacheKey} = await import('../src/jdk-cache.js');
|
||||
|
||||
const jdkTempRoots: string[] = [];
|
||||
|
||||
describe('cleanup', () => {
|
||||
let spyWarning: any;
|
||||
@@ -94,9 +88,6 @@ describe('cleanup', () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
while (jdkTempRoots.length) {
|
||||
fs.rmSync(jdkTempRoots.pop()!, {recursive: true, force: true});
|
||||
}
|
||||
resetState();
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
@@ -172,103 +163,6 @@ describe('cleanup', () => {
|
||||
|
||||
expect(spyCacheSave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('saves the JDK cache without dependency caching', async () => {
|
||||
const {key, path: jdkPath, state} = createRegisteredJdk();
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'cache-jdk' ? 'true' : ''
|
||||
);
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'jdk-caches' ? state : ''
|
||||
);
|
||||
spyCacheSave.mockResolvedValue(1);
|
||||
|
||||
await cleanup();
|
||||
|
||||
expect(spyCacheSave).toHaveBeenCalledWith([jdkPath], key);
|
||||
});
|
||||
|
||||
it('does not save a JDK cache when cache-jdk is disabled', async () => {
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'cache-jdk' ? 'false' : ''
|
||||
);
|
||||
|
||||
await cleanup();
|
||||
|
||||
expect(spyCacheSave).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['', '', false],
|
||||
['', 'true', true],
|
||||
['', 'false', false],
|
||||
['maven', '', true],
|
||||
['maven', 'true', true],
|
||||
['maven', 'false', false]
|
||||
])(
|
||||
'uses effective JDK caching for cache=%j and cache-jdk=%j',
|
||||
async (cacheInput, cacheJdkInput, expectedJdkSave) => {
|
||||
const {key: jdkKey, path: jdkPath, state} = createRegisteredJdk();
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) => {
|
||||
if (name === 'cache') return cacheInput;
|
||||
if (name === 'cache-jdk') return cacheJdkInput;
|
||||
return '';
|
||||
});
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'jdk-caches' ? state : ''
|
||||
);
|
||||
spyCacheSave.mockResolvedValue(1);
|
||||
|
||||
await cleanup();
|
||||
|
||||
const jdkSaveCalls = spyCacheSave.mock.calls.filter(
|
||||
([, key]) => key === jdkKey
|
||||
);
|
||||
expect(jdkSaveCalls).toHaveLength(expectedJdkSave ? 1 : 0);
|
||||
if (expectedJdkSave) {
|
||||
expect(spyCacheSave).toHaveBeenCalledWith([jdkPath], jdkKey);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
it('keeps saving the remaining JDK caches when one save fails', async () => {
|
||||
const first = createRegisteredJdk();
|
||||
const second = createRegisteredJdk('17.0.19+9');
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'cache-jdk' ? 'true' : ''
|
||||
);
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'jdk-caches' ? second.state : ''
|
||||
);
|
||||
spyCacheSave.mockImplementation(async (paths: string[]) => {
|
||||
if (paths[0] === first.path) {
|
||||
throw new Error('Unexpected save failure');
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
|
||||
expect(spyCacheSave).toHaveBeenCalledWith([first.path], first.key);
|
||||
expect(spyCacheSave).toHaveBeenCalledWith([second.path], second.key);
|
||||
expect(spyCoreError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not save a JDK installation that was replaced after registration', async () => {
|
||||
const {key, path: jdkPath, state, replace} = createRegisteredJdk();
|
||||
(core.getInput as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'cache-jdk' ? 'true' : ''
|
||||
);
|
||||
(core.getState as jest.Mock<any>).mockImplementation((name: string) =>
|
||||
name === 'jdk-caches' ? state : ''
|
||||
);
|
||||
spyCacheSave.mockResolvedValue(1);
|
||||
replace();
|
||||
|
||||
await cleanup();
|
||||
|
||||
expect(spyCacheSave).not.toHaveBeenCalledWith([jdkPath], key);
|
||||
});
|
||||
});
|
||||
|
||||
function resetState() {
|
||||
@@ -305,49 +199,3 @@ function createStateForSuccessfulRestoreWithWrapper(packageManager: string) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a real JDK installation in a temporary tool cache so the post-job
|
||||
* save sees the same installation identity that setup recorded.
|
||||
*/
|
||||
function createRegisteredJdk(version = '21.0.8+9') {
|
||||
const root = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'setup-java-cleanup-jdk-')
|
||||
);
|
||||
jdkTempRoots.push(root);
|
||||
const jdkPath = path.join(
|
||||
root,
|
||||
'Java_temurin_jdk',
|
||||
version.replace('+', '-')
|
||||
);
|
||||
const write = (marker: string) => {
|
||||
const architecturePath = path.join(jdkPath, 'x64');
|
||||
fs.rmSync(architecturePath, {recursive: true, force: true});
|
||||
fs.rmSync(`${architecturePath}.complete`, {force: true});
|
||||
fs.mkdirSync(architecturePath, {recursive: true});
|
||||
fs.writeFileSync(path.join(architecturePath, 'release'), marker);
|
||||
fs.writeFileSync(`${architecturePath}.complete`, marker);
|
||||
};
|
||||
write('installed');
|
||||
|
||||
const jdk = {
|
||||
distribution: 'temurin',
|
||||
packageType: 'jdk',
|
||||
architecture: 'x64',
|
||||
version,
|
||||
source: `sha256:${path.basename(root)}`,
|
||||
verification: 'unverified',
|
||||
path: jdkPath
|
||||
};
|
||||
registerJdk(jdk);
|
||||
const state = (
|
||||
(core.saveState as jest.Mock).mock.calls.at(-1) as string[]
|
||||
)[1];
|
||||
|
||||
return {
|
||||
key: buildJdkCacheKey(jdk),
|
||||
path: jdkPath,
|
||||
state,
|
||||
replace: () => write('replaced-by-a-later-step')
|
||||
};
|
||||
}
|
||||
|
||||
@@ -70,19 +70,6 @@ jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
}
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../src/jdk-cache.js', () => ({
|
||||
getJdkVerificationIdentity: jest.fn((verified: boolean, key?: string) =>
|
||||
verified ? (key ? 'verified:custom' : 'verified:bundled') : 'unverified'
|
||||
),
|
||||
registerJdk: jest.fn(),
|
||||
restoreJdk: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../src/jdk-resolution-cache.js', () => ({
|
||||
registerJdkResolution: jest.fn(),
|
||||
restoreJdkResolution: jest.fn()
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
@@ -99,8 +86,6 @@ jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
const core = await import('@actions/core');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const util = await import('../../src/util.js');
|
||||
const jdkCache = await import('../../src/jdk-cache.js');
|
||||
const jdkResolutionCache = await import('../../src/jdk-resolution-cache.js');
|
||||
const {JavaBase} = await import('../../src/distributions/base-installer.js');
|
||||
|
||||
class EmptyJavaBase extends JavaBase {
|
||||
@@ -351,10 +336,6 @@ describe('setupJava', () => {
|
||||
let spyCoreError: any;
|
||||
|
||||
beforeEach(() => {
|
||||
(jdkCache.getJdkVerificationIdentity as jest.Mock).mockImplementation(
|
||||
(verified: boolean, key?: string) =>
|
||||
verified ? (key ? 'verified:custom' : 'verified:bundled') : 'unverified'
|
||||
);
|
||||
spyGetToolcachePath = util.getToolcachePath as jest.Mock;
|
||||
spyGetToolcachePath.mockImplementation(
|
||||
(toolname: string, javaVersion: string, architecture: string) => {
|
||||
@@ -482,10 +463,8 @@ describe('setupJava', () => {
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
forceDownload: true,
|
||||
cacheJdk: true
|
||||
forceDownload: true
|
||||
});
|
||||
|
||||
const findInToolcache = jest.fn(() => ({
|
||||
version: actualJavaVersion,
|
||||
path: javaPathInstalled
|
||||
@@ -505,111 +484,6 @@ describe('setupJava', () => {
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith(
|
||||
`Resolved Java ${actualJavaVersion} from tool-cache`
|
||||
);
|
||||
expect(jdkCache.restoreJdk).not.toHaveBeenCalled();
|
||||
expect(jdkCache.registerJdk).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
version: actualJavaVersion,
|
||||
verification: 'unverified'
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[false, false, false, false],
|
||||
[false, true, true, true],
|
||||
[true, false, false, false],
|
||||
[true, true, false, true]
|
||||
])(
|
||||
'handles force-download=%s and cache-jdk=%s',
|
||||
async (forceDownload, cacheJdkEnabled, restores, registers) => {
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: actualJavaVersion,
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: true,
|
||||
forceDownload,
|
||||
cacheJdk: cacheJdkEnabled
|
||||
});
|
||||
(jdkCache.restoreJdk as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
expect(jdkCache.restoreJdk).toHaveBeenCalledTimes(restores ? 1 : 0);
|
||||
expect(jdkCache.registerJdk).toHaveBeenCalledTimes(registers ? 1 : 0);
|
||||
}
|
||||
);
|
||||
|
||||
it('restores the exact resolved JDK before downloading', async () => {
|
||||
const toolCachePath = path.join('toolcache');
|
||||
jest.replaceProperty(process, 'env', {
|
||||
...process.env,
|
||||
RUNNER_TOOL_CACHE: toolCachePath
|
||||
});
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: true,
|
||||
cacheJdk: true
|
||||
});
|
||||
const downloadTool = jest.spyOn(mockJavaBase as any, 'downloadTool');
|
||||
(jdkCache.restoreJdk as jest.Mock).mockResolvedValue(true);
|
||||
jest
|
||||
.spyOn(mockJavaBase as any, 'getRestoredJdkPath')
|
||||
.mockReturnValue(javaPathInstalled);
|
||||
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: actualJavaVersion,
|
||||
path: javaPathInstalled
|
||||
});
|
||||
|
||||
expect(jdkCache.restoreJdk).toHaveBeenCalledWith({
|
||||
distribution: 'Empty',
|
||||
packageType: 'jdk',
|
||||
architecture: 'x86',
|
||||
version: actualJavaVersion,
|
||||
source: `some/random_url/java/${actualJavaVersion}`,
|
||||
verification: 'unverified',
|
||||
path: path.join(toolCachePath, 'Java_Empty_jdk', actualJavaVersion)
|
||||
});
|
||||
expect(downloadTool).not.toHaveBeenCalled();
|
||||
expect(spyCoreInfo).not.toHaveBeenCalledWith('Trying to download...');
|
||||
// A restored entry is already stored under its key; it must not be
|
||||
// re-registered for a post-job save.
|
||||
expect(jdkCache.registerJdk).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('registers the downloaded JDK identity after a JDK cache miss', async () => {
|
||||
const toolCachePath = path.join('toolcache');
|
||||
jest.replaceProperty(process, 'env', {
|
||||
...process.env,
|
||||
RUNNER_TOOL_CACHE: toolCachePath
|
||||
});
|
||||
mockJavaBase = new EmptyJavaBase({
|
||||
version: '11',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: true,
|
||||
cacheJdk: true
|
||||
});
|
||||
(jdkCache.restoreJdk as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
const expectedIdentity = {
|
||||
distribution: 'Empty',
|
||||
packageType: 'jdk',
|
||||
architecture: 'x86',
|
||||
version: actualJavaVersion,
|
||||
source: `some/random_url/java/${actualJavaVersion}`,
|
||||
verification: 'unverified',
|
||||
path: path.join(toolCachePath, 'Java_Empty_jdk', actualJavaVersion)
|
||||
};
|
||||
expect(jdkCache.restoreJdk).toHaveBeenCalledWith(expectedIdentity);
|
||||
// Registration happens after the installation exists, so the post-job save
|
||||
// can detect a later step replacing it.
|
||||
expect(jdkCache.registerJdk).toHaveBeenCalledWith(expectedIdentity);
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith('Trying to download...');
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -955,155 +829,6 @@ describe('setupJava', () => {
|
||||
'Installing Java 11.0.9 (not setting as default)'
|
||||
);
|
||||
});
|
||||
|
||||
describe('resolution cache', () => {
|
||||
// 11.0.9 is not in the mocked tool-cache, so the tool-cache short-circuit
|
||||
// misses and the release has to be resolved, exactly as it does for every
|
||||
// distribution that is not preinstalled on hosted runners.
|
||||
const options: JavaInstallerOptions = {
|
||||
version: '11.0.9',
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
cacheJdk: true
|
||||
};
|
||||
const cachedRelease = {
|
||||
version: '11.0.9',
|
||||
url: 'https://example.com/java/11.0.9'
|
||||
};
|
||||
|
||||
const expectedRequest = {
|
||||
distribution: 'Empty',
|
||||
packageType: 'jdk',
|
||||
architecture: 'x86',
|
||||
versionSpec: '11.0.9',
|
||||
stable: true
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
(jdkCache.restoreJdk as jest.Mock).mockResolvedValue(false);
|
||||
(jdkResolutionCache.restoreJdkResolution as jest.Mock).mockResolvedValue(
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
it('skips the metadata API on a fresh cached resolution', async () => {
|
||||
mockJavaBase = new EmptyJavaBase(options);
|
||||
const findPackageForDownload = jest.spyOn(
|
||||
mockJavaBase as any,
|
||||
'findPackageForDownload'
|
||||
);
|
||||
(jdkResolutionCache.restoreJdkResolution as jest.Mock).mockResolvedValue({
|
||||
release: cachedRelease,
|
||||
fresh: true
|
||||
});
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
expect(jdkResolutionCache.restoreJdkResolution).toHaveBeenCalledWith(
|
||||
expectedRequest
|
||||
);
|
||||
expect(findPackageForDownload).not.toHaveBeenCalled();
|
||||
expect(jdkResolutionCache.registerJdkResolution).not.toHaveBeenCalled();
|
||||
expect(spyCoreInfo).toHaveBeenCalledWith(
|
||||
'Resolved Empty 11.0.9 from the resolution cache'
|
||||
);
|
||||
});
|
||||
|
||||
it('re-resolves and records the release on a miss', async () => {
|
||||
mockJavaBase = new EmptyJavaBase(options);
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
expect(jdkResolutionCache.registerJdkResolution).toHaveBeenCalledWith(
|
||||
expectedRequest,
|
||||
{version: '11.0.9', url: 'some/random_url/java/11.0.9'}
|
||||
);
|
||||
});
|
||||
|
||||
it('re-resolves when the cached resolution is stale', async () => {
|
||||
mockJavaBase = new EmptyJavaBase(options);
|
||||
const findPackageForDownload = jest.spyOn(
|
||||
mockJavaBase as any,
|
||||
'findPackageForDownload'
|
||||
);
|
||||
(jdkResolutionCache.restoreJdkResolution as jest.Mock).mockResolvedValue({
|
||||
release: cachedRelease,
|
||||
fresh: false
|
||||
});
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
expect(findPackageForDownload).toHaveBeenCalled();
|
||||
expect(jdkResolutionCache.registerJdkResolution).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('falls back to a stale resolution when the metadata API fails', async () => {
|
||||
mockJavaBase = new EmptyJavaBase(options);
|
||||
const downloadTool = jest
|
||||
.spyOn(mockJavaBase as any, 'downloadTool')
|
||||
.mockResolvedValue({version: '11.0.9', path: javaPathInstalled});
|
||||
jest
|
||||
.spyOn(mockJavaBase as any, 'findPackageForDownload')
|
||||
.mockRejectedValue(new Error('503 Service Unavailable'));
|
||||
(jdkResolutionCache.restoreJdkResolution as jest.Mock).mockResolvedValue({
|
||||
release: cachedRelease,
|
||||
fresh: false
|
||||
});
|
||||
|
||||
await expect(mockJavaBase.setupJava()).resolves.toEqual({
|
||||
version: '11.0.9',
|
||||
path: javaPathInstalled
|
||||
});
|
||||
|
||||
expect(downloadTool).toHaveBeenCalledWith(cachedRelease);
|
||||
expect(jdkResolutionCache.registerJdkResolution).not.toHaveBeenCalled();
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
expect.stringContaining('falling back to the cached resolution')
|
||||
);
|
||||
});
|
||||
|
||||
it('fails when the metadata API fails and nothing was cached', async () => {
|
||||
mockJavaBase = new EmptyJavaBase(options);
|
||||
jest
|
||||
.spyOn(mockJavaBase as any, 'findPackageForDownload')
|
||||
.mockRejectedValue(new Error('503 Service Unavailable'));
|
||||
|
||||
await expect(mockJavaBase.setupJava()).rejects.toThrow(
|
||||
'503 Service Unavailable'
|
||||
);
|
||||
});
|
||||
|
||||
it('does not record a floating release', async () => {
|
||||
mockJavaBase = new EmptyJavaBase(options);
|
||||
jest
|
||||
.spyOn(mockJavaBase as any, 'findPackageForDownload')
|
||||
.mockResolvedValue({
|
||||
version: '11.0.9',
|
||||
url: 'https://example.com/java/11/latest/jdk-11.tar.gz',
|
||||
checksum: {algorithm: 'sha256', value: 'abc'},
|
||||
floating: true
|
||||
});
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
expect(jdkResolutionCache.registerJdkResolution).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['cache-jdk is disabled', {cacheJdk: false}],
|
||||
['check-latest is enabled', {checkLatest: true}],
|
||||
['force-download is enabled', {forceDownload: true}],
|
||||
['java-version is "latest"', {version: 'latest'}]
|
||||
])('is bypassed when %s', async (_name, overrides) => {
|
||||
mockJavaBase = new EmptyJavaBase({...options, ...overrides});
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
expect(jdkResolutionCache.restoreJdkResolution).not.toHaveBeenCalled();
|
||||
expect(jdkResolutionCache.registerJdkResolution).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('downloadAndVerify', () => {
|
||||
|
||||
@@ -421,8 +421,7 @@ describe('GraalVMDistribution', () => {
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://download.oracle.com/graalvm/17/archive/graalvm-jdk-17.0.5_linux-x64_bin.tar.gz.sha256'
|
||||
},
|
||||
floating: false
|
||||
}
|
||||
});
|
||||
expect(mockHttpClient.head).toHaveBeenCalledWith(result.url);
|
||||
expect(mockHttpClient.get).toHaveBeenCalledWith(`${result.url}.sha256`);
|
||||
@@ -444,10 +443,7 @@ describe('GraalVMDistribution', () => {
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz.sha256'
|
||||
},
|
||||
// A major-only range resolves to the floating `/latest/` URL, so the
|
||||
// release must not be reused by a later job.
|
||||
floating: true
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -496,8 +492,7 @@ describe('GraalVMDistribution', () => {
|
||||
value: 'a'.repeat(64),
|
||||
source:
|
||||
'https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz.sha256'
|
||||
},
|
||||
floating: true
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@ import fs from 'fs';
|
||||
|
||||
import path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import os from 'os';
|
||||
|
||||
const realStatSync = fs.statSync;
|
||||
|
||||
// Mock @actions/core before importing source modules that depend on it
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
@@ -57,12 +54,6 @@ jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
evaluateVersions: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../src/jdk-cache.js', () => ({
|
||||
getJdkVerificationIdentity: jest.fn(() => 'unverified'),
|
||||
registerJdk: jest.fn(),
|
||||
restoreJdk: jest.fn()
|
||||
}));
|
||||
|
||||
const real_util_module = await import('../../src/util.js');
|
||||
jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
...real_util_module,
|
||||
@@ -79,7 +70,6 @@ jest.unstable_mockModule('../../src/util.js', () => ({
|
||||
const core = await import('@actions/core');
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const util = await import('../../src/util.js');
|
||||
const jdkCache = await import('../../src/jdk-cache.js');
|
||||
const {LocalDistribution} =
|
||||
await import('../../src/distributions/local/installer.js');
|
||||
|
||||
@@ -105,9 +95,6 @@ describe('setupJava', () => {
|
||||
const expectedJdkFile = 'JavaLocalJdkFile';
|
||||
|
||||
beforeEach(() => {
|
||||
(jdkCache.getJdkVerificationIdentity as jest.Mock).mockReturnValue(
|
||||
'unverified'
|
||||
);
|
||||
spyGetToolcachePath = util.getToolcachePath as jest.Mock;
|
||||
spyGetToolcachePath.mockImplementation(
|
||||
(toolname: string, javaVersion: string, architecture: string) => {
|
||||
@@ -244,72 +231,6 @@ describe('setupJava', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[false, true, true],
|
||||
[true, false, true]
|
||||
])(
|
||||
'handles jdkfile caching with force-download=%s',
|
||||
async (forceDownload, restores, registers) => {
|
||||
const temporaryDirectory = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'setup-java-local-cache-')
|
||||
);
|
||||
const jdkFile = path.join(temporaryDirectory, 'java.tar.gz');
|
||||
fs.writeFileSync(jdkFile, 'jdk archive');
|
||||
spyGetToolcachePath.mockReturnValue('');
|
||||
spyFsStat.mockImplementation((file: string) => realStatSync(file));
|
||||
(jdkCache.restoreJdk as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
try {
|
||||
mockJavaBase = new LocalDistribution(
|
||||
{
|
||||
version: actualJavaVersion,
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
forceDownload,
|
||||
cacheJdk: true
|
||||
},
|
||||
jdkFile
|
||||
);
|
||||
|
||||
await mockJavaBase.setupJava();
|
||||
|
||||
expect(jdkCache.restoreJdk).toHaveBeenCalledTimes(restores ? 1 : 0);
|
||||
expect(jdkCache.registerJdk).toHaveBeenCalledTimes(registers ? 1 : 0);
|
||||
expect(
|
||||
(jdkCache.restoreJdk as jest.Mock).mock.calls[0]?.[0] ??
|
||||
(jdkCache.registerJdk as jest.Mock).mock.calls[0]?.[0]
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
distribution: 'jdkfile',
|
||||
version: actualJavaVersion,
|
||||
verification: 'unverified'
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
fs.rmSync(temporaryDirectory, {recursive: true});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
it('rejects signature verification for jdkfile archives', async () => {
|
||||
mockJavaBase = new LocalDistribution(
|
||||
{
|
||||
version: actualJavaVersion,
|
||||
architecture: 'x86',
|
||||
packageType: 'jdk',
|
||||
checkLatest: false,
|
||||
verifySignature: true
|
||||
},
|
||||
expectedJdkFile
|
||||
);
|
||||
|
||||
await expect(mockJavaBase.setupJava()).rejects.toThrow(
|
||||
"Input 'verify-signature' is not supported for distribution 'jdkfile'."
|
||||
);
|
||||
expect(spyGetToolcachePath).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("java is resolved from toolcache, jdkfile doesn't exist", async () => {
|
||||
const inputs = {
|
||||
version: actualJavaVersion,
|
||||
|
||||
@@ -142,9 +142,6 @@ describe('findPackageForDownload', () => {
|
||||
.replace('{{OS_TYPE}}', osType)
|
||||
.replace('{{ARCHIVE_TYPE}}', archiveType);
|
||||
expect(result.url).toBe(url);
|
||||
// Only the `/latest/` path serves changing contents, so only it must be
|
||||
// excluded from the resolution cache.
|
||||
expect(result.floating).toBe(url.includes('/latest/'));
|
||||
});
|
||||
|
||||
it('fetches the authoritative sha256 checksum for the resolved archive', async () => {
|
||||
|
||||
@@ -22,7 +22,7 @@ describe('java-package published contract', () => {
|
||||
? content.match(/ {2}java-package:\n(?: {4}.+\n)+/)?.[0]
|
||||
: content
|
||||
.split('\n')
|
||||
.find(line => line.includes('| `java-package` |'));
|
||||
.find(line => line.includes('- `java-package`:'));
|
||||
|
||||
expect(contractLine).toBeDefined();
|
||||
for (const packageType of allPackageTypes) {
|
||||
|
||||
@@ -1,325 +0,0 @@
|
||||
import {jest, describe, it, expect, beforeEach, afterEach} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
jest.unstable_mockModule('@actions/cache', () => ({
|
||||
restoreCache: jest.fn(),
|
||||
saveCache: jest.fn(),
|
||||
ReserveCacheError: class ReserveCacheError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = 'ReserveCacheError';
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../src/cache-feature.js', () => ({
|
||||
isCacheFeatureAvailable: jest.fn()
|
||||
}));
|
||||
|
||||
const cache = await import('@actions/cache');
|
||||
const core = await import('@actions/core');
|
||||
const cacheFeature = await import('../src/cache-feature.js');
|
||||
const {
|
||||
buildJdkCacheKey,
|
||||
getJdkVerificationIdentity,
|
||||
registerJdk,
|
||||
restoreJdk,
|
||||
saveJdkCaches
|
||||
} = await import('../src/jdk-cache.js');
|
||||
|
||||
const jdk = {
|
||||
distribution: 'temurin',
|
||||
packageType: 'jdk',
|
||||
architecture: 'x64',
|
||||
version: '21.0.8+9',
|
||||
source: 'sha256:abc123',
|
||||
verification: 'unverified',
|
||||
path: '/toolcache/Java_temurin_jdk/21.0.8-9'
|
||||
};
|
||||
|
||||
describe('JDK cache', () => {
|
||||
const tempRoots: string[] = [];
|
||||
|
||||
const createInstallation = (marker = 'a'): string => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-java-jdk-'));
|
||||
tempRoots.push(root);
|
||||
const jdkPath = path.join(root, 'Java_temurin_jdk', '21.0.8-9');
|
||||
writeInstallation(jdkPath, marker);
|
||||
return jdkPath;
|
||||
};
|
||||
|
||||
const writeInstallation = (jdkPath: string, marker: string): void => {
|
||||
const architecturePath = path.join(jdkPath, 'x64');
|
||||
fs.rmSync(architecturePath, {recursive: true, force: true});
|
||||
fs.rmSync(`${architecturePath}.complete`, {force: true});
|
||||
fs.mkdirSync(path.join(architecturePath, 'bin'), {recursive: true});
|
||||
fs.writeFileSync(path.join(architecturePath, 'bin', 'java'), marker);
|
||||
fs.writeFileSync(`${architecturePath}.complete`, marker);
|
||||
};
|
||||
|
||||
const lastState = (): string =>
|
||||
((core.saveState as jest.Mock).mock.calls.at(-1) as string[])[1];
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
(cacheFeature.isCacheFeatureAvailable as jest.Mock).mockReturnValue(true);
|
||||
process.env['RUNNER_OS'] = 'Linux';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
delete process.env['RUNNER_OS'];
|
||||
while (tempRoots.length) {
|
||||
fs.rmSync(tempRoots.pop()!, {recursive: true, force: true});
|
||||
}
|
||||
});
|
||||
|
||||
it('builds distinct keys for incompatible JDK identities', () => {
|
||||
const key = buildJdkCacheKey(jdk);
|
||||
|
||||
expect(key).toMatch(/^setup-java-jdk-v1-Linux-x64-[a-f0-9]{64}$/);
|
||||
expect(buildJdkCacheKey({...jdk, architecture: 'aarch64'})).not.toBe(key);
|
||||
expect(buildJdkCacheKey({...jdk, distribution: 'zulu'})).not.toBe(key);
|
||||
expect(buildJdkCacheKey({...jdk, packageType: 'jre'})).not.toBe(key);
|
||||
expect(buildJdkCacheKey({...jdk, version: '21.0.7+6'})).not.toBe(key);
|
||||
expect(buildJdkCacheKey({...jdk, source: 'sha256:def456'})).not.toBe(key);
|
||||
});
|
||||
|
||||
it('preserves canonical runner OS values and separates operating systems', () => {
|
||||
process.env['RUNNER_OS'] = 'Linux';
|
||||
const linux = buildJdkCacheKey(jdk);
|
||||
process.env['RUNNER_OS'] = 'Windows';
|
||||
const windows = buildJdkCacheKey(jdk);
|
||||
process.env['RUNNER_OS'] = 'macOS';
|
||||
const macos = buildJdkCacheKey(jdk);
|
||||
|
||||
expect(new Set([linux, windows, macos])).toHaveProperty('size', 3);
|
||||
expect(linux).toMatch(/^setup-java-jdk-v1-Linux-x64-/);
|
||||
expect(windows).toMatch(/^setup-java-jdk-v1-Windows-x64-/);
|
||||
expect(macos).toMatch(/^setup-java-jdk-v1-macOS-x64-/);
|
||||
});
|
||||
|
||||
it('falls back to process.platform without RUNNER_OS', () => {
|
||||
delete process.env['RUNNER_OS'];
|
||||
|
||||
expect(buildJdkCacheKey(jdk)).toMatch(
|
||||
new RegExp(`^setup-java-jdk-v1-${process.platform}-x64-`)
|
||||
);
|
||||
});
|
||||
|
||||
it('separates unverified, bundled-key, and custom-key caches', () => {
|
||||
const unverified = getJdkVerificationIdentity(false);
|
||||
const bundled = getJdkVerificationIdentity(true);
|
||||
const customA = getJdkVerificationIdentity(
|
||||
true,
|
||||
'-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nkey-a\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n'
|
||||
);
|
||||
const customANormalized = getJdkVerificationIdentity(
|
||||
true,
|
||||
'-----BEGIN PGP PUBLIC KEY BLOCK-----\nkey-a\n-----END PGP PUBLIC KEY BLOCK-----'
|
||||
);
|
||||
const customB = getJdkVerificationIdentity(true, 'different-key');
|
||||
|
||||
expect(new Set([unverified, bundled, customA, customB])).toHaveProperty(
|
||||
'size',
|
||||
4
|
||||
);
|
||||
expect(customA).toBe(customANormalized);
|
||||
expect(customA).not.toContain('key-a');
|
||||
expect(
|
||||
new Set(
|
||||
[unverified, bundled, customA, customB].map(verification =>
|
||||
buildJdkCacheKey({...jdk, verification})
|
||||
)
|
||||
)
|
||||
).toHaveProperty('size', 4);
|
||||
});
|
||||
|
||||
it('restores and records an exact JDK cache hit', async () => {
|
||||
(cache.restoreCache as jest.Mock).mockResolvedValue(buildJdkCacheKey(jdk));
|
||||
jest.spyOn(fs, 'existsSync').mockReturnValue(true);
|
||||
|
||||
await expect(restoreJdk(jdk)).resolves.toBe(true);
|
||||
|
||||
expect(cache.restoreCache).toHaveBeenCalledWith(
|
||||
[jdk.path],
|
||||
buildJdkCacheKey(jdk)
|
||||
);
|
||||
const architecturePath = path.join(jdk.path, 'x64');
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(architecturePath);
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(`${architecturePath}.complete`);
|
||||
expect(core.saveState).toHaveBeenCalledWith(
|
||||
'jdk-caches',
|
||||
expect.stringContaining(buildJdkCacheKey(jdk))
|
||||
);
|
||||
});
|
||||
|
||||
it('falls back to download when restoration fails', async () => {
|
||||
(cache.restoreCache as jest.Mock).mockRejectedValue(
|
||||
new Error('cache unavailable')
|
||||
);
|
||||
|
||||
await expect(restoreJdk(jdk)).resolves.toBe(false);
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
'Failed to restore JDK cache: cache unavailable'
|
||||
);
|
||||
});
|
||||
|
||||
it('saves a downloaded JDK registered after installation', async () => {
|
||||
const jdkPath = createInstallation();
|
||||
const installed = {...jdk, path: jdkPath};
|
||||
const key = buildJdkCacheKey(installed);
|
||||
(cache.restoreCache as jest.Mock).mockResolvedValue(undefined);
|
||||
|
||||
await restoreJdk(installed);
|
||||
registerJdk(installed);
|
||||
(core.getState as jest.Mock).mockReturnValue(lastState());
|
||||
(cache.saveCache as jest.Mock).mockResolvedValue(1);
|
||||
|
||||
await saveJdkCaches();
|
||||
|
||||
expect(cache.saveCache).toHaveBeenCalledWith([jdkPath], key);
|
||||
});
|
||||
|
||||
it('does not save an installation that was replaced after registration', async () => {
|
||||
const jdkPath = createInstallation();
|
||||
const installed = {...jdk, path: jdkPath};
|
||||
const key = buildJdkCacheKey(installed);
|
||||
|
||||
registerJdk(installed);
|
||||
(core.getState as jest.Mock).mockReturnValue(lastState());
|
||||
writeInstallation(jdkPath, 'replaced-by-a-later-step');
|
||||
|
||||
await saveJdkCaches();
|
||||
|
||||
expect(cache.saveCache).not.toHaveBeenCalledWith([jdkPath], key);
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
expect.stringContaining('was replaced after it was registered')
|
||||
);
|
||||
});
|
||||
|
||||
it('saves only the key matching the installation that occupies the path', async () => {
|
||||
const jdkPath = createInstallation();
|
||||
const verified = {...jdk, path: jdkPath, verification: 'verified:bundled'};
|
||||
const unverified = {...jdk, path: jdkPath};
|
||||
|
||||
registerJdk(verified);
|
||||
writeInstallation(jdkPath, 'force-downloaded-without-verification');
|
||||
registerJdk(unverified);
|
||||
(core.getState as jest.Mock).mockReturnValue(lastState());
|
||||
(cache.saveCache as jest.Mock).mockResolvedValue(1);
|
||||
|
||||
await saveJdkCaches();
|
||||
|
||||
expect(cache.saveCache).not.toHaveBeenCalledWith(
|
||||
[jdkPath],
|
||||
buildJdkCacheKey(verified)
|
||||
);
|
||||
expect(cache.saveCache).toHaveBeenCalledWith(
|
||||
[jdkPath],
|
||||
buildJdkCacheKey(unverified)
|
||||
);
|
||||
});
|
||||
|
||||
it('does not save a path that was never registered as installed', async () => {
|
||||
const jdkPath = createInstallation();
|
||||
const installed = {...jdk, path: jdkPath};
|
||||
(cache.restoreCache as jest.Mock).mockResolvedValue(undefined);
|
||||
|
||||
await restoreJdk(installed);
|
||||
(core.getState as jest.Mock).mockReturnValue(lastState());
|
||||
|
||||
await saveJdkCaches();
|
||||
|
||||
expect(cache.saveCache).not.toHaveBeenCalledWith(
|
||||
[jdkPath],
|
||||
buildJdkCacheKey(installed)
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps saving the remaining JDK caches when one save fails', async () => {
|
||||
const failingPath = createInstallation();
|
||||
const succeedingPath = createInstallation();
|
||||
const failing = {...jdk, path: failingPath};
|
||||
const succeeding = {...jdk, path: succeedingPath, version: '17.0.19+9'};
|
||||
|
||||
registerJdk(failing);
|
||||
registerJdk(succeeding);
|
||||
(core.getState as jest.Mock).mockReturnValue(lastState());
|
||||
(cache.saveCache as jest.Mock).mockImplementation(
|
||||
async (paths: unknown) => {
|
||||
if ((paths as string[])[0] === failingPath) {
|
||||
throw new Error('cache service unavailable');
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
);
|
||||
|
||||
await expect(saveJdkCaches()).resolves.toBeUndefined();
|
||||
|
||||
expect(cache.saveCache).toHaveBeenCalledWith(
|
||||
[succeedingPath],
|
||||
buildJdkCacheKey(succeeding)
|
||||
);
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
expect.stringContaining('cache service unavailable')
|
||||
);
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
`JDK cache saved with the key: ${buildJdkCacheKey(succeeding)}`
|
||||
);
|
||||
});
|
||||
|
||||
it('reports a reserved cache key without failing the remaining saves', async () => {
|
||||
const reservedPath = createInstallation();
|
||||
const reserved = {...jdk, path: reservedPath};
|
||||
|
||||
registerJdk(reserved);
|
||||
(core.getState as jest.Mock).mockReturnValue(lastState());
|
||||
(cache.saveCache as jest.Mock).mockRejectedValue(
|
||||
new cache.ReserveCacheError('Unable to reserve cache')
|
||||
);
|
||||
|
||||
await expect(saveJdkCaches()).resolves.toBeUndefined();
|
||||
|
||||
expect(core.info).toHaveBeenCalledWith('Unable to reserve cache');
|
||||
});
|
||||
|
||||
it('registers a force-downloaded JDK without restoring it', () => {
|
||||
const jdkPath = createInstallation();
|
||||
registerJdk({...jdk, path: jdkPath});
|
||||
|
||||
expect(cache.restoreCache).not.toHaveBeenCalled();
|
||||
expect(core.saveState).toHaveBeenCalledWith(
|
||||
'jdk-caches',
|
||||
expect.stringContaining(buildJdkCacheKey({...jdk, path: jdkPath}))
|
||||
);
|
||||
});
|
||||
|
||||
it('does not save an exact JDK cache hit again', async () => {
|
||||
const key = buildJdkCacheKey(jdk);
|
||||
(core.getState as jest.Mock).mockReturnValue(
|
||||
JSON.stringify([
|
||||
{
|
||||
key,
|
||||
path: jdk.path,
|
||||
architecture: jdk.architecture,
|
||||
matchedKey: key
|
||||
}
|
||||
])
|
||||
);
|
||||
|
||||
await saveJdkCaches();
|
||||
|
||||
expect(cache.saveCache).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,387 +0,0 @@
|
||||
import {jest, describe, it, expect, beforeEach, afterEach} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
jest.unstable_mockModule('@actions/cache', () => ({
|
||||
isFeatureAvailable: jest.fn(),
|
||||
restoreCache: jest.fn(),
|
||||
saveCache: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
getState: jest.fn()
|
||||
}));
|
||||
|
||||
const cache = await import('@actions/cache');
|
||||
const core = await import('@actions/core');
|
||||
const {restoreJdkResolution, registerJdkResolution, saveJdkResolutionCaches} =
|
||||
await import('../src/jdk-resolution-cache.js');
|
||||
|
||||
const request = {
|
||||
distribution: 'Temurin-Hotspot',
|
||||
packageType: 'jdk',
|
||||
architecture: 'x64',
|
||||
versionSpec: '21',
|
||||
stable: true
|
||||
};
|
||||
|
||||
const release = {
|
||||
version: '21.0.8+9',
|
||||
url: 'https://example.com/jdk-21.0.8.tar.gz',
|
||||
checksum: {algorithm: 'sha256' as const, value: 'abc123'}
|
||||
};
|
||||
|
||||
const WEEK = 7 * 24 * 60 * 60 * 1000;
|
||||
const bucket = () =>
|
||||
new Date(Math.floor(Date.now() / WEEK) * WEEK).toISOString().slice(0, 10);
|
||||
|
||||
describe('JDK resolution cache', () => {
|
||||
const tempRoots: string[] = [];
|
||||
let originalTemp: string | undefined;
|
||||
let originalOs: string | undefined;
|
||||
|
||||
const createRunnerTemp = (): string => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-java-res-'));
|
||||
tempRoots.push(root);
|
||||
process.env['RUNNER_TEMP'] = root;
|
||||
return root;
|
||||
};
|
||||
|
||||
/** Emulates the cache service materializing the entry at the requested path. */
|
||||
const restoreWith = (contents: string, matchedKey: string) => {
|
||||
jest
|
||||
.mocked(cache.restoreCache)
|
||||
.mockImplementation(async (paths: string[]) => {
|
||||
fs.mkdirSync(paths[0], {recursive: true});
|
||||
fs.writeFileSync(path.join(paths[0], 'release.json'), contents);
|
||||
return matchedKey;
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
originalTemp = process.env['RUNNER_TEMP'];
|
||||
originalOs = process.env['RUNNER_OS'];
|
||||
process.env['RUNNER_OS'] = 'Linux';
|
||||
jest.mocked(cache.isFeatureAvailable).mockReturnValue(true);
|
||||
jest.mocked(cache.restoreCache).mockResolvedValue(undefined);
|
||||
jest.mocked(cache.saveCache).mockResolvedValue(1);
|
||||
jest.mocked(core.getState).mockReturnValue('');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env['RUNNER_TEMP'] = originalTemp;
|
||||
process.env['RUNNER_OS'] = originalOs;
|
||||
if (originalTemp === undefined) {
|
||||
delete process.env['RUNNER_TEMP'];
|
||||
}
|
||||
if (originalOs === undefined) {
|
||||
delete process.env['RUNNER_OS'];
|
||||
}
|
||||
while (tempRoots.length > 0) {
|
||||
fs.rmSync(tempRoots.pop()!, {recursive: true, force: true});
|
||||
}
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('restoreJdkResolution', () => {
|
||||
it('looks the entry up with a bucket-independent path', async () => {
|
||||
const runnerTemp = createRunnerTemp();
|
||||
await restoreJdkResolution(request);
|
||||
|
||||
const [paths, primaryKey, restoreKeys] = jest.mocked(cache.restoreCache)
|
||||
.mock.calls[0] as [string[], string, string[]];
|
||||
expect(paths).toHaveLength(1);
|
||||
expect(
|
||||
paths[0].startsWith(path.join(runnerTemp, 'setup-java-jdk-resolution'))
|
||||
).toBe(true);
|
||||
expect(paths[0]).not.toContain(bucket());
|
||||
expect(primaryKey).toBe(`${restoreKeys[0]}${bucket()}`);
|
||||
expect(restoreKeys[0]).toMatch(
|
||||
/^setup-java-jdkres-v1-Linux-x64-[0-9a-f]{64}-$/
|
||||
);
|
||||
});
|
||||
|
||||
it('holds the key steady for a week and then rolls it', async () => {
|
||||
createRunnerTemp();
|
||||
const nowSpy = jest.spyOn(Date, 'now');
|
||||
const keyAt = async (ms: number) => {
|
||||
nowSpy.mockReturnValue(ms);
|
||||
await restoreJdkResolution(request);
|
||||
return jest.mocked(cache.restoreCache).mock.calls.at(-1)![1] as string;
|
||||
};
|
||||
|
||||
// A window boundary, so the offsets below are unambiguous.
|
||||
const windowStart = 2900 * WEEK;
|
||||
|
||||
const start = await keyAt(windowStart);
|
||||
const sameWindow = await keyAt(windowStart + 6 * 24 * 60 * 60 * 1000);
|
||||
const nextWindow = await keyAt(windowStart + WEEK);
|
||||
|
||||
expect(sameWindow).toBe(start);
|
||||
expect(nextWindow).not.toBe(start);
|
||||
nowSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('reports a hit on the current bucket as fresh', async () => {
|
||||
createRunnerTemp();
|
||||
const key = `setup-java-jdkres-v1-Linux-x64-${'0'.repeat(64)}-${bucket()}`;
|
||||
restoreWith(JSON.stringify(release), key);
|
||||
|
||||
// The key the module computes is the one it passes to restoreCache, so
|
||||
// echo it back to emulate an exact hit.
|
||||
jest
|
||||
.mocked(cache.restoreCache)
|
||||
.mockImplementation(async (paths: string[], primaryKey: string) => {
|
||||
fs.mkdirSync(paths[0], {recursive: true});
|
||||
fs.writeFileSync(
|
||||
path.join(paths[0], 'release.json'),
|
||||
JSON.stringify(release)
|
||||
);
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const restored = await restoreJdkResolution(request);
|
||||
expect(restored?.fresh).toBe(true);
|
||||
expect(restored?.release).toEqual(release);
|
||||
});
|
||||
|
||||
it('reports a hit on an older bucket as stale', async () => {
|
||||
createRunnerTemp();
|
||||
restoreWith(JSON.stringify(release), 'setup-java-jdkres-v1-old');
|
||||
|
||||
const restored = await restoreJdkResolution(request);
|
||||
expect(restored?.fresh).toBe(false);
|
||||
expect(restored?.release).toEqual(release);
|
||||
});
|
||||
|
||||
it('returns nothing when the entry is missing', async () => {
|
||||
createRunnerTemp();
|
||||
await expect(restoreJdkResolution(request)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns nothing when the cache service is unavailable', async () => {
|
||||
createRunnerTemp();
|
||||
jest.mocked(cache.isFeatureAvailable).mockReturnValue(false);
|
||||
|
||||
await expect(restoreJdkResolution(request)).resolves.toBeUndefined();
|
||||
expect(cache.restoreCache).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns nothing when RUNNER_TEMP is not set', async () => {
|
||||
delete process.env['RUNNER_TEMP'];
|
||||
|
||||
await expect(restoreJdkResolution(request)).resolves.toBeUndefined();
|
||||
expect(cache.restoreCache).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not fail the job when the restore throws', async () => {
|
||||
createRunnerTemp();
|
||||
jest
|
||||
.mocked(cache.restoreCache)
|
||||
.mockRejectedValue(new Error('service unavailable'));
|
||||
|
||||
await expect(restoreJdkResolution(request)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['malformed JSON', 'not json'],
|
||||
['a non-object payload', '"nope"'],
|
||||
[
|
||||
'a missing version',
|
||||
JSON.stringify({url: 'https://example.com/a.tar.gz'})
|
||||
],
|
||||
['a missing url', JSON.stringify({version: '21.0.8+9'})],
|
||||
[
|
||||
'a non-HTTPS url',
|
||||
JSON.stringify({
|
||||
version: '21.0.8+9',
|
||||
url: 'http://example.com/a.tar.gz'
|
||||
})
|
||||
],
|
||||
[
|
||||
'a malformed url',
|
||||
JSON.stringify({version: '21.0.8+9', url: 'not-a-url'})
|
||||
],
|
||||
[
|
||||
'a non-HTTPS signature url',
|
||||
JSON.stringify({
|
||||
version: '21.0.8+9',
|
||||
url: 'https://example.com/a.tar.gz',
|
||||
signatureUrl: 'http://example.com/a.sig'
|
||||
})
|
||||
],
|
||||
[
|
||||
'an unsupported checksum algorithm',
|
||||
JSON.stringify({
|
||||
version: '21.0.8+9',
|
||||
url: 'https://example.com/a.tar.gz',
|
||||
checksum: {algorithm: 'md5', value: 'abc'}
|
||||
})
|
||||
],
|
||||
[
|
||||
'a checksum without a value',
|
||||
JSON.stringify({
|
||||
version: '21.0.8+9',
|
||||
url: 'https://example.com/a.tar.gz',
|
||||
checksum: {algorithm: 'sha256'}
|
||||
})
|
||||
]
|
||||
])('rejects an entry with %s', async (_name, contents) => {
|
||||
createRunnerTemp();
|
||||
restoreWith(contents, 'setup-java-jdkres-v1-old');
|
||||
|
||||
await expect(restoreJdkResolution(request)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('keeps the optional fields of a valid entry', async () => {
|
||||
createRunnerTemp();
|
||||
const full = {
|
||||
version: '21.0.8+9',
|
||||
url: 'https://example.com/a.tar.gz',
|
||||
signatureUrl: 'https://example.com/a.sig',
|
||||
checksum: {
|
||||
algorithm: 'sha512',
|
||||
value: 'def456',
|
||||
source: 'https://example.com/a.sha512'
|
||||
}
|
||||
};
|
||||
restoreWith(JSON.stringify(full), 'setup-java-jdkres-v1-old');
|
||||
|
||||
const restored = await restoreJdkResolution(request);
|
||||
expect(restored?.release).toEqual(full);
|
||||
});
|
||||
|
||||
it('ignores unknown fields rather than passing them through', async () => {
|
||||
createRunnerTemp();
|
||||
restoreWith(
|
||||
JSON.stringify({...release, evil: 'payload'}),
|
||||
'setup-java-jdkres-v1-old'
|
||||
);
|
||||
|
||||
const restored = await restoreJdkResolution(request);
|
||||
expect(restored?.release).toEqual(release);
|
||||
});
|
||||
});
|
||||
|
||||
describe('registerJdkResolution', () => {
|
||||
it('writes the release and records it under the current bucket', () => {
|
||||
createRunnerTemp();
|
||||
registerJdkResolution(request, release);
|
||||
|
||||
const state = JSON.parse(
|
||||
jest.mocked(core.saveState).mock.calls.at(-1)![1] as string
|
||||
);
|
||||
const entry = state.at(-1);
|
||||
expect(entry.key.endsWith(bucket())).toBe(true);
|
||||
expect(
|
||||
JSON.parse(
|
||||
fs.readFileSync(path.join(entry.path, 'release.json'), 'utf8')
|
||||
)
|
||||
).toEqual(release);
|
||||
});
|
||||
|
||||
it('does nothing when the cache service is unavailable', () => {
|
||||
createRunnerTemp();
|
||||
jest.mocked(cache.isFeatureAvailable).mockReturnValue(false);
|
||||
|
||||
registerJdkResolution(request, release);
|
||||
expect(core.saveState).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does nothing when RUNNER_TEMP is not set', () => {
|
||||
delete process.env['RUNNER_TEMP'];
|
||||
|
||||
registerJdkResolution(request, release);
|
||||
expect(core.saveState).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('uses different keys for different requests', () => {
|
||||
createRunnerTemp();
|
||||
registerJdkResolution(request, release);
|
||||
registerJdkResolution({...request, distribution: 'zulu'}, release);
|
||||
|
||||
const state = JSON.parse(
|
||||
jest.mocked(core.saveState).mock.calls.at(-1)![1] as string
|
||||
);
|
||||
expect(new Set(state.map((item: {key: string}) => item.key)).size).toBe(
|
||||
state.length
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('saveJdkResolutionCaches', () => {
|
||||
const stateFor = (cachePath: string) =>
|
||||
JSON.stringify([
|
||||
{
|
||||
key: 'setup-java-jdkres-v1-key',
|
||||
path: cachePath,
|
||||
release: JSON.stringify(release)
|
||||
}
|
||||
]);
|
||||
|
||||
it('does nothing without state', async () => {
|
||||
await saveJdkResolutionCaches();
|
||||
expect(cache.saveCache).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('saves a recorded entry', async () => {
|
||||
const root = createRunnerTemp();
|
||||
jest.mocked(core.getState).mockReturnValue(stateFor(root));
|
||||
|
||||
await saveJdkResolutionCaches();
|
||||
expect(cache.saveCache).toHaveBeenCalledWith(
|
||||
[root],
|
||||
'setup-java-jdkres-v1-key'
|
||||
);
|
||||
});
|
||||
|
||||
it('saves the payload the key was computed for, not the file on disk', async () => {
|
||||
const root = createRunnerTemp();
|
||||
jest.mocked(core.getState).mockReturnValue(stateFor(root));
|
||||
// A restore performed by a later step replaces the file behind the key.
|
||||
fs.writeFileSync(
|
||||
path.join(root, 'release.json'),
|
||||
JSON.stringify({version: '8.0.1+1', url: 'https://example.com/stale'})
|
||||
);
|
||||
|
||||
await saveJdkResolutionCaches();
|
||||
|
||||
expect(
|
||||
JSON.parse(fs.readFileSync(path.join(root, 'release.json'), 'utf8'))
|
||||
).toEqual(release);
|
||||
expect(cache.saveCache).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not fail the job when the payload cannot be written', async () => {
|
||||
const root = createRunnerTemp();
|
||||
const blocked = path.join(root, 'blocked');
|
||||
fs.writeFileSync(blocked, 'not a directory');
|
||||
jest.mocked(core.getState).mockReturnValue(stateFor(blocked));
|
||||
|
||||
await expect(saveJdkResolutionCaches()).resolves.toBeUndefined();
|
||||
expect(cache.saveCache).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not fail the job when the save throws', async () => {
|
||||
const root = createRunnerTemp();
|
||||
jest.mocked(core.getState).mockReturnValue(stateFor(root));
|
||||
jest
|
||||
.mocked(cache.saveCache)
|
||||
.mockRejectedValue(new Error('already reserved'));
|
||||
|
||||
await expect(saveJdkResolutionCaches()).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not fail the job on invalid state', async () => {
|
||||
jest.mocked(core.getState).mockReturnValue('{}');
|
||||
|
||||
await expect(saveJdkResolutionCaches()).resolves.toBeUndefined();
|
||||
expect(cache.saveCache).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -33,8 +33,7 @@ jest.unstable_mockModule('fs', () => ({
|
||||
|
||||
jest.unstable_mockModule('../src/util.js', () => ({
|
||||
getBooleanInput: jest.fn(),
|
||||
getVersionFromFileContent: jest.fn(),
|
||||
isJdkCacheEnabled: jest.fn()
|
||||
getVersionFromFileContent: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../src/toolchains.js', () => ({
|
||||
@@ -99,7 +98,6 @@ describe('setup-java conditional module loading', () => {
|
||||
return booleanInputs.get(name as string) ?? defaultValue;
|
||||
}
|
||||
);
|
||||
(util.isJdkCacheEnabled as jest.Mock).mockReturnValue(false);
|
||||
(toolchains.configureToolchains as jest.Mock).mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@ jest.unstable_mockModule('fs', () => ({
|
||||
|
||||
jest.unstable_mockModule('../src/util.js', () => ({
|
||||
getBooleanInput: jest.fn(),
|
||||
getVersionFromFileContent: jest.fn(),
|
||||
isJdkCacheEnabled: jest.fn()
|
||||
getVersionFromFileContent: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../src/toolchains.js', () => ({
|
||||
@@ -114,14 +113,6 @@ describe('setup action orchestration', () => {
|
||||
return booleanInputs.get(name as string) ?? defaultValue;
|
||||
}
|
||||
);
|
||||
(util.isJdkCacheEnabled as jest.Mock).mockImplementation(
|
||||
(cache: string) => {
|
||||
const explicit = inputs.get('cache-jdk');
|
||||
return explicit
|
||||
? (booleanInputs.get('cache-jdk') ?? explicit === 'true')
|
||||
: Boolean(cache);
|
||||
}
|
||||
);
|
||||
(cacheFeature.isCacheFeatureAvailable as jest.Mock).mockReturnValue(true);
|
||||
(toolchainIds.validateToolchainIds as jest.Mock).mockImplementation(
|
||||
() => undefined
|
||||
@@ -226,7 +217,6 @@ describe('setup action orchestration', () => {
|
||||
packageType: 'jdk',
|
||||
checkLatest: true,
|
||||
forceDownload: true,
|
||||
cacheJdk: false,
|
||||
setDefault: false,
|
||||
verifySignature: true,
|
||||
verifySignaturePublicKey: 'public-key'
|
||||
@@ -467,7 +457,6 @@ describe('setup action orchestration', () => {
|
||||
it('does not initialize cache modules when cache input is absent', async () => {
|
||||
inputs.set('distribution', 'temurin');
|
||||
multilineInputs.set('java-version', ['21']);
|
||||
booleanInputs.set('cache-jdk', false);
|
||||
(factory.getJavaDistribution as jest.Mock).mockReturnValue({
|
||||
setupJava: jest.fn(async () => ({
|
||||
version: '21.0.4+7',
|
||||
@@ -479,47 +468,8 @@ describe('setup action orchestration', () => {
|
||||
|
||||
expect(cacheFeature.isCacheFeatureAvailable).not.toHaveBeenCalled();
|
||||
expect(cache.restore).not.toHaveBeenCalled();
|
||||
expect(factory.getJavaDistribution).toHaveBeenCalledWith(
|
||||
'temurin',
|
||||
expect.objectContaining({cacheJdk: false}),
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['', '', false],
|
||||
['', 'true', true],
|
||||
['', 'false', false],
|
||||
['maven', '', true],
|
||||
['maven', 'true', true],
|
||||
['maven', 'false', false]
|
||||
])(
|
||||
'passes effective JDK caching for cache=%j and cache-jdk=%j',
|
||||
async (cacheInput, cacheJdkInput, expected) => {
|
||||
inputs.set('distribution', 'temurin');
|
||||
inputs.set('cache', cacheInput);
|
||||
inputs.set('cache-jdk', cacheJdkInput);
|
||||
multilineInputs.set('java-version', ['21']);
|
||||
if (cacheJdkInput) {
|
||||
booleanInputs.set('cache-jdk', cacheJdkInput === 'true');
|
||||
}
|
||||
(factory.getJavaDistribution as jest.Mock).mockReturnValue({
|
||||
setupJava: jest.fn(async () => ({
|
||||
version: '21.0.4+7',
|
||||
path: '/opt/java/21'
|
||||
}))
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(factory.getJavaDistribution).toHaveBeenCalledWith(
|
||||
'temurin',
|
||||
expect.objectContaining({cacheJdk: expected}),
|
||||
''
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it('reports unsupported distributions through core.setFailed', async () => {
|
||||
inputs.set('distribution', 'unsupported');
|
||||
multilineInputs.set('java-version', ['21']);
|
||||
|
||||
@@ -1,412 +0,0 @@
|
||||
import {jest, describe, it, expect, beforeEach, afterEach} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
jest.unstable_mockModule('@actions/core', () => ({
|
||||
debug: jest.fn(),
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
error: jest.fn(),
|
||||
getInput: jest.fn(() => ''),
|
||||
isDebug: jest.fn(() => false),
|
||||
addPath: jest.fn(),
|
||||
exportVariable: jest.fn(),
|
||||
setOutput: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/tool-cache', () => ({
|
||||
cacheDir: jest.fn(),
|
||||
extractTar: jest.fn(),
|
||||
extractZip: jest.fn(),
|
||||
extract7z: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/exec', () => ({
|
||||
exec: jest.fn()
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/io', () => ({
|
||||
which: jest.fn(),
|
||||
rmRF: jest.fn(async (target: string) =>
|
||||
fs.rmSync(target, {recursive: true, force: true})
|
||||
),
|
||||
mkdirP: jest.fn(async (target: string) =>
|
||||
fs.mkdirSync(target, {recursive: true})
|
||||
)
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('@actions/http-client', () => ({
|
||||
HttpClient: jest.fn(),
|
||||
HttpClientError: class HttpClientError extends Error {}
|
||||
}));
|
||||
|
||||
const tc = await import('@actions/tool-cache');
|
||||
const exec = await import('@actions/exec');
|
||||
const io = await import('@actions/io');
|
||||
const {cacheJdkDir, extractJdkFile} = await import('../src/util.js');
|
||||
|
||||
const originalToolCache = process.env['RUNNER_TOOL_CACHE'];
|
||||
const originalTemp = process.env['RUNNER_TEMP'];
|
||||
const originalPlatform = process.platform;
|
||||
|
||||
let workDir: string;
|
||||
|
||||
function setPlatform(platform: NodeJS.Platform) {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: platform,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
workDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-java-util-'));
|
||||
process.env['RUNNER_TOOL_CACHE'] = path.join(workDir, 'toolcache');
|
||||
process.env['RUNNER_TEMP'] = path.join(workDir, 'temp');
|
||||
fs.mkdirSync(process.env['RUNNER_TEMP'], {recursive: true});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
setPlatform(originalPlatform);
|
||||
while (lockedDirs.length) {
|
||||
fs.chmodSync(lockedDirs.pop()!, 0o755);
|
||||
}
|
||||
fs.rmSync(workDir, {recursive: true, force: true});
|
||||
if (originalToolCache === undefined) {
|
||||
delete process.env['RUNNER_TOOL_CACHE'];
|
||||
} else {
|
||||
process.env['RUNNER_TOOL_CACHE'] = originalToolCache;
|
||||
}
|
||||
if (originalTemp === undefined) {
|
||||
delete process.env['RUNNER_TEMP'];
|
||||
} else {
|
||||
process.env['RUNNER_TEMP'] = originalTemp;
|
||||
}
|
||||
});
|
||||
|
||||
function createJdkDir(name = 'jdk-source'): string {
|
||||
const sourceDir = path.join(workDir, name);
|
||||
fs.mkdirSync(path.join(sourceDir, 'bin'), {recursive: true});
|
||||
fs.writeFileSync(path.join(sourceDir, 'bin', 'java'), 'binary');
|
||||
fs.writeFileSync(path.join(sourceDir, 'release'), 'JAVA_VERSION="17"');
|
||||
|
||||
return sourceDir;
|
||||
}
|
||||
|
||||
// A rename needs write permission on the source's parent directory, so making
|
||||
// that parent read-only is a portable way to force the same failure a
|
||||
// cross-device tool-cache (EXDEV) or a Windows anti-virus handle (EPERM) would.
|
||||
// Root ignores the permission bits, so those tests are skipped there.
|
||||
const canForceRenameFailure =
|
||||
process.platform !== 'win32' &&
|
||||
typeof process.getuid === 'function' &&
|
||||
process.getuid() !== 0;
|
||||
const itUnlessRoot = canForceRenameFailure ? it : it.skip;
|
||||
const lockedDirs: string[] = [];
|
||||
|
||||
function createUnrenameableJdkDir(): string {
|
||||
const parent = path.join(workDir, 'locked');
|
||||
fs.mkdirSync(parent, {recursive: true});
|
||||
const sourceDir = path.join(parent, 'jdk-source');
|
||||
fs.mkdirSync(path.join(sourceDir, 'bin'), {recursive: true});
|
||||
fs.writeFileSync(path.join(sourceDir, 'bin', 'java'), 'binary');
|
||||
fs.chmodSync(parent, 0o555);
|
||||
lockedDirs.push(parent);
|
||||
|
||||
return sourceDir;
|
||||
}
|
||||
|
||||
describe('cacheJdkDir', () => {
|
||||
it('moves the JDK into the tool-cache instead of copying it', async () => {
|
||||
const sourceDir = createJdkDir();
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
sourceDir,
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
|
||||
expect(javaPath).toBe(
|
||||
path.join(
|
||||
process.env['RUNNER_TOOL_CACHE']!,
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
)
|
||||
);
|
||||
expect(fs.existsSync(path.join(javaPath, 'bin', 'java'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(javaPath, 'release'))).toBe(true);
|
||||
// the source is moved, not copied, so it no longer exists
|
||||
expect(fs.existsSync(sourceDir)).toBe(false);
|
||||
expect(tc.cacheDir).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('writes the .complete marker expected by the tool-cache', async () => {
|
||||
const javaPath = await cacheJdkDir(
|
||||
createJdkDir(),
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
|
||||
expect(fs.existsSync(`${javaPath}.complete`)).toBe(true);
|
||||
});
|
||||
|
||||
it('replaces an existing tool-cache entry', async () => {
|
||||
const destPath = path.join(
|
||||
process.env['RUNNER_TOOL_CACHE']!,
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
fs.mkdirSync(destPath, {recursive: true});
|
||||
fs.writeFileSync(path.join(destPath, 'stale'), 'stale');
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
createJdkDir(),
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
|
||||
expect(fs.existsSync(path.join(javaPath, 'stale'))).toBe(false);
|
||||
expect(fs.existsSync(path.join(javaPath, 'bin', 'java'))).toBe(true);
|
||||
});
|
||||
|
||||
it('normalizes the version the same way as tc.cacheDir', async () => {
|
||||
const javaPath = await cacheJdkDir(
|
||||
createJdkDir(),
|
||||
'Java_temurin_jdk',
|
||||
'v17.0.1',
|
||||
'x64'
|
||||
);
|
||||
|
||||
expect(path.basename(path.dirname(javaPath))).toBe('17.0.1');
|
||||
});
|
||||
|
||||
it('keeps unparseable versions as-is', async () => {
|
||||
const javaPath = await cacheJdkDir(
|
||||
createJdkDir(),
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1-ea.3',
|
||||
'x64'
|
||||
);
|
||||
|
||||
expect(path.basename(path.dirname(javaPath))).toBe('17.0.1-ea.3');
|
||||
});
|
||||
|
||||
it('falls back to tc.cacheDir when the move fails', async () => {
|
||||
(tc.cacheDir as jest.Mock).mockResolvedValue('/fallback/path' as never);
|
||||
const missingDir = path.join(workDir, 'does-not-exist');
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
missingDir,
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
|
||||
expect(javaPath).toBe('/fallback/path');
|
||||
expect(tc.cacheDir).toHaveBeenCalledWith(
|
||||
missingDir,
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
});
|
||||
|
||||
itUnlessRoot(
|
||||
'falls back to tc.cacheDir when the rename itself fails',
|
||||
async () => {
|
||||
const sourceDir = createUnrenameableJdkDir();
|
||||
(tc.cacheDir as jest.Mock).mockResolvedValue('/fallback/path' as never);
|
||||
|
||||
await expect(
|
||||
cacheJdkDir(sourceDir, 'Java_temurin_jdk', '17.0.1', 'x64')
|
||||
).resolves.toBe('/fallback/path');
|
||||
// the source must survive so the copy-based fallback can still read it
|
||||
expect(fs.existsSync(path.join(sourceDir, 'bin', 'java'))).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
itUnlessRoot(
|
||||
'does not leave a .complete marker behind when the rename fails',
|
||||
async () => {
|
||||
const destPath = path.join(
|
||||
process.env['RUNNER_TOOL_CACHE']!,
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
fs.mkdirSync(destPath, {recursive: true});
|
||||
fs.writeFileSync(`${destPath}.complete`, '');
|
||||
(tc.cacheDir as jest.Mock).mockResolvedValue('/fallback/path' as never);
|
||||
|
||||
await cacheJdkDir(
|
||||
createUnrenameableJdkDir(),
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
'x64'
|
||||
);
|
||||
|
||||
// a stale marker without a matching installation would make the
|
||||
// tool-cache resolve a directory that is no longer there
|
||||
expect(fs.existsSync(`${destPath}.complete`)).toBe(false);
|
||||
}
|
||||
);
|
||||
|
||||
it('falls back to tc.cacheDir for symlinked sources', async () => {
|
||||
const realDir = createJdkDir('real-jdk');
|
||||
const linkDir = path.join(workDir, 'linked-jdk');
|
||||
fs.symlinkSync(realDir, linkDir, 'dir');
|
||||
(tc.cacheDir as jest.Mock).mockResolvedValue('/fallback/path' as never);
|
||||
|
||||
await expect(
|
||||
cacheJdkDir(linkDir, 'Java_temurin_jdk', '17.0.1', 'x64')
|
||||
).resolves.toBe('/fallback/path');
|
||||
// moving the symlink itself would leave a dangling tool-cache entry
|
||||
expect(fs.lstatSync(linkDir).isSymbolicLink()).toBe(true);
|
||||
});
|
||||
|
||||
it('defaults the architecture the same way as tc.cacheDir', async () => {
|
||||
const javaPath = await cacheJdkDir(
|
||||
createJdkDir(),
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
''
|
||||
);
|
||||
|
||||
expect(javaPath).toBe(
|
||||
path.join(
|
||||
process.env['RUNNER_TOOL_CACHE']!,
|
||||
'Java_temurin_jdk',
|
||||
'17.0.1',
|
||||
os.arch()
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('falls back to tc.cacheDir when the tool-cache location is unknown', async () => {
|
||||
delete process.env['RUNNER_TOOL_CACHE'];
|
||||
(tc.cacheDir as jest.Mock).mockResolvedValue('/fallback/path' as never);
|
||||
|
||||
await expect(
|
||||
cacheJdkDir(createJdkDir(), 'Java_temurin_jdk', '17.0.1', 'x64')
|
||||
).resolves.toBe('/fallback/path');
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractJdkFile', () => {
|
||||
it('uses pigz for tarballs when it is available', async () => {
|
||||
(io.which as jest.Mock).mockResolvedValue('/usr/bin/pigz' as never);
|
||||
(tc.extractTar as jest.Mock).mockResolvedValue('/extracted' as never);
|
||||
|
||||
await expect(extractJdkFile('/tmp/jdk.tar.gz')).resolves.toBe('/extracted');
|
||||
expect(tc.extractTar).toHaveBeenCalledWith(
|
||||
'/tmp/jdk.tar.gz',
|
||||
expect.stringContaining(process.env['RUNNER_TEMP']!),
|
||||
['--use-compress-program', '/usr/bin/pigz -d', '-x']
|
||||
);
|
||||
});
|
||||
|
||||
it('falls back to gzip when pigz is not installed', async () => {
|
||||
(io.which as jest.Mock).mockResolvedValue('' as never);
|
||||
(tc.extractTar as jest.Mock).mockResolvedValue('/extracted' as never);
|
||||
|
||||
await expect(extractJdkFile('/tmp/jdk.tar.gz')).resolves.toBe('/extracted');
|
||||
expect(tc.extractTar).toHaveBeenCalledWith('/tmp/jdk.tar.gz');
|
||||
});
|
||||
|
||||
it('falls back to gzip when pigz extraction fails', async () => {
|
||||
(io.which as jest.Mock).mockResolvedValue('/usr/bin/pigz' as never);
|
||||
(tc.extractTar as jest.Mock)
|
||||
.mockRejectedValueOnce(new Error('pigz exploded') as never)
|
||||
.mockResolvedValue('/extracted' as never);
|
||||
|
||||
await expect(extractJdkFile('/tmp/jdk.tar.gz')).resolves.toBe('/extracted');
|
||||
expect(tc.extractTar).toHaveBeenNthCalledWith(2, '/tmp/jdk.tar.gz');
|
||||
});
|
||||
|
||||
it('cleans up the abandoned folder when pigz extraction fails', async () => {
|
||||
(io.which as jest.Mock).mockResolvedValue('/usr/bin/pigz' as never);
|
||||
let pigzDest: string | undefined;
|
||||
(tc.extractTar as jest.Mock)
|
||||
.mockImplementationOnce((...args: unknown[]) => {
|
||||
pigzDest = args[1] as string;
|
||||
throw new Error('pigz exploded');
|
||||
})
|
||||
.mockResolvedValue('/extracted' as never);
|
||||
|
||||
await extractJdkFile('/tmp/jdk.tar.gz');
|
||||
|
||||
expect(pigzDest).toBeDefined();
|
||||
expect(fs.existsSync(pigzDest!)).toBe(false);
|
||||
});
|
||||
|
||||
it('ignores pigz when its path contains whitespace', async () => {
|
||||
(io.which as jest.Mock).mockResolvedValue(
|
||||
'C:\\Program Files\\pigz.exe' as never
|
||||
);
|
||||
(tc.extractTar as jest.Mock).mockResolvedValue('/extracted' as never);
|
||||
|
||||
await extractJdkFile('/tmp/jdk.tar.gz');
|
||||
|
||||
// tar word-splits --use-compress-program, so a spaced path is unusable
|
||||
expect(tc.extractTar).toHaveBeenCalledWith('/tmp/jdk.tar.gz');
|
||||
});
|
||||
|
||||
it('leaves uncompressed tarballs on the default extraction path', async () => {
|
||||
(tc.extractTar as jest.Mock).mockResolvedValue('/extracted' as never);
|
||||
|
||||
await expect(extractJdkFile('/tmp/jdk.tar')).resolves.toBe('/extracted');
|
||||
expect(tc.extractTar).toHaveBeenCalledWith('/tmp/jdk.tar');
|
||||
expect(io.which).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('uses the bundled tar.exe for zip archives on Windows', async () => {
|
||||
setPlatform('win32');
|
||||
const systemRoot = path.join(workDir, 'Windows');
|
||||
fs.mkdirSync(path.join(systemRoot, 'System32'), {recursive: true});
|
||||
const systemTar = path.join(systemRoot, 'System32', 'tar.exe');
|
||||
fs.writeFileSync(systemTar, '');
|
||||
process.env['SystemRoot'] = systemRoot;
|
||||
|
||||
const javaPath = await extractJdkFile('/tmp/jdk.zip');
|
||||
|
||||
expect(tc.extractZip).not.toHaveBeenCalled();
|
||||
expect(exec.exec).toHaveBeenCalledWith(
|
||||
`"${systemTar}"`,
|
||||
['-xf', '/tmp/jdk.zip', '-C', javaPath],
|
||||
{silent: true}
|
||||
);
|
||||
expect(fs.existsSync(javaPath)).toBe(true);
|
||||
});
|
||||
|
||||
it('falls back to tc.extractZip when tar.exe fails', async () => {
|
||||
setPlatform('win32');
|
||||
const systemRoot = path.join(workDir, 'Windows');
|
||||
fs.mkdirSync(path.join(systemRoot, 'System32'), {recursive: true});
|
||||
fs.writeFileSync(path.join(systemRoot, 'System32', 'tar.exe'), '');
|
||||
process.env['SystemRoot'] = systemRoot;
|
||||
let tarDest: string | undefined;
|
||||
(exec.exec as jest.Mock).mockImplementation((...args: unknown[]) => {
|
||||
tarDest = (args[1] as string[])[3];
|
||||
throw new Error('boom');
|
||||
});
|
||||
(tc.extractZip as jest.Mock).mockResolvedValue('/extracted' as never);
|
||||
|
||||
await expect(extractJdkFile('/tmp/jdk.zip')).resolves.toBe('/extracted');
|
||||
expect(tarDest).toBeDefined();
|
||||
expect(fs.existsSync(tarDest!)).toBe(false);
|
||||
});
|
||||
|
||||
it('uses tc.extractZip on non-Windows platforms', async () => {
|
||||
setPlatform('linux');
|
||||
(tc.extractZip as jest.Mock).mockResolvedValue('/extracted' as never);
|
||||
|
||||
await expect(extractJdkFile('/tmp/jdk.zip')).resolves.toBe('/extracted');
|
||||
expect(exec.exec).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
+1
-33
@@ -49,8 +49,7 @@ const {
|
||||
isGhes,
|
||||
validatePaginationUrl,
|
||||
getLatestMajorVersion,
|
||||
getBooleanInput,
|
||||
isJdkCacheEnabled
|
||||
getBooleanInput
|
||||
} = await import('../src/util.js');
|
||||
|
||||
describe('getBooleanInput', () => {
|
||||
@@ -116,37 +115,6 @@ describe('getBooleanInput', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isJdkCacheEnabled', () => {
|
||||
let inputs: Record<string, string>;
|
||||
|
||||
beforeEach(() => {
|
||||
inputs = {};
|
||||
(core.getInput as jest.Mock).mockImplementation(
|
||||
(name: string) => inputs[name] ?? ''
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['', '', false],
|
||||
['', 'true', true],
|
||||
['', 'false', false],
|
||||
['maven', '', true],
|
||||
['maven', 'true', true],
|
||||
['maven', 'false', false]
|
||||
])(
|
||||
'resolves cache=%j and cache-jdk=%j to %s',
|
||||
(cache, cacheJdk, expected) => {
|
||||
inputs['cache-jdk'] = cacheJdk;
|
||||
|
||||
expect(isJdkCacheEnabled(cache)).toBe(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('isVersionSatisfies', () => {
|
||||
it.each([
|
||||
['x', '11.0.0', true],
|
||||
|
||||
+2
-5
@@ -84,9 +84,6 @@ inputs:
|
||||
cache:
|
||||
description: 'Name of the build platform to cache dependencies. It can be "maven", "gradle" or "sbt".'
|
||||
required: false
|
||||
cache-jdk:
|
||||
description: 'Cache downloaded JDK installations between jobs. Defaults to enabled when dependency caching is configured with `cache`; set explicitly to "true" or "false" to override.'
|
||||
required: false
|
||||
cache-dependency-path:
|
||||
description: 'The path to a dependency file: pom.xml, build.gradle, build.sbt, etc. This option can be used with the `cache` option. If this option is omitted, the action searches for the dependency file in the entire repository. This option supports wildcards and a list of file names for caching multiple dependencies.'
|
||||
required: false
|
||||
@@ -94,7 +91,7 @@ inputs:
|
||||
description: 'The path to cache instead of the default dependency cache path for the selected package manager. This option can be used with the `cache` option and supports a list of paths and exclusion patterns.'
|
||||
required: false
|
||||
cache-read-only:
|
||||
description: 'Restore caches without saving cache changes in the post action.'
|
||||
description: 'Restore dependency caches without saving cache changes in the post action.'
|
||||
required: false
|
||||
default: false
|
||||
job-status:
|
||||
@@ -106,7 +103,7 @@ inputs:
|
||||
required: false
|
||||
default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
|
||||
mvn-toolchain-id:
|
||||
description: 'Name of Maven Toolchain ID if the default name of "${mvn-toolchain-vendor}_${java-version}" is not wanted. The toolchain vendor defaults to the "distribution" input. When supplied, the number of IDs must match the number of Java versions. See examples of supported syntax in Advanced Usage file'
|
||||
description: 'Name of Maven Toolchain ID if the default name of "${distribution}_${java-version}" is not wanted. When supplied, the number of IDs must match the number of Java versions. See examples of supported syntax in Advanced Usage file'
|
||||
required: false
|
||||
mvn-toolchain-vendor:
|
||||
description: 'Name of Maven Toolchain Vendor if the default name of "${distribution}" is not wanted. See examples of supported syntax in Advanced Usage file'
|
||||
|
||||
Vendored
-224
@@ -1,224 +0,0 @@
|
||||
export const id = 314;
|
||||
export const ids = [314];
|
||||
export const modules = {
|
||||
|
||||
/***/ 2314:
|
||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
|
||||
// EXPORTS
|
||||
__webpack_require__.d(__webpack_exports__, {
|
||||
saveJdkCaches: () => (/* binding */ saveJdkCaches)
|
||||
});
|
||||
|
||||
// UNUSED EXPORTS: buildJdkCacheKey, getJdkVerificationIdentity, registerJdk, restoreJdk
|
||||
|
||||
// EXTERNAL MODULE: external "crypto"
|
||||
var external_crypto_ = __webpack_require__(6982);
|
||||
// EXTERNAL MODULE: external "fs"
|
||||
var external_fs_ = __webpack_require__(9896);
|
||||
var external_fs_default = /*#__PURE__*/__webpack_require__.n(external_fs_);
|
||||
// EXTERNAL MODULE: external "path"
|
||||
var external_path_ = __webpack_require__(6928);
|
||||
var external_path_default = /*#__PURE__*/__webpack_require__.n(external_path_);
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/cache/lib/cache.js + 291 modules
|
||||
var lib_cache = __webpack_require__(5767);
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js + 7 modules
|
||||
var lib_core = __webpack_require__(3838);
|
||||
// EXTERNAL MODULE: ./src/util.ts
|
||||
var util = __webpack_require__(4527);
|
||||
;// CONCATENATED MODULE: ./src/cache-feature.ts
|
||||
|
||||
|
||||
|
||||
function cache_feature_isCacheFeatureAvailable() {
|
||||
if (cache.isFeatureAvailable()) {
|
||||
return true;
|
||||
}
|
||||
if (isGhes()) {
|
||||
core.warning('Caching is only supported on GHES version >= 3.5. If you are on a version >= 3.5, please check with your GHES admin if the Actions cache service is enabled or not.');
|
||||
return false;
|
||||
}
|
||||
core.warning('The runner was not able to contact the cache service. Caching will be skipped');
|
||||
return false;
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ./src/jdk-cache.ts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const STATE_JDK_CACHES = 'jdk-caches';
|
||||
const JDK_CACHE_KEY_VERSION = 1;
|
||||
const restoredCaches = (/* unused pure expression or super */ null && ([]));
|
||||
async function restoreJdk(jdk) {
|
||||
if (!jdk.path || !isCacheFeatureAvailable()) {
|
||||
return false;
|
||||
}
|
||||
const key = buildJdkCacheKey(jdk);
|
||||
let matchedKey;
|
||||
try {
|
||||
matchedKey = await cache.restoreCache([jdk.path], key);
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`Failed to restore JDK cache: ${error.message}`);
|
||||
}
|
||||
const architecturePath = path.join(jdk.path, jdk.architecture);
|
||||
if (matchedKey &&
|
||||
(!fs.existsSync(architecturePath) ||
|
||||
!fs.existsSync(`${architecturePath}.complete`))) {
|
||||
core.warning(`JDK cache key ${matchedKey} was restored without the expected tool-cache path; downloading the JDK instead.`);
|
||||
matchedKey = undefined;
|
||||
}
|
||||
recordJdkCache({
|
||||
key,
|
||||
path: jdk.path,
|
||||
architecture: jdk.architecture,
|
||||
matchedKey
|
||||
});
|
||||
if (matchedKey) {
|
||||
core.info(`JDK cache restored from key: ${matchedKey}`);
|
||||
return true;
|
||||
}
|
||||
core.info(`JDK cache is not found for ${jdk.distribution} ${jdk.version}`);
|
||||
return false;
|
||||
}
|
||||
function registerJdk(jdk) {
|
||||
if (!jdk.path) {
|
||||
return;
|
||||
}
|
||||
recordJdkCache({
|
||||
key: buildJdkCacheKey(jdk),
|
||||
path: jdk.path,
|
||||
architecture: jdk.architecture,
|
||||
installation: getInstallationIdentity(jdk.path, jdk.architecture)
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Cheap fingerprint of the installation stored at a tool-cache path. The
|
||||
* `<architecture>.complete` marker is (re)created by `tc.cacheDir` every time an
|
||||
* installation is written, so its inode and timestamps change whenever the
|
||||
* installation is replaced. This avoids rehashing a multi-hundred-megabyte JDK
|
||||
* directory while still detecting that the bytes behind a key were swapped.
|
||||
*/
|
||||
function getInstallationIdentity(jdkPath, architecture) {
|
||||
const architecturePath = external_path_default().join(jdkPath, architecture);
|
||||
try {
|
||||
const marker = external_fs_default().statSync(`${architecturePath}.complete`);
|
||||
const installation = external_fs_default().statSync(architecturePath);
|
||||
return [
|
||||
marker.ino,
|
||||
marker.mtimeMs,
|
||||
marker.ctimeMs,
|
||||
marker.size,
|
||||
installation.ino,
|
||||
installation.mtimeMs,
|
||||
installation.ctimeMs
|
||||
].join(':');
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
function getJdkVerificationIdentity(verifySignature, publicKey) {
|
||||
if (!verifySignature) {
|
||||
return 'unverified';
|
||||
}
|
||||
if (!publicKey) {
|
||||
return 'verified:bundled';
|
||||
}
|
||||
const normalizedKey = publicKey.replace(/\r\n?/g, '\n').trim();
|
||||
const fingerprint = createHash('sha256').update(normalizedKey).digest('hex');
|
||||
return `verified:custom:sha256:${fingerprint}`;
|
||||
}
|
||||
async function saveJdkCaches() {
|
||||
const state = lib_core/* getState */.Gu(STATE_JDK_CACHES);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
const caches = parseJdkCacheState(state);
|
||||
for (const jdk of caches) {
|
||||
if (jdk.matchedKey === jdk.key) {
|
||||
lib_core/* info */.pq(`Cache hit occurred on the JDK primary key ${jdk.key}, not saving cache.`);
|
||||
continue;
|
||||
}
|
||||
if (!external_fs_default().existsSync(jdk.path)) {
|
||||
lib_core/* debug */.Yz(`JDK cache path does not exist, not saving: ${jdk.path}`);
|
||||
continue;
|
||||
}
|
||||
if (!jdk.installation) {
|
||||
lib_core/* debug */.Yz(`No JDK installation was registered for the key ${jdk.key}, not saving cache.`);
|
||||
continue;
|
||||
}
|
||||
if (getInstallationIdentity(jdk.path, jdk.architecture) !== jdk.installation) {
|
||||
lib_core/* warning */.$e(`The JDK installation in ${jdk.path} was replaced after it was registered for the key ${jdk.key}; not saving cache.`);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const cacheId = await lib_cache/* saveCache */.Io([jdk.path], jdk.key);
|
||||
if (cacheId !== -1) {
|
||||
lib_core/* info */.pq(`JDK cache saved with the key: ${jdk.key}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
const err = error;
|
||||
if (err.name === lib_cache/* ReserveCacheError */.Zh.name) {
|
||||
lib_core/* info */.pq(err.message);
|
||||
}
|
||||
else {
|
||||
// Saving is best-effort and per entry: one failure must not suppress
|
||||
// the remaining JDK caches.
|
||||
lib_core/* warning */.$e(`Failed to save the JDK cache with the key ${jdk.key}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function buildJdkCacheKey(jdk) {
|
||||
const runnerOs = process.env['RUNNER_OS'] ?? process.platform;
|
||||
const normalizedArchitecture = jdk.architecture.toLowerCase();
|
||||
const identity = JSON.stringify({
|
||||
keyVersion: JDK_CACHE_KEY_VERSION,
|
||||
runnerOs,
|
||||
distribution: jdk.distribution.toLowerCase(),
|
||||
packageType: jdk.packageType.toLowerCase(),
|
||||
architecture: normalizedArchitecture,
|
||||
version: jdk.version,
|
||||
source: jdk.source,
|
||||
verification: jdk.verification
|
||||
});
|
||||
const digest = createHash('sha256').update(identity).digest('hex');
|
||||
return `setup-java-jdk-v${JDK_CACHE_KEY_VERSION}-${runnerOs}-${normalizedArchitecture}-${digest}`;
|
||||
}
|
||||
function recordJdkCache(jdk) {
|
||||
const existing = restoredCaches.findIndex(item => item.key === jdk.key && item.path === jdk.path);
|
||||
if (existing === -1) {
|
||||
restoredCaches.push(jdk);
|
||||
}
|
||||
else {
|
||||
restoredCaches[existing] = { ...restoredCaches[existing], ...jdk };
|
||||
}
|
||||
core.saveState(STATE_JDK_CACHES, JSON.stringify(restoredCaches));
|
||||
}
|
||||
function parseJdkCacheState(state) {
|
||||
const value = JSON.parse(state);
|
||||
if (!Array.isArray(value) ||
|
||||
!value.every(item => typeof item === 'object' &&
|
||||
item !== null &&
|
||||
typeof item.key === 'string' &&
|
||||
typeof item.path === 'string' &&
|
||||
typeof item.architecture === 'string' &&
|
||||
(item.matchedKey === undefined ||
|
||||
typeof item.matchedKey === 'string') &&
|
||||
(item.installation === undefined ||
|
||||
typeof item.installation === 'string'))) {
|
||||
throw new Error('Invalid JDK cache information retrieved from state.');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
Vendored
-270
@@ -1,270 +0,0 @@
|
||||
export const id = 348;
|
||||
export const ids = [348];
|
||||
export const modules = {
|
||||
|
||||
/***/ 967:
|
||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ saveJdkResolutionCaches: () => (/* binding */ saveJdkResolutionCaches)
|
||||
/* harmony export */ });
|
||||
/* unused harmony exports restoreJdkResolution, registerJdkResolution */
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6982);
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5767);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3838);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const STATE_JDK_RESOLUTIONS = 'jdk-resolutions';
|
||||
const JDK_RESOLUTION_KEY_VERSION = 1;
|
||||
const RESOLUTION_DIRECTORY = 'setup-java-jdk-resolution';
|
||||
const RESOLUTION_FILE_NAME = 'release.json';
|
||||
const pendingResolutions = (/* unused pure expression or super */ null && ([]));
|
||||
/**
|
||||
* Restores a previously resolved release so a distribution can skip its vendor
|
||||
* metadata API.
|
||||
*
|
||||
* The cache path deliberately excludes the freshness window: `@actions/cache`
|
||||
* derives
|
||||
* a cache version by hashing the requested paths, so a bucket-independent path
|
||||
* is what allows the restore keys to fall back to an older bucket.
|
||||
*/
|
||||
async function restoreJdkResolution(request) {
|
||||
// Deliberately not `isCacheFeatureAvailable()`: this is an optional
|
||||
// optimization, and the JDK cache already warns once when the service is
|
||||
// unreachable.
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
return undefined;
|
||||
}
|
||||
const cachePath = getResolutionCachePath(request);
|
||||
if (!cachePath) {
|
||||
return undefined;
|
||||
}
|
||||
const keyPrefix = getResolutionKeyPrefix(request);
|
||||
const primaryKey = `${keyPrefix}${getFreshnessBucket()}`;
|
||||
let matchedKey;
|
||||
try {
|
||||
matchedKey = await cache.restoreCache([cachePath], primaryKey, [keyPrefix]);
|
||||
}
|
||||
catch (error) {
|
||||
core.debug(`Failed to restore the JDK resolution cache: ${getErrorMessage(error)}`);
|
||||
return undefined;
|
||||
}
|
||||
if (!matchedKey) {
|
||||
return undefined;
|
||||
}
|
||||
let release;
|
||||
try {
|
||||
const contents = fs.readFileSync(path.join(cachePath, RESOLUTION_FILE_NAME), 'utf8');
|
||||
release = parseResolvedRelease(contents);
|
||||
}
|
||||
catch (error) {
|
||||
core.debug(`Ignoring the JDK resolution cache entry ${matchedKey}: ${getErrorMessage(error)}`);
|
||||
return undefined;
|
||||
}
|
||||
return { release, fresh: matchedKey === primaryKey };
|
||||
}
|
||||
/**
|
||||
* Persists a freshly resolved release for later jobs. The entry is written to
|
||||
* disk immediately and uploaded by the post-job step.
|
||||
*/
|
||||
function registerJdkResolution(request, release) {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
return;
|
||||
}
|
||||
const cachePath = getResolutionCachePath(request);
|
||||
if (!cachePath) {
|
||||
return;
|
||||
}
|
||||
const payload = JSON.stringify(release);
|
||||
try {
|
||||
fs.mkdirSync(cachePath, { recursive: true });
|
||||
fs.writeFileSync(path.join(cachePath, RESOLUTION_FILE_NAME), payload);
|
||||
}
|
||||
catch (error) {
|
||||
core.debug(`Failed to record the JDK resolution cache entry: ${getErrorMessage(error)}`);
|
||||
return;
|
||||
}
|
||||
const key = `${getResolutionKeyPrefix(request)}${getFreshnessBucket()}`;
|
||||
if (!pendingResolutions.some(item => item.key === key)) {
|
||||
pendingResolutions.push({ key, path: cachePath, release: payload });
|
||||
}
|
||||
core.saveState(STATE_JDK_RESOLUTIONS, JSON.stringify(pendingResolutions));
|
||||
}
|
||||
async function saveJdkResolutionCaches() {
|
||||
const state = _actions_core__WEBPACK_IMPORTED_MODULE_4__/* .getState */ .Gu(STATE_JDK_RESOLUTIONS);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
let resolutions;
|
||||
try {
|
||||
resolutions = parseJdkResolutionState(state);
|
||||
}
|
||||
catch (error) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Invalid JDK resolution cache state, not saving: ${getErrorMessage(error)}`);
|
||||
return;
|
||||
}
|
||||
for (const resolution of resolutions) {
|
||||
// A restore performed by a later step overwrites this path, so the payload
|
||||
// the key was computed for is written again rather than trusted to still be
|
||||
// on disk.
|
||||
try {
|
||||
fs__WEBPACK_IMPORTED_MODULE_1___default().mkdirSync(resolution.path, { recursive: true });
|
||||
fs__WEBPACK_IMPORTED_MODULE_1___default().writeFileSync(path__WEBPACK_IMPORTED_MODULE_2___default().join(resolution.path, RESOLUTION_FILE_NAME), resolution.release);
|
||||
}
|
||||
catch (error) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Failed to write the JDK resolution cache entry for the key ${resolution.key}: ${getErrorMessage(error)}`);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
await _actions_cache__WEBPACK_IMPORTED_MODULE_3__/* .saveCache */ .Io([resolution.path], resolution.key);
|
||||
}
|
||||
catch (error) {
|
||||
// A matrix of jobs resolving the same JDK races on the same daily key, so
|
||||
// an already-reserved key is the expected outcome rather than a problem.
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Failed to save the JDK resolution cache with the key ${resolution.key}: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
function getResolutionCachePath(request) {
|
||||
const runnerTemp = process.env['RUNNER_TEMP'];
|
||||
if (!runnerTemp) {
|
||||
return undefined;
|
||||
}
|
||||
return path.join(runnerTemp, RESOLUTION_DIRECTORY, getResolutionIdentity(request));
|
||||
}
|
||||
function getResolutionIdentity(request) {
|
||||
const identity = JSON.stringify({
|
||||
keyVersion: JDK_RESOLUTION_KEY_VERSION,
|
||||
runnerOs: getRunnerOs(),
|
||||
distribution: request.distribution.toLowerCase(),
|
||||
packageType: request.packageType.toLowerCase(),
|
||||
architecture: request.architecture.toLowerCase(),
|
||||
versionSpec: request.versionSpec,
|
||||
stable: request.stable
|
||||
});
|
||||
return createHash('sha256').update(identity).digest('hex');
|
||||
}
|
||||
function getResolutionKeyPrefix(request) {
|
||||
const architecture = request.architecture.toLowerCase();
|
||||
const digest = getResolutionIdentity(request);
|
||||
return `setup-java-jdkres-v${JDK_RESOLUTION_KEY_VERSION}-${getRunnerOs()}-${architecture}-${digest}-`;
|
||||
}
|
||||
function getRunnerOs() {
|
||||
return process.env['RUNNER_OS'] ?? process.platform;
|
||||
}
|
||||
/**
|
||||
* Start of the seven-day window the entry was resolved in, which bounds how long
|
||||
* a floating version spec such as `21` can keep resolving to an already known
|
||||
* release.
|
||||
*
|
||||
* Seven days is the longest usable window: GitHub evicts cache entries that have
|
||||
* not been accessed for seven days, so a longer one would mean the previous
|
||||
* entry is already gone when the window rolls over, taking the stale-fallback
|
||||
* path with it. It also comfortably covers the real release cadence, which is
|
||||
* monthly at its fastest and usually quarterly.
|
||||
*/
|
||||
function getFreshnessBucket() {
|
||||
const week = 7 * 24 * 60 * 60 * 1000;
|
||||
return new Date(Math.floor(Date.now() / week) * week)
|
||||
.toISOString()
|
||||
.slice(0, 10);
|
||||
}
|
||||
/**
|
||||
* The restored payload drives a download, so it is validated as untrusted input
|
||||
* rather than trusted because it came back from the cache service.
|
||||
*/
|
||||
function parseResolvedRelease(contents) {
|
||||
const value = JSON.parse(contents);
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
throw new Error('The cached resolution is not an object.');
|
||||
}
|
||||
const candidate = value;
|
||||
const version = candidate['version'];
|
||||
const url = candidate['url'];
|
||||
const signatureUrl = candidate['signatureUrl'];
|
||||
if (typeof version !== 'string' || !version) {
|
||||
throw new Error('The cached resolution has no version.');
|
||||
}
|
||||
assertHttpsUrl(url, 'url');
|
||||
if (signatureUrl !== undefined) {
|
||||
assertHttpsUrl(signatureUrl, 'signatureUrl');
|
||||
}
|
||||
const release = {
|
||||
version,
|
||||
url: url
|
||||
};
|
||||
if (signatureUrl !== undefined) {
|
||||
release.signatureUrl = signatureUrl;
|
||||
}
|
||||
const checksum = candidate['checksum'];
|
||||
if (checksum !== undefined) {
|
||||
release.checksum = parseChecksum(checksum);
|
||||
}
|
||||
return release;
|
||||
}
|
||||
function parseChecksum(value) {
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
throw new Error('The cached checksum is not an object.');
|
||||
}
|
||||
const candidate = value;
|
||||
const algorithm = candidate['algorithm'];
|
||||
const checksumValue = candidate['value'];
|
||||
const source = candidate['source'];
|
||||
if (algorithm !== 'sha256' && algorithm !== 'sha512') {
|
||||
throw new Error(`Unsupported cached checksum algorithm: ${algorithm}`);
|
||||
}
|
||||
if (typeof checksumValue !== 'string' || !checksumValue) {
|
||||
throw new Error('The cached checksum has no value.');
|
||||
}
|
||||
if (source !== undefined && typeof source !== 'string') {
|
||||
throw new Error('The cached checksum source is not a string.');
|
||||
}
|
||||
const checksum = { algorithm, value: checksumValue };
|
||||
if (source !== undefined) {
|
||||
checksum.source = source;
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
function assertHttpsUrl(value, field) {
|
||||
if (typeof value !== 'string' || !value) {
|
||||
throw new Error(`The cached resolution has no ${field}.`);
|
||||
}
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(value);
|
||||
}
|
||||
catch {
|
||||
throw new Error(`The cached resolution has a malformed ${field}.`);
|
||||
}
|
||||
if (parsed.protocol !== 'https:') {
|
||||
throw new Error(`The cached resolution ${field} does not use HTTPS: ${parsed.protocol}`);
|
||||
}
|
||||
}
|
||||
function parseJdkResolutionState(state) {
|
||||
const value = JSON.parse(state);
|
||||
if (!Array.isArray(value) ||
|
||||
!value.every(item => typeof item === 'object' &&
|
||||
item !== null &&
|
||||
typeof item.key === 'string' &&
|
||||
typeof item.path === 'string' &&
|
||||
typeof item.release === 'string')) {
|
||||
throw new Error('Invalid JDK resolution information retrieved from state.');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function getErrorMessage(error) {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
Vendored
+4
-30
@@ -59543,7 +59543,7 @@ function combine(acc, pre, values, max, maxLength, dropEmpties) {
|
||||
}
|
||||
// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
|
||||
// sequence body.
|
||||
function expandSequence(body, isAlphaSequence, max, maxLength) {
|
||||
function expandSequence(body, isAlphaSequence, max) {
|
||||
const n = body.split(/\.\./);
|
||||
const N = [];
|
||||
// A sequence body always splits into two or three parts, but the compiler
|
||||
@@ -59566,7 +59566,6 @@ function expandSequence(body, isAlphaSequence, max, maxLength) {
|
||||
test = gte;
|
||||
}
|
||||
const pad = n.some(isPadded);
|
||||
let length = 0;
|
||||
for (let i = x; test(i, y) && N.length < max; i += incr) {
|
||||
let c;
|
||||
if (isAlphaSequence) {
|
||||
@@ -59590,10 +59589,7 @@ function expandSequence(body, isAlphaSequence, max, maxLength) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (length + c.length > maxLength)
|
||||
break;
|
||||
N.push(c);
|
||||
length += c.length;
|
||||
}
|
||||
return N;
|
||||
}
|
||||
@@ -59647,7 +59643,7 @@ function expand_(str, max, maxLength, isTop) {
|
||||
}
|
||||
let values;
|
||||
if (isSequence) {
|
||||
values = expandSequence(m.body, isAlphaSequence, max, maxLength);
|
||||
values = expandSequence(m.body, isAlphaSequence, max);
|
||||
}
|
||||
else {
|
||||
let n = parseCommaParts(m.body);
|
||||
@@ -59665,31 +59661,9 @@ function expand_(str, max, maxLength, isTop) {
|
||||
}
|
||||
/* c8 ignore stop */
|
||||
}
|
||||
// Values that `combine` is going to drop as empty produce no result, so
|
||||
// they must not count against `max` - otherwise `{a,,b}` with `max: 2`
|
||||
// would stop at `['a', '']` and yield one result instead of two. Skipping
|
||||
// them outright keeps `values` bounded while leaving `max` a bound on
|
||||
// *kept* results.
|
||||
let dropsEmpties = dropEmpties && !m.post.length && !pre;
|
||||
for (let d = 0; dropsEmpties && d < acc.length; d++) {
|
||||
if (acc[d]) {
|
||||
dropsEmpties = false;
|
||||
}
|
||||
}
|
||||
values = [];
|
||||
let valuesLength = 0;
|
||||
outer: for (let j = 0; j < n.length; j++) {
|
||||
const expanded = expand_(n[j], max, maxLength, false);
|
||||
for (let k = 0; k < expanded.length; k++) {
|
||||
const v = expanded[k];
|
||||
if (dropsEmpties && !v)
|
||||
continue;
|
||||
if (values.length >= max || valuesLength + v.length > maxLength) {
|
||||
break outer;
|
||||
}
|
||||
values.push(v);
|
||||
valuesLength += v.length;
|
||||
}
|
||||
for (let j = 0; j < n.length; j++) {
|
||||
values.push.apply(values, expand_(n[j], max, maxLength, false));
|
||||
}
|
||||
}
|
||||
acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
|
||||
|
||||
Vendored
+581
-768
File diff suppressed because it is too large
Load Diff
Vendored
+17
-15
@@ -9,19 +9,21 @@ export const modules = {
|
||||
/* harmony export */ CorrettoDistribution: () => (/* binding */ CorrettoDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const CORRETTO_VERSIONS_URL = 'https://corretto.github.io/corretto-downloads/latest_links/indexmap_with_checksum.json';
|
||||
class CorrettoDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
class CorrettoDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('Corretto', installerOptions);
|
||||
}
|
||||
@@ -29,15 +31,15 @@ class CorrettoDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
let javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_3__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .getDownloadArchiveExtension */ .ag)();
|
||||
if (process.platform === 'win32') {
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_3__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_3__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_1___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(extractedJavaPath, archiveName);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_3__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async findPackageForDownload(version) {
|
||||
@@ -64,7 +66,7 @@ class CorrettoDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4
|
||||
.filter(item => item.version == version)
|
||||
.map(item => {
|
||||
return {
|
||||
version: (0,_util_js__WEBPACK_IMPORTED_MODULE_3__/* .convertVersionToSemver */ .ZY)(item.correttoVersion),
|
||||
version: (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .convertVersionToSemver */ .ZY)(item.correttoVersion),
|
||||
url: item.downloadLink,
|
||||
checksum: {
|
||||
algorithm: 'sha256',
|
||||
@@ -110,7 +112,7 @@ class CorrettoDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4
|
||||
for (const version in eligibleVersions) {
|
||||
const availableVersion = eligibleVersions[version];
|
||||
for (const fileType in availableVersion) {
|
||||
const skipNonExtractableBinaries = fileType != (0,_util_js__WEBPACK_IMPORTED_MODULE_3__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const skipNonExtractableBinaries = fileType != (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .getDownloadArchiveExtension */ .ag)();
|
||||
if (skipNonExtractableBinaries) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vendored
+19
-17
@@ -9,14 +9,16 @@ export const modules = {
|
||||
/* harmony export */ KonaDistribution: () => (/* binding */ KonaDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +26,7 @@ export const modules = {
|
||||
|
||||
|
||||
const KONA_RELEASES_URL = 'https://tencent.github.io/konajdk/releases/kona-v1.json';
|
||||
class KonaDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
class KonaDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('Kona', installerOptions);
|
||||
}
|
||||
@@ -32,15 +34,15 @@ class KonaDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Kona JDK ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
const javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const archivePath = process.platform === 'win32'
|
||||
? (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .renameWinArchive */ .n2)(javaArchivePath)
|
||||
? (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .renameWinArchive */ .n2)(javaArchivePath)
|
||||
: javaArchivePath;
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(archivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const jdkDirectory = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .extractJdkFile */ .PE)(archivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_3___default().readdirSync(extractedJavaPath)[0];
|
||||
const jdkDirectory = path__WEBPACK_IMPORTED_MODULE_4___default().join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .cacheJdkDir */ .Vj)(jdkDirectory, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(jdkDirectory, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async findPackageForDownload(version) {
|
||||
@@ -53,7 +55,7 @@ class KonaDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
|
||||
const availableReleases = await this.getAvailableReleases();
|
||||
const releases = availableReleases
|
||||
.filter(item => {
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .isVersionSatisfies */ .y)(version, item.version);
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .isVersionSatisfies */ .y)(version, item.version);
|
||||
})
|
||||
.map(item => {
|
||||
return {
|
||||
@@ -68,7 +70,7 @@ class KonaDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
|
||||
: undefined
|
||||
};
|
||||
})
|
||||
.sort((a, b) => -semver__WEBPACK_IMPORTED_MODULE_1___default().compareBuild(a.version, b.version));
|
||||
.sort((a, b) => -semver__WEBPACK_IMPORTED_MODULE_2___default().compareBuild(a.version, b.version));
|
||||
if (!releases.length) {
|
||||
throw new Error(`No Kona release for the specified version "${version}" on OS "${this.getOs()}" and arch "${this.getArch()}".`);
|
||||
}
|
||||
|
||||
Vendored
+21
-21
@@ -9,13 +9,15 @@ export const modules = {
|
||||
/* harmony export */ OracleDistribution: () => (/* binding */ OracleDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_http_client__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4942);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_http_client__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4942);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +25,7 @@ export const modules = {
|
||||
|
||||
|
||||
const ORACLE_DL_BASE = 'https://download.oracle.com/java';
|
||||
class OracleDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaBase */ .O {
|
||||
class OracleDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('Oracle', installerOptions);
|
||||
}
|
||||
@@ -31,15 +33,15 @@ class OracleDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
let javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
|
||||
if (process.platform === 'win32') {
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_1___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(extractedJavaPath, archiveName);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async findPackageForDownload(range) {
|
||||
@@ -54,12 +56,12 @@ class OracleDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__
|
||||
throw new Error('Oracle JDK provides only the `jdk` package type');
|
||||
}
|
||||
const platform = this.getPlatform();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
|
||||
// The `latest` alias is normalized to the SemVer wildcard. Oracle builds its
|
||||
// download URLs from a concrete major and has no endpoint to list releases,
|
||||
// so resolve the newest available GA major from the Adoptium API and use it.
|
||||
if (this.latest) {
|
||||
const latestMajor = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .getLatestMajorVersion */ .ri)(this.http);
|
||||
const latestMajor = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getLatestMajorVersion */ .ri)(this.http);
|
||||
range = latestMajor.toString();
|
||||
}
|
||||
const isOnlyMajorProvided = !range.includes('.');
|
||||
@@ -75,22 +77,20 @@ class OracleDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__
|
||||
if (isOnlyMajorProvided) {
|
||||
possibleUrls.push(`${ORACLE_DL_BASE}/${major}/latest/jdk-${major}_${platform}-${arch}_bin.${extension}`);
|
||||
}
|
||||
const floatingUrl = isOnlyMajorProvided ? possibleUrls[0] : undefined;
|
||||
possibleUrls.push(`${ORACLE_DL_BASE}/${major}/archive/jdk-${range}_${platform}-${arch}_bin.${extension}`);
|
||||
if (parseInt(major) < 17) {
|
||||
throw new Error('Oracle JDK is only supported for JDK 17 and later');
|
||||
}
|
||||
for (const url of possibleUrls) {
|
||||
const response = await this.http.head(url);
|
||||
if (response.message.statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_5__/* .HttpCodes */ .Hv.OK) {
|
||||
if (response.message.statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.OK) {
|
||||
return {
|
||||
url,
|
||||
version: range,
|
||||
checksum: await this.fetchChecksum(`${url}.sha256`, 'sha256'),
|
||||
floating: url === floatingUrl
|
||||
checksum: await this.fetchChecksum(`${url}.sha256`, 'sha256')
|
||||
};
|
||||
}
|
||||
if (response.message.statusCode !== _actions_http_client__WEBPACK_IMPORTED_MODULE_5__/* .HttpCodes */ .Hv.NotFound) {
|
||||
if (response.message.statusCode !== _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.NotFound) {
|
||||
throw new Error(`Http request for Oracle JDK failed with status code: ${response.message.statusCode}`);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+27
-74
@@ -8,16 +8,15 @@ export const modules = {
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ LocalDistribution: () => (/* binding */ LocalDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9805);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7242);
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6982);
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_5__);
|
||||
|
||||
|
||||
|
||||
@@ -25,8 +24,7 @@ export const modules = {
|
||||
|
||||
|
||||
|
||||
|
||||
class LocalDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__/* .JavaBase */ .O {
|
||||
class LocalDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
jdkFile;
|
||||
constructor(installerOptions, jdkFile) {
|
||||
super('jdkfile', installerOptions);
|
||||
@@ -36,80 +34,42 @@ class LocalDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__/
|
||||
if (this.latest) {
|
||||
throw new Error("The 'latest' version alias is not supported for the 'jdkfile' distribution. Please specify a concrete version.");
|
||||
}
|
||||
if (this.verifySignature) {
|
||||
throw new Error(`Input 'verify-signature' is not supported for distribution '${this.distribution}'.`);
|
||||
}
|
||||
let foundJava = this.forceDownload ? null : this.findInToolcache();
|
||||
if (foundJava) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Resolved Java ${foundJava.version} from tool-cache`);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Resolved Java ${foundJava.version} from tool-cache`);
|
||||
}
|
||||
else {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Java ${this.version} was not found in tool-cache. Trying to unpack JDK file...`);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Java ${this.version} was not found in tool-cache. Trying to unpack JDK file...`);
|
||||
if (!this.jdkFile) {
|
||||
throw new Error("'jdkFile' is not specified");
|
||||
}
|
||||
const jdkFilePath = path__WEBPACK_IMPORTED_MODULE_2___default().resolve(this.jdkFile);
|
||||
const stats = fs__WEBPACK_IMPORTED_MODULE_1___default().statSync(jdkFilePath);
|
||||
const jdkFilePath = path__WEBPACK_IMPORTED_MODULE_3___default().resolve(this.jdkFile);
|
||||
const stats = fs__WEBPACK_IMPORTED_MODULE_2___default().statSync(jdkFilePath);
|
||||
if (!stats.isFile()) {
|
||||
throw new Error(`JDK file was not found in path '${jdkFilePath}'`);
|
||||
}
|
||||
let jdkCache;
|
||||
if (this.cacheJdk) {
|
||||
const [{ getJdkVerificationIdentity }, source] = await Promise.all([
|
||||
Promise.all(/* import() */[__webpack_require__.e(824), __webpack_require__.e(971), __webpack_require__.e(779)]).then(__webpack_require__.bind(__webpack_require__, 5779)),
|
||||
hashFile(jdkFilePath)
|
||||
]);
|
||||
jdkCache = {
|
||||
distribution: this.distribution,
|
||||
packageType: this.packageType,
|
||||
architecture: this.architecture,
|
||||
version: this.version,
|
||||
source,
|
||||
verification: getJdkVerificationIdentity(false),
|
||||
path: this.getJdkCachePath(this.version)
|
||||
};
|
||||
}
|
||||
if (!this.forceDownload && jdkCache) {
|
||||
const { restoreJdk } = await Promise.all(/* import() */[__webpack_require__.e(824), __webpack_require__.e(971), __webpack_require__.e(779)]).then(__webpack_require__.bind(__webpack_require__, 5779));
|
||||
const restored = await restoreJdk(jdkCache);
|
||||
const restoredPath = restored
|
||||
? this.getRestoredJdkPath(this.version)
|
||||
: undefined;
|
||||
if (restoredPath) {
|
||||
foundJava = {
|
||||
version: this.version,
|
||||
path: restoredPath
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!foundJava) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java from '${jdkFilePath}'`);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .extractJdkFile */ .PE)(jdkFilePath);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_1___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(extractedJavaPath, archiveName);
|
||||
const javaVersion = this.version;
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaVersion), this.architecture);
|
||||
foundJava = {
|
||||
version: javaVersion,
|
||||
path: javaPath
|
||||
};
|
||||
if (jdkCache) {
|
||||
const { registerJdk } = await Promise.all(/* import() */[__webpack_require__.e(824), __webpack_require__.e(971), __webpack_require__.e(779)]).then(__webpack_require__.bind(__webpack_require__, 5779));
|
||||
registerJdk(jdkCache);
|
||||
}
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Extracting Java from '${jdkFilePath}'`);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(jdkFilePath);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const javaVersion = this.version;
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_0__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaVersion), this.architecture);
|
||||
foundJava = {
|
||||
version: javaVersion,
|
||||
path: javaPath
|
||||
};
|
||||
}
|
||||
// JDK folder may contain postfix "Contents/Home" on macOS
|
||||
const macOSPostfixPath = path__WEBPACK_IMPORTED_MODULE_2___default().join(foundJava.path, _constants_js__WEBPACK_IMPORTED_MODULE_6__/* .MACOS_JAVA_CONTENT_POSTFIX */ .PG);
|
||||
if (process.platform === 'darwin' && fs__WEBPACK_IMPORTED_MODULE_1___default().existsSync(macOSPostfixPath)) {
|
||||
const macOSPostfixPath = path__WEBPACK_IMPORTED_MODULE_3___default().join(foundJava.path, _constants_js__WEBPACK_IMPORTED_MODULE_6__/* .MACOS_JAVA_CONTENT_POSTFIX */ .PG);
|
||||
if (process.platform === 'darwin' && fs__WEBPACK_IMPORTED_MODULE_2___default().existsSync(macOSPostfixPath)) {
|
||||
foundJava.path = macOSPostfixPath;
|
||||
}
|
||||
if (this.setDefault) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Setting Java ${foundJava.version} as the default`);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Setting Java ${foundJava.version} as the default`);
|
||||
this.setJavaDefault(foundJava.version, foundJava.path);
|
||||
}
|
||||
else {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Installing Java ${foundJava.version} (not setting as default)`);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Installing Java ${foundJava.version} (not setting as default)`);
|
||||
this.setJavaEnvironment(foundJava.version, foundJava.path);
|
||||
}
|
||||
return foundJava;
|
||||
@@ -123,13 +83,6 @@ class LocalDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_3__/
|
||||
throw new Error('This method should not be implemented in local file provider');
|
||||
}
|
||||
}
|
||||
async function hashFile(file) {
|
||||
const hash = (0,crypto__WEBPACK_IMPORTED_MODULE_5__.createHash)('sha256');
|
||||
for await (const chunk of (0,fs__WEBPACK_IMPORTED_MODULE_1__.createReadStream)(file)) {
|
||||
hash.update(chunk);
|
||||
}
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
Vendored
+1
-1
@@ -89,7 +89,7 @@ class MicrosoftDistributions extends base_installer/* JavaBase */.O {
|
||||
const extractedJavaPath = await (0,util/* extractJdkFile */.PE)(javaArchivePath, extension);
|
||||
const archiveName = external_fs_default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = external_path_default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await (0,util/* cacheJdkDir */.Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
const javaPath = await tool_cache/* cacheDir */.e8(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async findPackageForDownload(range) {
|
||||
|
||||
Vendored
+4
-120
@@ -217,7 +217,6 @@ class JavaBase {
|
||||
latest;
|
||||
checkLatest;
|
||||
forceDownload;
|
||||
cacheJdk;
|
||||
setDefault;
|
||||
verifySignature;
|
||||
verifySignaturePublicKey;
|
||||
@@ -233,7 +232,6 @@ class JavaBase {
|
||||
this.packageType = installerOptions.packageType;
|
||||
this.checkLatest = installerOptions.checkLatest;
|
||||
this.forceDownload = installerOptions.forceDownload ?? false;
|
||||
this.cacheJdk = installerOptions.cacheJdk ?? false;
|
||||
this.setDefault =
|
||||
installerOptions.setDefault !== undefined
|
||||
? installerOptions.setDefault
|
||||
@@ -322,50 +320,15 @@ class JavaBase {
|
||||
else {
|
||||
core/* info */.pq('Trying to resolve the latest version from remote');
|
||||
try {
|
||||
const javaRelease = await this.resolveJavaRelease();
|
||||
const javaRelease = await this.findPackageForDownload(this.version);
|
||||
core/* info */.pq(`Resolved latest version as ${javaRelease.version}`);
|
||||
if (!this.forceDownload && foundJava?.version === javaRelease.version) {
|
||||
core/* info */.pq(`Resolved Java ${foundJava.version} from tool-cache`);
|
||||
}
|
||||
else {
|
||||
let jdkCache;
|
||||
if (this.cacheJdk) {
|
||||
const { getJdkVerificationIdentity } = await Promise.all(/* import() */[__webpack_require__.e(824), __webpack_require__.e(971), __webpack_require__.e(779)]).then(__webpack_require__.bind(__webpack_require__, 5779));
|
||||
jdkCache = {
|
||||
distribution: this.distribution,
|
||||
packageType: this.packageType,
|
||||
architecture: this.architecture,
|
||||
version: javaRelease.version,
|
||||
source: this.getJdkReleaseIdentity(javaRelease),
|
||||
verification: getJdkVerificationIdentity(this.verifySignature, this.verifySignaturePublicKey),
|
||||
path: this.getJdkCachePath(javaRelease.version)
|
||||
};
|
||||
}
|
||||
if (!this.forceDownload && jdkCache) {
|
||||
const { restoreJdk } = await Promise.all(/* import() */[__webpack_require__.e(824), __webpack_require__.e(971), __webpack_require__.e(779)]).then(__webpack_require__.bind(__webpack_require__, 5779));
|
||||
const restored = await restoreJdk(jdkCache);
|
||||
if (restored) {
|
||||
const restoredPath = this.getRestoredJdkPath(javaRelease.version);
|
||||
if (restoredPath) {
|
||||
foundJava = {
|
||||
version: javaRelease.version,
|
||||
path: restoredPath
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundJava || foundJava.version !== javaRelease.version) {
|
||||
core/* info */.pq('Trying to download...');
|
||||
foundJava = await this.downloadTool(javaRelease);
|
||||
core/* info */.pq(`Java ${foundJava.version} was downloaded`);
|
||||
if (jdkCache) {
|
||||
// Register after the installation exists so its identity is
|
||||
// captured; the post-job save refuses to upload a path whose
|
||||
// installation was replaced afterwards.
|
||||
const { registerJdk } = await Promise.all(/* import() */[__webpack_require__.e(824), __webpack_require__.e(971), __webpack_require__.e(779)]).then(__webpack_require__.bind(__webpack_require__, 5779));
|
||||
registerJdk(jdkCache);
|
||||
}
|
||||
}
|
||||
core/* info */.pq('Trying to download...');
|
||||
foundJava = await this.downloadTool(javaRelease);
|
||||
core/* info */.pq(`Java ${foundJava.version} was downloaded`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@@ -391,55 +354,6 @@ class JavaBase {
|
||||
}
|
||||
return foundJava;
|
||||
}
|
||||
/**
|
||||
* Resolves the release to install, preferring a cached resolution over the
|
||||
* distribution's metadata API.
|
||||
*
|
||||
* Only Temurin is preinstalled on hosted runners, so for every other
|
||||
* distribution the tool-cache lookup misses and the vendor API becomes a
|
||||
* per-job dependency even when the JDK itself is already in the GitHub
|
||||
* Actions cache. A cached resolution removes that dependency, and because it
|
||||
* carries the download URL and checksum it also keeps a job working when the
|
||||
* vendor API is unavailable but the JDK still has to be downloaded.
|
||||
*/
|
||||
async resolveJavaRelease() {
|
||||
if (!this.cacheJdk ||
|
||||
this.checkLatest ||
|
||||
this.latest ||
|
||||
this.forceDownload) {
|
||||
return this.findPackageForDownload(this.version);
|
||||
}
|
||||
const { restoreJdkResolution, registerJdkResolution } = await Promise.all(/* import() */[__webpack_require__.e(824), __webpack_require__.e(971), __webpack_require__.e(348)]).then(__webpack_require__.bind(__webpack_require__, 967));
|
||||
const request = {
|
||||
distribution: this.distribution,
|
||||
packageType: this.packageType,
|
||||
architecture: this.architecture,
|
||||
versionSpec: this.version,
|
||||
stable: this.stable
|
||||
};
|
||||
const restored = await restoreJdkResolution(request);
|
||||
if (restored?.fresh) {
|
||||
core/* info */.pq(`Resolved ${this.distribution} ${restored.release.version} from the resolution cache`);
|
||||
return restored.release;
|
||||
}
|
||||
try {
|
||||
const javaRelease = await this.findPackageForDownload(this.version);
|
||||
if (!javaRelease.floating) {
|
||||
registerJdkResolution(request, javaRelease);
|
||||
}
|
||||
return javaRelease;
|
||||
}
|
||||
catch (error) {
|
||||
if (!restored) {
|
||||
throw error;
|
||||
}
|
||||
// The cached resolution is older than the current bucket, but falling
|
||||
// back to it is strictly better than failing the job because the vendor
|
||||
// metadata API is down.
|
||||
core/* warning */.$e(`Failed to resolve ${this.distribution} ${this.version} from remote (${error instanceof Error ? error.message : String(error)}); falling back to the cached resolution for ${restored.release.version}.`);
|
||||
return restored.release;
|
||||
}
|
||||
}
|
||||
logSetupError(error) {
|
||||
const httpStatusCode = error instanceof tool_cache/* HTTPError */.Hl
|
||||
? error.httpStatusCode
|
||||
@@ -521,36 +435,6 @@ class JavaBase {
|
||||
// related issue: https://github.com/actions/virtual-environments/issues/3014
|
||||
return version.replace('+', '-');
|
||||
}
|
||||
getJdkCachePath(version) {
|
||||
const toolCache = process.env['RUNNER_TOOL_CACHE'];
|
||||
if (!toolCache) {
|
||||
return '';
|
||||
}
|
||||
return external_path_default().join(toolCache, this.toolcacheFolderName, this.getToolcacheVersionName(version));
|
||||
}
|
||||
getRestoredJdkPath(version) {
|
||||
const basePath = this.getJdkCachePath(version);
|
||||
if (!basePath) {
|
||||
return null;
|
||||
}
|
||||
const architecturePath = external_path_default().join(basePath, this.architecture);
|
||||
return external_fs_.existsSync(architecturePath) &&
|
||||
external_fs_.existsSync(`${architecturePath}.complete`)
|
||||
? architecturePath
|
||||
: null;
|
||||
}
|
||||
getJdkReleaseIdentity(javaRelease) {
|
||||
if (javaRelease.checksum) {
|
||||
return `${javaRelease.checksum.algorithm}:${javaRelease.checksum.value}`;
|
||||
}
|
||||
try {
|
||||
const url = new URL(javaRelease.url);
|
||||
return `${url.origin}${url.pathname}`;
|
||||
}
|
||||
catch {
|
||||
return javaRelease.url;
|
||||
}
|
||||
}
|
||||
findInToolcache() {
|
||||
// we can't use tc.find directly because firstly, we need to filter versions by stability flag
|
||||
// if *-ea is provided, take only ea versions from toolcache, otherwise - only stable versions
|
||||
|
||||
Vendored
+20
-18
@@ -9,15 +9,16 @@ export const modules = {
|
||||
/* harmony export */ JetBrainsDistribution: () => (/* binding */ JetBrainsDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_http_client__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4942);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_http_client__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(4942);
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +26,8 @@ export const modules = {
|
||||
|
||||
|
||||
|
||||
class JetBrainsDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
|
||||
class JetBrainsDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('JetBrains', installerOptions);
|
||||
}
|
||||
@@ -39,9 +41,9 @@ class JetBrainsDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
|
||||
};
|
||||
});
|
||||
const satisfiedVersions = versions
|
||||
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .isVersionSatisfies */ .y)(range, item.version))
|
||||
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .isVersionSatisfies */ .y)(range, item.version))
|
||||
.sort((a, b) => {
|
||||
return -semver__WEBPACK_IMPORTED_MODULE_3___default().compareBuild(a.version, b.version);
|
||||
return -semver__WEBPACK_IMPORTED_MODULE_4___default().compareBuild(a.version, b.version);
|
||||
});
|
||||
const resolvedFullVersion = satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
|
||||
if (!resolvedFullVersion) {
|
||||
@@ -61,11 +63,11 @@ class JetBrainsDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
const javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(javaArchivePath, 'tar.gz');
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_1___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(extractedJavaPath, archiveName);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .extractJdkFile */ .PE)(javaArchivePath, 'tar.gz');
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async getAvailableVersions() {
|
||||
@@ -154,13 +156,13 @@ class JetBrainsDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
|
||||
let url = `https://cache-redirector.jetbrains.com/intellij-jbr/${type}-${semver}-${platform}-${arch}-b${build}.tar.gz`;
|
||||
let include = false;
|
||||
const res = await this.http.head(url);
|
||||
if (res.message.statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.OK) {
|
||||
if (res.message.statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_7__/* .HttpCodes */ .Hv.OK) {
|
||||
include = true;
|
||||
}
|
||||
else {
|
||||
url = `https://cache-redirector.jetbrains.com/intellij-jbr/${type}_nomod-${semver}-${platform}-${arch}-b${build}.tar.gz`;
|
||||
const res2 = await this.http.head(url);
|
||||
if (res2.message.statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.OK) {
|
||||
if (res2.message.statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_7__/* .HttpCodes */ .Hv.OK) {
|
||||
include = true;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-271
@@ -1,271 +0,0 @@
|
||||
export const id = 348;
|
||||
export const ids = [348];
|
||||
export const modules = {
|
||||
|
||||
/***/ 967:
|
||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ registerJdkResolution: () => (/* binding */ registerJdkResolution),
|
||||
/* harmony export */ restoreJdkResolution: () => (/* binding */ restoreJdkResolution)
|
||||
/* harmony export */ });
|
||||
/* unused harmony export saveJdkResolutionCaches */
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6982);
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6971);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3838);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const STATE_JDK_RESOLUTIONS = 'jdk-resolutions';
|
||||
const JDK_RESOLUTION_KEY_VERSION = 1;
|
||||
const RESOLUTION_DIRECTORY = 'setup-java-jdk-resolution';
|
||||
const RESOLUTION_FILE_NAME = 'release.json';
|
||||
const pendingResolutions = [];
|
||||
/**
|
||||
* Restores a previously resolved release so a distribution can skip its vendor
|
||||
* metadata API.
|
||||
*
|
||||
* The cache path deliberately excludes the freshness window: `@actions/cache`
|
||||
* derives
|
||||
* a cache version by hashing the requested paths, so a bucket-independent path
|
||||
* is what allows the restore keys to fall back to an older bucket.
|
||||
*/
|
||||
async function restoreJdkResolution(request) {
|
||||
// Deliberately not `isCacheFeatureAvailable()`: this is an optional
|
||||
// optimization, and the JDK cache already warns once when the service is
|
||||
// unreachable.
|
||||
if (!_actions_cache__WEBPACK_IMPORTED_MODULE_3__/* .isFeatureAvailable */ .w3()) {
|
||||
return undefined;
|
||||
}
|
||||
const cachePath = getResolutionCachePath(request);
|
||||
if (!cachePath) {
|
||||
return undefined;
|
||||
}
|
||||
const keyPrefix = getResolutionKeyPrefix(request);
|
||||
const primaryKey = `${keyPrefix}${getFreshnessBucket()}`;
|
||||
let matchedKey;
|
||||
try {
|
||||
matchedKey = await _actions_cache__WEBPACK_IMPORTED_MODULE_3__/* .restoreCache */ .P3([cachePath], primaryKey, [keyPrefix]);
|
||||
}
|
||||
catch (error) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Failed to restore the JDK resolution cache: ${getErrorMessage(error)}`);
|
||||
return undefined;
|
||||
}
|
||||
if (!matchedKey) {
|
||||
return undefined;
|
||||
}
|
||||
let release;
|
||||
try {
|
||||
const contents = fs__WEBPACK_IMPORTED_MODULE_1___default().readFileSync(path__WEBPACK_IMPORTED_MODULE_2___default().join(cachePath, RESOLUTION_FILE_NAME), 'utf8');
|
||||
release = parseResolvedRelease(contents);
|
||||
}
|
||||
catch (error) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Ignoring the JDK resolution cache entry ${matchedKey}: ${getErrorMessage(error)}`);
|
||||
return undefined;
|
||||
}
|
||||
return { release, fresh: matchedKey === primaryKey };
|
||||
}
|
||||
/**
|
||||
* Persists a freshly resolved release for later jobs. The entry is written to
|
||||
* disk immediately and uploaded by the post-job step.
|
||||
*/
|
||||
function registerJdkResolution(request, release) {
|
||||
if (!_actions_cache__WEBPACK_IMPORTED_MODULE_3__/* .isFeatureAvailable */ .w3()) {
|
||||
return;
|
||||
}
|
||||
const cachePath = getResolutionCachePath(request);
|
||||
if (!cachePath) {
|
||||
return;
|
||||
}
|
||||
const payload = JSON.stringify(release);
|
||||
try {
|
||||
fs__WEBPACK_IMPORTED_MODULE_1___default().mkdirSync(cachePath, { recursive: true });
|
||||
fs__WEBPACK_IMPORTED_MODULE_1___default().writeFileSync(path__WEBPACK_IMPORTED_MODULE_2___default().join(cachePath, RESOLUTION_FILE_NAME), payload);
|
||||
}
|
||||
catch (error) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Failed to record the JDK resolution cache entry: ${getErrorMessage(error)}`);
|
||||
return;
|
||||
}
|
||||
const key = `${getResolutionKeyPrefix(request)}${getFreshnessBucket()}`;
|
||||
if (!pendingResolutions.some(item => item.key === key)) {
|
||||
pendingResolutions.push({ key, path: cachePath, release: payload });
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .saveState */ .LZ(STATE_JDK_RESOLUTIONS, JSON.stringify(pendingResolutions));
|
||||
}
|
||||
async function saveJdkResolutionCaches() {
|
||||
const state = core.getState(STATE_JDK_RESOLUTIONS);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
let resolutions;
|
||||
try {
|
||||
resolutions = parseJdkResolutionState(state);
|
||||
}
|
||||
catch (error) {
|
||||
core.debug(`Invalid JDK resolution cache state, not saving: ${getErrorMessage(error)}`);
|
||||
return;
|
||||
}
|
||||
for (const resolution of resolutions) {
|
||||
// A restore performed by a later step overwrites this path, so the payload
|
||||
// the key was computed for is written again rather than trusted to still be
|
||||
// on disk.
|
||||
try {
|
||||
fs.mkdirSync(resolution.path, { recursive: true });
|
||||
fs.writeFileSync(path.join(resolution.path, RESOLUTION_FILE_NAME), resolution.release);
|
||||
}
|
||||
catch (error) {
|
||||
core.debug(`Failed to write the JDK resolution cache entry for the key ${resolution.key}: ${getErrorMessage(error)}`);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
await cache.saveCache([resolution.path], resolution.key);
|
||||
}
|
||||
catch (error) {
|
||||
// A matrix of jobs resolving the same JDK races on the same daily key, so
|
||||
// an already-reserved key is the expected outcome rather than a problem.
|
||||
core.debug(`Failed to save the JDK resolution cache with the key ${resolution.key}: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
function getResolutionCachePath(request) {
|
||||
const runnerTemp = process.env['RUNNER_TEMP'];
|
||||
if (!runnerTemp) {
|
||||
return undefined;
|
||||
}
|
||||
return path__WEBPACK_IMPORTED_MODULE_2___default().join(runnerTemp, RESOLUTION_DIRECTORY, getResolutionIdentity(request));
|
||||
}
|
||||
function getResolutionIdentity(request) {
|
||||
const identity = JSON.stringify({
|
||||
keyVersion: JDK_RESOLUTION_KEY_VERSION,
|
||||
runnerOs: getRunnerOs(),
|
||||
distribution: request.distribution.toLowerCase(),
|
||||
packageType: request.packageType.toLowerCase(),
|
||||
architecture: request.architecture.toLowerCase(),
|
||||
versionSpec: request.versionSpec,
|
||||
stable: request.stable
|
||||
});
|
||||
return (0,crypto__WEBPACK_IMPORTED_MODULE_0__.createHash)('sha256').update(identity).digest('hex');
|
||||
}
|
||||
function getResolutionKeyPrefix(request) {
|
||||
const architecture = request.architecture.toLowerCase();
|
||||
const digest = getResolutionIdentity(request);
|
||||
return `setup-java-jdkres-v${JDK_RESOLUTION_KEY_VERSION}-${getRunnerOs()}-${architecture}-${digest}-`;
|
||||
}
|
||||
function getRunnerOs() {
|
||||
return process.env['RUNNER_OS'] ?? process.platform;
|
||||
}
|
||||
/**
|
||||
* Start of the seven-day window the entry was resolved in, which bounds how long
|
||||
* a floating version spec such as `21` can keep resolving to an already known
|
||||
* release.
|
||||
*
|
||||
* Seven days is the longest usable window: GitHub evicts cache entries that have
|
||||
* not been accessed for seven days, so a longer one would mean the previous
|
||||
* entry is already gone when the window rolls over, taking the stale-fallback
|
||||
* path with it. It also comfortably covers the real release cadence, which is
|
||||
* monthly at its fastest and usually quarterly.
|
||||
*/
|
||||
function getFreshnessBucket() {
|
||||
const week = 7 * 24 * 60 * 60 * 1000;
|
||||
return new Date(Math.floor(Date.now() / week) * week)
|
||||
.toISOString()
|
||||
.slice(0, 10);
|
||||
}
|
||||
/**
|
||||
* The restored payload drives a download, so it is validated as untrusted input
|
||||
* rather than trusted because it came back from the cache service.
|
||||
*/
|
||||
function parseResolvedRelease(contents) {
|
||||
const value = JSON.parse(contents);
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
throw new Error('The cached resolution is not an object.');
|
||||
}
|
||||
const candidate = value;
|
||||
const version = candidate['version'];
|
||||
const url = candidate['url'];
|
||||
const signatureUrl = candidate['signatureUrl'];
|
||||
if (typeof version !== 'string' || !version) {
|
||||
throw new Error('The cached resolution has no version.');
|
||||
}
|
||||
assertHttpsUrl(url, 'url');
|
||||
if (signatureUrl !== undefined) {
|
||||
assertHttpsUrl(signatureUrl, 'signatureUrl');
|
||||
}
|
||||
const release = {
|
||||
version,
|
||||
url: url
|
||||
};
|
||||
if (signatureUrl !== undefined) {
|
||||
release.signatureUrl = signatureUrl;
|
||||
}
|
||||
const checksum = candidate['checksum'];
|
||||
if (checksum !== undefined) {
|
||||
release.checksum = parseChecksum(checksum);
|
||||
}
|
||||
return release;
|
||||
}
|
||||
function parseChecksum(value) {
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
throw new Error('The cached checksum is not an object.');
|
||||
}
|
||||
const candidate = value;
|
||||
const algorithm = candidate['algorithm'];
|
||||
const checksumValue = candidate['value'];
|
||||
const source = candidate['source'];
|
||||
if (algorithm !== 'sha256' && algorithm !== 'sha512') {
|
||||
throw new Error(`Unsupported cached checksum algorithm: ${algorithm}`);
|
||||
}
|
||||
if (typeof checksumValue !== 'string' || !checksumValue) {
|
||||
throw new Error('The cached checksum has no value.');
|
||||
}
|
||||
if (source !== undefined && typeof source !== 'string') {
|
||||
throw new Error('The cached checksum source is not a string.');
|
||||
}
|
||||
const checksum = { algorithm, value: checksumValue };
|
||||
if (source !== undefined) {
|
||||
checksum.source = source;
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
function assertHttpsUrl(value, field) {
|
||||
if (typeof value !== 'string' || !value) {
|
||||
throw new Error(`The cached resolution has no ${field}.`);
|
||||
}
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(value);
|
||||
}
|
||||
catch {
|
||||
throw new Error(`The cached resolution has a malformed ${field}.`);
|
||||
}
|
||||
if (parsed.protocol !== 'https:') {
|
||||
throw new Error(`The cached resolution ${field} does not use HTTPS: ${parsed.protocol}`);
|
||||
}
|
||||
}
|
||||
function parseJdkResolutionState(state) {
|
||||
const value = JSON.parse(state);
|
||||
if (!Array.isArray(value) ||
|
||||
!value.every(item => typeof item === 'object' &&
|
||||
item !== null &&
|
||||
typeof item.key === 'string' &&
|
||||
typeof item.path === 'string' &&
|
||||
typeof item.release === 'string')) {
|
||||
throw new Error('Invalid JDK resolution information retrieved from state.');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function getErrorMessage(error) {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
Vendored
+4
-1
@@ -16,6 +16,8 @@ __webpack_require__.d(__webpack_exports__, {
|
||||
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js + 7 modules
|
||||
var core = __webpack_require__(3838);
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/tool-cache/lib/tool-cache.js + 2 modules
|
||||
var tool_cache = __webpack_require__(9805);
|
||||
// EXTERNAL MODULE: external "fs"
|
||||
var external_fs_ = __webpack_require__(9896);
|
||||
var external_fs_default = /*#__PURE__*/__webpack_require__.n(external_fs_);
|
||||
@@ -79,6 +81,7 @@ var util = __webpack_require__(4527);
|
||||
|
||||
|
||||
|
||||
|
||||
var TemurinImplementation;
|
||||
(function (TemurinImplementation) {
|
||||
TemurinImplementation["Hotspot"] = "Hotspot";
|
||||
@@ -147,7 +150,7 @@ class TemurinDistribution extends base_installer/* JavaBase */.O {
|
||||
await this.installJmods(javaRelease.version, javaHome);
|
||||
}
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,util/* cacheJdkDir */.Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await tool_cache/* cacheDir */.e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
supportsSignatureVerification() {
|
||||
|
||||
Vendored
+9
-7
@@ -13,10 +13,12 @@ export const modules = {
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_5__);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_5__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_6__);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -38,9 +40,9 @@ class LibericaNikDistributions extends _base_installer_js__WEBPACK_IMPORTED_MODU
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_4___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_5___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_5___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_6___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async findPackageForDownload(range) {
|
||||
|
||||
Vendored
+22
-20
@@ -9,21 +9,23 @@ export const modules = {
|
||||
/* harmony export */ SapMachineDistribution: () => (/* binding */ SapMachineDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(6242);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class SapMachineDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
|
||||
class SapMachineDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_6__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('SapMachine', installerOptions);
|
||||
}
|
||||
@@ -35,7 +37,7 @@ class SapMachineDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
const availableVersions = await this.getAvailableVersions();
|
||||
const matchedVersions = availableVersions
|
||||
.filter(item => {
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .isVersionSatisfies */ .y)(version, item.version);
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .isVersionSatisfies */ .y)(version, item.version);
|
||||
})
|
||||
.map(item => {
|
||||
return {
|
||||
@@ -77,15 +79,15 @@ class SapMachineDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
let javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
|
||||
if (process.platform === 'win32') {
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_3___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_4___default().join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
parseVersions(platform, arch, versions) {
|
||||
@@ -102,9 +104,9 @@ class SapMachineDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
if (buildVersionWithoutPrefix.split('.').length > 3) {
|
||||
buildVersionWithoutPrefix = buildVersionWithoutPrefix.replace('+', '.');
|
||||
}
|
||||
buildVersionWithoutPrefix = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__/* .convertVersionToSemver */ .ZY)(buildVersionWithoutPrefix);
|
||||
buildVersionWithoutPrefix = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .convertVersionToSemver */ .ZY)(buildVersionWithoutPrefix);
|
||||
// ignore invalid version
|
||||
if (!semver__WEBPACK_IMPORTED_MODULE_1___default().valid(buildVersionWithoutPrefix)) {
|
||||
if (!semver__WEBPACK_IMPORTED_MODULE_2___default().valid(buildVersionWithoutPrefix)) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .debug */ .Yz(`Invalid version: ${buildVersionWithoutPrefix}`);
|
||||
continue;
|
||||
}
|
||||
@@ -151,7 +153,7 @@ class SapMachineDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
const sortedVersions = eligibleVersions.sort((versionObj1, versionObj2) => {
|
||||
const version1 = versionObj1.version;
|
||||
const version2 = versionObj2.version;
|
||||
return semver__WEBPACK_IMPORTED_MODULE_1___default().compareBuild(version1, version2);
|
||||
return semver__WEBPACK_IMPORTED_MODULE_2___default().compareBuild(version1, version2);
|
||||
});
|
||||
return sortedVersions.reverse();
|
||||
}
|
||||
@@ -163,7 +165,7 @@ class SapMachineDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
return 'macos';
|
||||
case 'linux':
|
||||
// figure out if alpine/musl
|
||||
if (fs__WEBPACK_IMPORTED_MODULE_2___default().existsSync('/etc/alpine-release')) {
|
||||
if (fs__WEBPACK_IMPORTED_MODULE_3___default().existsSync('/etc/alpine-release')) {
|
||||
return 'linux-musl';
|
||||
}
|
||||
return 'linux';
|
||||
|
||||
Vendored
+9
-7
@@ -13,10 +13,12 @@ export const modules = {
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_5__);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_5__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_6__);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -38,9 +40,9 @@ class LibericaDistributions extends _base_installer_js__WEBPACK_IMPORTED_MODULE_
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_4___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_5___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_5___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_6___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async findPackageForDownload(range) {
|
||||
|
||||
Vendored
+21
-19
@@ -9,21 +9,23 @@ export const modules = {
|
||||
/* harmony export */ DragonwellDistribution: () => (/* binding */ DragonwellDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DragonwellDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
|
||||
class DragonwellDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('Dragonwell', installerOptions);
|
||||
}
|
||||
@@ -37,7 +39,7 @@ class DragonwellDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
const availableVersions = await this.getAvailableVersions();
|
||||
const matchedVersions = availableVersions
|
||||
.filter(item => {
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .isVersionSatisfies */ .y)(version, item.jdk_version);
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .isVersionSatisfies */ .y)(version, item.jdk_version);
|
||||
})
|
||||
.map(item => {
|
||||
return {
|
||||
@@ -81,15 +83,15 @@ class DragonwellDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
let javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
|
||||
if (process.platform === 'win32') {
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_3___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_4___default().join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
parseVersions(platform, arch, dragonwellVersions) {
|
||||
@@ -114,7 +116,7 @@ class DragonwellDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
const jdkVersionNums = jdkVersion
|
||||
.replace('+', '.')
|
||||
.split('.');
|
||||
jdkVersion = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .convertVersionToSemver */ .ZY)(`${jdkVersionNums.slice(0, 3).join('.')}.${jdkVersionNums[jdkVersionNums.length - 1]}`);
|
||||
jdkVersion = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .convertVersionToSemver */ .ZY)(`${jdkVersionNums.slice(0, 3).join('.')}.${jdkVersionNums[jdkVersionNums.length - 1]}`);
|
||||
for (const edition in archMap) {
|
||||
eligibleVersions.push({
|
||||
os: platform,
|
||||
@@ -137,7 +139,7 @@ class DragonwellDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
const sortedVersions = eligibleVersions.sort((versionObj1, versionObj2) => {
|
||||
const version1 = versionObj1.jdk_version;
|
||||
const version2 = versionObj2.jdk_version;
|
||||
return semver__WEBPACK_IMPORTED_MODULE_1___default().compareBuild(version1, version2);
|
||||
return semver__WEBPACK_IMPORTED_MODULE_2___default().compareBuild(version1, version2);
|
||||
});
|
||||
return sortedVersions.reverse();
|
||||
}
|
||||
@@ -167,7 +169,7 @@ class DragonwellDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE
|
||||
const branch = 'main';
|
||||
const filePath = 'releases.json';
|
||||
const backupUrl = `https://api.github.com/repos/${owner}/${repository}/contents/${filePath}?ref=${branch}`;
|
||||
const headers = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getGitHubHttpHeaders */ .U_)();
|
||||
const headers = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getGitHubHttpHeaders */ .U_)();
|
||||
try {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .debug */ .Yz(`Trying to fetch available Dragonwell versions info from the backup url: ${backupUrl}`);
|
||||
const fetchedDragonwellJson = (await this.http.getJson(backupUrl, headers)).result;
|
||||
|
||||
Vendored
+19
-17
@@ -9,14 +9,16 @@ export const modules = {
|
||||
/* harmony export */ OpenJdkDistribution: () => (/* binding */ OpenJdkDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +26,7 @@ export const modules = {
|
||||
|
||||
|
||||
const OPENJDK_BASE_URL = 'https://jdk.java.net';
|
||||
class OpenJdkDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
class OpenJdkDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('Oracle OpenJDK', installerOptions);
|
||||
}
|
||||
@@ -39,8 +41,8 @@ class OpenJdkDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
const platform = this.getPlatform();
|
||||
const releases = await this.getAvailableVersions(platform, arch);
|
||||
const matchingReleases = releases
|
||||
.filter(release => (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .isVersionSatisfies */ .y)(range, release.version))
|
||||
.sort((left, right) => -semver__WEBPACK_IMPORTED_MODULE_3___default().compareBuild(left.version, right.version));
|
||||
.filter(release => (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .isVersionSatisfies */ .y)(range, release.version))
|
||||
.sort((left, right) => -semver__WEBPACK_IMPORTED_MODULE_4___default().compareBuild(left.version, right.version));
|
||||
if (!matchingReleases.length) {
|
||||
throw this.createVersionNotFoundError(range, releases.map(release => release.version), `Platform: ${platform}`);
|
||||
}
|
||||
@@ -56,12 +58,12 @@ class OpenJdkDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = javaRelease.url.endsWith('.zip') ? 'zip' : 'tar.gz';
|
||||
if (extension === 'zip') {
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_1___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async getAvailableVersions(platform, arch) {
|
||||
@@ -104,7 +106,7 @@ class OpenJdkDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
toSemver(version, urlBuild) {
|
||||
const [javaVersion, filenameBuild] = version.replace('-ea', '').split('+');
|
||||
const versionParts = javaVersion.split('.');
|
||||
const normalizedVersion = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .convertVersionToSemver */ .ZY)(versionParts.length === 1 ? `${javaVersion}.0.0` : javaVersion);
|
||||
const normalizedVersion = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .convertVersionToSemver */ .ZY)(versionParts.length === 1 ? `${javaVersion}.0.0` : javaVersion);
|
||||
const build = filenameBuild ?? (versionParts.length <= 3 ? urlBuild : undefined);
|
||||
return build ? `${normalizedVersion}+${build}` : normalizedVersion;
|
||||
}
|
||||
|
||||
Vendored
-229
@@ -1,229 +0,0 @@
|
||||
export const id = 779;
|
||||
export const ids = [779,394];
|
||||
export const modules = {
|
||||
|
||||
/***/ 1394:
|
||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ isCacheFeatureAvailable: () => (/* binding */ isCacheFeatureAvailable)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6971);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3838);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4527);
|
||||
|
||||
|
||||
|
||||
function isCacheFeatureAvailable() {
|
||||
if (_actions_cache__WEBPACK_IMPORTED_MODULE_0__/* .isFeatureAvailable */ .w3()) {
|
||||
return true;
|
||||
}
|
||||
if ((0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .isGhes */ .aT)()) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .warning */ .$e('Caching is only supported on GHES version >= 3.5. If you are on a version >= 3.5, please check with your GHES admin if the Actions cache service is enabled or not.');
|
||||
return false;
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .warning */ .$e('The runner was not able to contact the cache service. Caching will be skipped');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 5779:
|
||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ buildJdkCacheKey: () => (/* binding */ buildJdkCacheKey),
|
||||
/* harmony export */ getJdkVerificationIdentity: () => (/* binding */ getJdkVerificationIdentity),
|
||||
/* harmony export */ registerJdk: () => (/* binding */ registerJdk),
|
||||
/* harmony export */ restoreJdk: () => (/* binding */ restoreJdk),
|
||||
/* harmony export */ saveJdkCaches: () => (/* binding */ saveJdkCaches)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6982);
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6971);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3838);
|
||||
/* harmony import */ var _cache_feature_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1394);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const STATE_JDK_CACHES = 'jdk-caches';
|
||||
const JDK_CACHE_KEY_VERSION = 1;
|
||||
const restoredCaches = [];
|
||||
async function restoreJdk(jdk) {
|
||||
if (!jdk.path || !(0,_cache_feature_js__WEBPACK_IMPORTED_MODULE_5__.isCacheFeatureAvailable)()) {
|
||||
return false;
|
||||
}
|
||||
const key = buildJdkCacheKey(jdk);
|
||||
let matchedKey;
|
||||
try {
|
||||
matchedKey = await _actions_cache__WEBPACK_IMPORTED_MODULE_3__/* .restoreCache */ .P3([jdk.path], key);
|
||||
}
|
||||
catch (error) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .warning */ .$e(`Failed to restore JDK cache: ${error.message}`);
|
||||
}
|
||||
const architecturePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(jdk.path, jdk.architecture);
|
||||
if (matchedKey &&
|
||||
(!fs__WEBPACK_IMPORTED_MODULE_1___default().existsSync(architecturePath) ||
|
||||
!fs__WEBPACK_IMPORTED_MODULE_1___default().existsSync(`${architecturePath}.complete`))) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .warning */ .$e(`JDK cache key ${matchedKey} was restored without the expected tool-cache path; downloading the JDK instead.`);
|
||||
matchedKey = undefined;
|
||||
}
|
||||
recordJdkCache({
|
||||
key,
|
||||
path: jdk.path,
|
||||
architecture: jdk.architecture,
|
||||
matchedKey
|
||||
});
|
||||
if (matchedKey) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .info */ .pq(`JDK cache restored from key: ${matchedKey}`);
|
||||
return true;
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .info */ .pq(`JDK cache is not found for ${jdk.distribution} ${jdk.version}`);
|
||||
return false;
|
||||
}
|
||||
function registerJdk(jdk) {
|
||||
if (!jdk.path) {
|
||||
return;
|
||||
}
|
||||
recordJdkCache({
|
||||
key: buildJdkCacheKey(jdk),
|
||||
path: jdk.path,
|
||||
architecture: jdk.architecture,
|
||||
installation: getInstallationIdentity(jdk.path, jdk.architecture)
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Cheap fingerprint of the installation stored at a tool-cache path. The
|
||||
* `<architecture>.complete` marker is (re)created by `tc.cacheDir` every time an
|
||||
* installation is written, so its inode and timestamps change whenever the
|
||||
* installation is replaced. This avoids rehashing a multi-hundred-megabyte JDK
|
||||
* directory while still detecting that the bytes behind a key were swapped.
|
||||
*/
|
||||
function getInstallationIdentity(jdkPath, architecture) {
|
||||
const architecturePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(jdkPath, architecture);
|
||||
try {
|
||||
const marker = fs__WEBPACK_IMPORTED_MODULE_1___default().statSync(`${architecturePath}.complete`);
|
||||
const installation = fs__WEBPACK_IMPORTED_MODULE_1___default().statSync(architecturePath);
|
||||
return [
|
||||
marker.ino,
|
||||
marker.mtimeMs,
|
||||
marker.ctimeMs,
|
||||
marker.size,
|
||||
installation.ino,
|
||||
installation.mtimeMs,
|
||||
installation.ctimeMs
|
||||
].join(':');
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
function getJdkVerificationIdentity(verifySignature, publicKey) {
|
||||
if (!verifySignature) {
|
||||
return 'unverified';
|
||||
}
|
||||
if (!publicKey) {
|
||||
return 'verified:bundled';
|
||||
}
|
||||
const normalizedKey = publicKey.replace(/\r\n?/g, '\n').trim();
|
||||
const fingerprint = (0,crypto__WEBPACK_IMPORTED_MODULE_0__.createHash)('sha256').update(normalizedKey).digest('hex');
|
||||
return `verified:custom:sha256:${fingerprint}`;
|
||||
}
|
||||
async function saveJdkCaches() {
|
||||
const state = _actions_core__WEBPACK_IMPORTED_MODULE_4__/* .getState */ .Gu(STATE_JDK_CACHES);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
const caches = parseJdkCacheState(state);
|
||||
for (const jdk of caches) {
|
||||
if (jdk.matchedKey === jdk.key) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .info */ .pq(`Cache hit occurred on the JDK primary key ${jdk.key}, not saving cache.`);
|
||||
continue;
|
||||
}
|
||||
if (!fs__WEBPACK_IMPORTED_MODULE_1___default().existsSync(jdk.path)) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`JDK cache path does not exist, not saving: ${jdk.path}`);
|
||||
continue;
|
||||
}
|
||||
if (!jdk.installation) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`No JDK installation was registered for the key ${jdk.key}, not saving cache.`);
|
||||
continue;
|
||||
}
|
||||
if (getInstallationIdentity(jdk.path, jdk.architecture) !== jdk.installation) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .warning */ .$e(`The JDK installation in ${jdk.path} was replaced after it was registered for the key ${jdk.key}; not saving cache.`);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const cacheId = await _actions_cache__WEBPACK_IMPORTED_MODULE_3__/* .saveCache */ .Io([jdk.path], jdk.key);
|
||||
if (cacheId !== -1) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .info */ .pq(`JDK cache saved with the key: ${jdk.key}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
const err = error;
|
||||
if (err.name === _actions_cache__WEBPACK_IMPORTED_MODULE_3__/* .ReserveCacheError */ .Zh.name) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .info */ .pq(err.message);
|
||||
}
|
||||
else {
|
||||
// Saving is best-effort and per entry: one failure must not suppress
|
||||
// the remaining JDK caches.
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .warning */ .$e(`Failed to save the JDK cache with the key ${jdk.key}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function buildJdkCacheKey(jdk) {
|
||||
const runnerOs = process.env['RUNNER_OS'] ?? process.platform;
|
||||
const normalizedArchitecture = jdk.architecture.toLowerCase();
|
||||
const identity = JSON.stringify({
|
||||
keyVersion: JDK_CACHE_KEY_VERSION,
|
||||
runnerOs,
|
||||
distribution: jdk.distribution.toLowerCase(),
|
||||
packageType: jdk.packageType.toLowerCase(),
|
||||
architecture: normalizedArchitecture,
|
||||
version: jdk.version,
|
||||
source: jdk.source,
|
||||
verification: jdk.verification
|
||||
});
|
||||
const digest = (0,crypto__WEBPACK_IMPORTED_MODULE_0__.createHash)('sha256').update(identity).digest('hex');
|
||||
return `setup-java-jdk-v${JDK_CACHE_KEY_VERSION}-${runnerOs}-${normalizedArchitecture}-${digest}`;
|
||||
}
|
||||
function recordJdkCache(jdk) {
|
||||
const existing = restoredCaches.findIndex(item => item.key === jdk.key && item.path === jdk.path);
|
||||
if (existing === -1) {
|
||||
restoredCaches.push(jdk);
|
||||
}
|
||||
else {
|
||||
restoredCaches[existing] = { ...restoredCaches[existing], ...jdk };
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .saveState */ .LZ(STATE_JDK_CACHES, JSON.stringify(restoredCaches));
|
||||
}
|
||||
function parseJdkCacheState(state) {
|
||||
const value = JSON.parse(state);
|
||||
if (!Array.isArray(value) ||
|
||||
!value.every(item => typeof item === 'object' &&
|
||||
item !== null &&
|
||||
typeof item.key === 'string' &&
|
||||
typeof item.path === 'string' &&
|
||||
typeof item.architecture === 'string' &&
|
||||
(item.matchedKey === undefined ||
|
||||
typeof item.matchedKey === 'string') &&
|
||||
(item.installation === undefined ||
|
||||
typeof item.installation === 'string'))) {
|
||||
throw new Error('Invalid JDK cache information retrieved from state.');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
Vendored
+9
-7
@@ -13,10 +13,12 @@ export const modules = {
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_5__);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_5__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_6__);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -88,10 +90,10 @@ class SemeruDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_0__
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_4___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_5___default().join(extractedJavaPath, archiveName);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_5___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_6___default().join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_2__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
get toolcacheFolderName() {
|
||||
|
||||
Vendored
+35
-36
@@ -10,15 +10,17 @@ export const modules = {
|
||||
/* harmony export */ GraalVMDistribution: () => (/* binding */ GraalVMDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _actions_http_client__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4942);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _actions_http_client__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4942);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(4527);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +39,7 @@ const IS_WINDOWS = process.platform === 'win32';
|
||||
const GRAALVM_PLATFORM = IS_WINDOWS ? 'windows' : process.platform;
|
||||
const GRAALVM_MIN_VERSION = 17;
|
||||
const SUPPORTED_ARCHITECTURES = ['x64', 'aarch64'];
|
||||
class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
constructor(installerOptions, distributionName = 'GraalVM') {
|
||||
super(distributionName, installerOptions);
|
||||
}
|
||||
@@ -46,22 +48,22 @@ class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
let javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .getDownloadArchiveExtension */ .ag)();
|
||||
if (IS_WINDOWS) {
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
// Add validation for extracted path
|
||||
if (!fs__WEBPACK_IMPORTED_MODULE_1___default().existsSync(extractedJavaPath)) {
|
||||
if (!fs__WEBPACK_IMPORTED_MODULE_2___default().existsSync(extractedJavaPath)) {
|
||||
throw new Error(`Extraction failed: path ${extractedJavaPath} does not exist`);
|
||||
}
|
||||
const dirContents = fs__WEBPACK_IMPORTED_MODULE_1___default().readdirSync(extractedJavaPath);
|
||||
const dirContents = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath);
|
||||
if (dirContents.length === 0) {
|
||||
throw new Error('Extraction failed: no files found in extracted directory');
|
||||
}
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(extractedJavaPath, dirContents[0]);
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_3___default().join(extractedJavaPath, dirContents[0]);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, version, this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
catch (error) {
|
||||
@@ -83,7 +85,7 @@ class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
// builds its download URLs from a concrete major and has no endpoint to list
|
||||
// releases, so resolve the newest available GA major from the Adoptium API.
|
||||
if (this.latest) {
|
||||
range = (await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getLatestMajorVersion */ .ri)(this.http)).toString();
|
||||
range = (await (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .getLatestMajorVersion */ .ri)(this.http)).toString();
|
||||
}
|
||||
const { platform, extension, major } = this.validateStableBuildRequest(range);
|
||||
const fileUrl = this.constructFileUrl(range, major, platform, arch, extension);
|
||||
@@ -92,10 +94,7 @@ class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
return {
|
||||
url: fileUrl,
|
||||
version: range,
|
||||
checksum: await this.fetchChecksum(`${fileUrl}.sha256`, 'sha256'),
|
||||
// A major-only range resolves to the vendor's `/latest/` path, whose
|
||||
// contents change when a new build is published.
|
||||
floating: !range.includes('.')
|
||||
checksum: await this.fetchChecksum(`${fileUrl}.sha256`, 'sha256')
|
||||
};
|
||||
}
|
||||
validateVersionRange(range) {
|
||||
@@ -115,7 +114,7 @@ class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
throw new Error(`${this.distribution} provides only the \`jdk\` package type`);
|
||||
}
|
||||
const platform = this.getPlatform();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const major = range.includes('.') ? range.split('.')[0] : range;
|
||||
const majorVersion = parseInt(major);
|
||||
if (isNaN(majorVersion)) {
|
||||
@@ -137,7 +136,7 @@ class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
}
|
||||
handleHttpResponse(response, range) {
|
||||
const statusCode = response.message.statusCode;
|
||||
if (statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_5__/* .HttpCodes */ .Hv.NotFound) {
|
||||
if (statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.NotFound) {
|
||||
// Create the standard error with additional hint about checking the download URL
|
||||
const error = this.createVersionNotFoundError(range);
|
||||
if (this.latest) {
|
||||
@@ -146,11 +145,11 @@ class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
error.message += `\nPlease check if this version is available at ${GRAALVM_DOWNLOAD_URL} . Pick a version from the list.`;
|
||||
throw error;
|
||||
}
|
||||
if (statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_5__/* .HttpCodes */ .Hv.Unauthorized ||
|
||||
statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_5__/* .HttpCodes */ .Hv.Forbidden) {
|
||||
if (statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.Unauthorized ||
|
||||
statusCode === _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.Forbidden) {
|
||||
throw new Error(`Access denied when downloading GraalVM. Status code: ${statusCode}. Please check your credentials or permissions.`);
|
||||
}
|
||||
if (statusCode !== _actions_http_client__WEBPACK_IMPORTED_MODULE_5__/* .HttpCodes */ .Hv.OK) {
|
||||
if (statusCode !== _actions_http_client__WEBPACK_IMPORTED_MODULE_6__/* .HttpCodes */ .Hv.OK) {
|
||||
throw new Error(`HTTP request for GraalVM failed with status code: ${statusCode} (${response.message.statusMessage || 'Unknown error'})`);
|
||||
}
|
||||
}
|
||||
@@ -183,7 +182,7 @@ class GraalVMDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4_
|
||||
}
|
||||
async fetchEAJson(javaEaVersion) {
|
||||
const url = `https://api.github.com/repos/graalvm/oracle-graalvm-ea-builds/contents/versions/${javaEaVersion}.json?ref=main`;
|
||||
const headers = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getGitHubHttpHeaders */ .U_)();
|
||||
const headers = (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .getGitHubHttpHeaders */ .U_)();
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .debug */ .Yz(`Trying to fetch available version info for GraalVM EA builds from '${url}'`);
|
||||
try {
|
||||
const response = await this.http.getJson(url, headers);
|
||||
@@ -244,7 +243,7 @@ class GraalVMCommunityDistribution extends GraalVMDistribution {
|
||||
throw new Error(`${this.distribution} provides only the \`jdk\` package type`);
|
||||
}
|
||||
platform = this.getPlatform();
|
||||
extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
|
||||
extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .getDownloadArchiveExtension */ .ag)();
|
||||
}
|
||||
else {
|
||||
({ platform, extension } = this.validateStableBuildRequest(range));
|
||||
@@ -254,8 +253,8 @@ class GraalVMCommunityDistribution extends GraalVMDistribution {
|
||||
const assetSuffix = `_${platform}-${arch}_bin.${extension}`;
|
||||
const availableVersions = await this.getAvailableVersions(assetSuffix);
|
||||
const satisfiedVersion = availableVersions
|
||||
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .isVersionSatisfies */ .y)(range, item.version))
|
||||
.sort((a, b) => -semver__WEBPACK_IMPORTED_MODULE_3___default().compareBuild(a.version, b.version))[0];
|
||||
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .isVersionSatisfies */ .y)(range, item.version))
|
||||
.sort((a, b) => -semver__WEBPACK_IMPORTED_MODULE_4___default().compareBuild(a.version, b.version))[0];
|
||||
if (!satisfiedVersion) {
|
||||
const error = this.createVersionNotFoundError(range, availableVersions.map(item => item.version), `Platform: ${platform}`);
|
||||
error.message += `\nPlease check if this version is available at ${GRAALVM_COMMUNITY_DOWNLOAD_URL}.`;
|
||||
@@ -264,10 +263,10 @@ class GraalVMCommunityDistribution extends GraalVMDistribution {
|
||||
return satisfiedVersion;
|
||||
}
|
||||
async getAvailableVersions(assetSuffix) {
|
||||
const headers = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getGitHubHttpHeaders */ .U_)();
|
||||
const headers = (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .getGitHubHttpHeaders */ .U_)();
|
||||
const versions = new Map();
|
||||
let releasesUrl = GRAALVM_COMMUNITY_RELEASES_URL;
|
||||
for (let pageIndex = 0; releasesUrl && pageIndex < _util_js__WEBPACK_IMPORTED_MODULE_6__/* .MAX_PAGINATION_PAGES */ .Tp; pageIndex++) {
|
||||
for (let pageIndex = 0; releasesUrl && pageIndex < _util_js__WEBPACK_IMPORTED_MODULE_7__/* .MAX_PAGINATION_PAGES */ .Tp; pageIndex++) {
|
||||
const response = await this.http.getJson(releasesUrl, headers);
|
||||
// A successful GitHub releases listing is always a JSON array (possibly
|
||||
// empty). Anything else indicates an unexpected/error payload (rate
|
||||
@@ -323,12 +322,12 @@ class GraalVMCommunityDistribution extends GraalVMDistribution {
|
||||
if (!GRAALVM_COMMUNITY_VERSION_PATTERN.test(rawVersion)) {
|
||||
return null;
|
||||
}
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .convertVersionToSemver */ .ZY)(rawVersion);
|
||||
return (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .convertVersionToSemver */ .ZY)(rawVersion);
|
||||
}
|
||||
getNextReleasesUrl(headers) {
|
||||
const nextUrl = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getNextPageUrlFromLinkHeader */ .rC)(headers);
|
||||
const nextUrl = (0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .getNextPageUrlFromLinkHeader */ .rC)(headers);
|
||||
if (nextUrl &&
|
||||
!(0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .validatePaginationUrl */ .SA)(nextUrl, GRAALVM_COMMUNITY_RELEASES_PAGE_ORIGIN)) {
|
||||
!(0,_util_js__WEBPACK_IMPORTED_MODULE_7__/* .validatePaginationUrl */ .SA)(nextUrl, GRAALVM_COMMUNITY_RELEASES_PAGE_ORIGIN)) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .warning */ .$e(`Ignoring pagination link with unexpected origin: ${nextUrl}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
Vendored
+185
-210
File diff suppressed because it is too large
Load Diff
Vendored
+23
-21
@@ -9,21 +9,23 @@ export const modules = {
|
||||
/* harmony export */ ZuluDistribution: () => (/* binding */ ZuluDistribution)
|
||||
/* harmony export */ });
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9805);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9896);
|
||||
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2088);
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var _base_installer_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6242);
|
||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/* .JavaBase */ .O {
|
||||
|
||||
class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_5__/* .JavaBase */ .O {
|
||||
constructor(installerOptions) {
|
||||
super('Zulu', installerOptions);
|
||||
}
|
||||
@@ -37,19 +39,19 @@ class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
|
||||
? [...item.java_version, item.openjdk_build_number]
|
||||
: item.java_version;
|
||||
return {
|
||||
version: (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .convertVersionToSemver */ .ZY)(javaVersion),
|
||||
version: (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .convertVersionToSemver */ .ZY)(javaVersion),
|
||||
url: item.download_url,
|
||||
zuluVersion: (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .convertVersionToSemver */ .ZY)(item.distro_version),
|
||||
zuluVersion: (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .convertVersionToSemver */ .ZY)(item.distro_version),
|
||||
packageUuid: item.package_uuid
|
||||
};
|
||||
});
|
||||
const satisfiedVersions = availableVersions
|
||||
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .isVersionSatisfies */ .y)(version, item.version))
|
||||
.filter(item => (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .isVersionSatisfies */ .y)(version, item.version))
|
||||
.sort((a, b) => {
|
||||
// Azul provides two versions: java_version and distro_version
|
||||
// we should sort by both fields by descending
|
||||
return (-semver__WEBPACK_IMPORTED_MODULE_3___default().compareBuild(a.version, b.version) ||
|
||||
-semver__WEBPACK_IMPORTED_MODULE_3___default().compareBuild(a.zuluVersion, b.zuluVersion));
|
||||
return (-semver__WEBPACK_IMPORTED_MODULE_4___default().compareBuild(a.version, b.version) ||
|
||||
-semver__WEBPACK_IMPORTED_MODULE_4___default().compareBuild(a.zuluVersion, b.zuluVersion));
|
||||
})
|
||||
.map((item) => ({
|
||||
version: item.version,
|
||||
@@ -83,21 +85,21 @@ class ZuluDistribution extends _base_installer_js__WEBPACK_IMPORTED_MODULE_4__/*
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`);
|
||||
let javaArchivePath = await this.downloadAndVerify(javaRelease);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Extracting Java archive...`);
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
|
||||
if (process.platform === 'win32') {
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
javaArchivePath = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .renameWinArchive */ .n2)(javaArchivePath);
|
||||
}
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_2___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_1___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .cacheJdkDir */ .Vj)(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
const extractedJavaPath = await (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .extractJdkFile */ .PE)(javaArchivePath, extension);
|
||||
const archiveName = fs__WEBPACK_IMPORTED_MODULE_3___default().readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path__WEBPACK_IMPORTED_MODULE_2___default().join(extractedJavaPath, archiveName);
|
||||
const javaPath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_1__/* .cacheDir */ .e8(archivePath, this.toolcacheFolderName, this.getToolcacheVersionName(javaRelease.version), this.architecture);
|
||||
return { version: javaRelease.version, path: javaPath };
|
||||
}
|
||||
async getAvailableVersions() {
|
||||
const arch = this.getArchitectureOptions();
|
||||
const [bundleType, features] = this.packageType.split('+');
|
||||
const platform = this.getPlatformOption();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const extension = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getDownloadArchiveExtension */ .ag)();
|
||||
const javafx = features?.includes('fx') ?? false;
|
||||
const crac = features?.includes('crac') ?? false;
|
||||
const releaseStatus = this.stable ? 'ga' : 'ea';
|
||||
|
||||
Vendored
+5
-128
@@ -30770,7 +30770,6 @@ module.exports = {
|
||||
/* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ At: () => (/* binding */ INPUT_CACHE_DEPENDENCY_PATH),
|
||||
/* harmony export */ E8: () => (/* binding */ INPUT_SET_DEFAULT),
|
||||
/* harmony export */ GL: () => (/* binding */ INPUT_CACHE_JDK),
|
||||
/* harmony export */ I9: () => (/* binding */ INPUT_FORCE_DOWNLOAD),
|
||||
/* harmony export */ K$: () => (/* binding */ GPG_PASSPHRASE_PROFILE_ID),
|
||||
/* harmony export */ LS: () => (/* binding */ INPUT_ARCHITECTURE),
|
||||
@@ -30850,7 +30849,6 @@ const MAVEN_GPG_PASSPHRASE_DEFAULT_ENV = 'MAVEN_GPG_PASSPHRASE';
|
||||
// Id of the settings.xml profile used to set `gpg.passphraseEnvName`.
|
||||
const GPG_PASSPHRASE_PROFILE_ID = 'setup-java-gpg';
|
||||
const INPUT_CACHE = 'cache';
|
||||
const INPUT_CACHE_JDK = 'cache-jdk';
|
||||
const INPUT_CACHE_DEPENDENCY_PATH = 'cache-dependency-path';
|
||||
const INPUT_CACHE_PATH = 'cache-path';
|
||||
const INPUT_CACHE_READ_ONLY = 'cache-read-only';
|
||||
@@ -31241,12 +31239,10 @@ function validateToolchainIds(versions, versionFile, toolchainIds) {
|
||||
/* harmony export */ SA: () => (/* binding */ validatePaginationUrl),
|
||||
/* harmony export */ Tp: () => (/* binding */ MAX_PAGINATION_PAGES),
|
||||
/* harmony export */ U_: () => (/* binding */ getGitHubHttpHeaders),
|
||||
/* harmony export */ Vj: () => (/* binding */ cacheJdkDir),
|
||||
/* harmony export */ Vt: () => (/* binding */ getBooleanInput),
|
||||
/* harmony export */ ZY: () => (/* binding */ convertVersionToSemver),
|
||||
/* harmony export */ aT: () => (/* binding */ isGhes),
|
||||
/* harmony export */ ag: () => (/* binding */ getDownloadArchiveExtension),
|
||||
/* harmony export */ lN: () => (/* binding */ isJdkCacheEnabled),
|
||||
/* harmony export */ n2: () => (/* binding */ renameWinArchive),
|
||||
/* harmony export */ rC: () => (/* binding */ getNextPageUrlFromLinkHeader),
|
||||
/* harmony export */ ri: () => (/* binding */ getLatestMajorVersion),
|
||||
@@ -31264,14 +31260,7 @@ function validateToolchainIds(versions, versionFile, toolchainIds) {
|
||||
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__nccwpck_require__.n(semver__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_4__ = __nccwpck_require__(3838);
|
||||
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(9805);
|
||||
/* harmony import */ var _actions_exec__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(5260);
|
||||
/* harmony import */ var _actions_io__WEBPACK_IMPORTED_MODULE_7__ = __nccwpck_require__(8701);
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_8__ = __nccwpck_require__(6982);
|
||||
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__nccwpck_require__.n(crypto__WEBPACK_IMPORTED_MODULE_8__);
|
||||
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_9__ = __nccwpck_require__(7242);
|
||||
|
||||
|
||||
|
||||
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(7242);
|
||||
|
||||
|
||||
|
||||
@@ -31297,11 +31286,6 @@ function getBooleanInput(inputName, defaultValue = false) {
|
||||
}
|
||||
throw new Error(`Invalid value '${inputValue}' for boolean input '${inputName}'. Expected 'true' or 'false'.`);
|
||||
}
|
||||
function isJdkCacheEnabled(cache) {
|
||||
return _actions_core__WEBPACK_IMPORTED_MODULE_4__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_9__/* .INPUT_CACHE_JDK */ .GL).trim()
|
||||
? getBooleanInput(_constants_js__WEBPACK_IMPORTED_MODULE_9__/* .INPUT_CACHE_JDK */ .GL)
|
||||
: Boolean(cache.trim());
|
||||
}
|
||||
function getVersionFromToolcachePath(toolPath) {
|
||||
if (toolPath) {
|
||||
return path.basename(path.dirname(toolPath));
|
||||
@@ -31319,116 +31303,14 @@ async function extractJdkFile(toolPath, extension) {
|
||||
}
|
||||
switch (extension) {
|
||||
case 'tar.gz':
|
||||
return await extractTarGz(toolPath);
|
||||
case 'tar':
|
||||
return await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .extractTar */ .nN(toolPath);
|
||||
case 'zip':
|
||||
return await extractZipArchive(toolPath);
|
||||
return await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .extractZip */ .JE(toolPath);
|
||||
default:
|
||||
return await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .extract7z */ .$E(toolPath);
|
||||
}
|
||||
}
|
||||
async function createExtractFolder() {
|
||||
const dest = path__WEBPACK_IMPORTED_MODULE_1___default().join(getTempDir(), (0,crypto__WEBPACK_IMPORTED_MODULE_8__.randomUUID)());
|
||||
await _actions_io__WEBPACK_IMPORTED_MODULE_7__/* .mkdirP */ .U$(dest);
|
||||
return dest;
|
||||
}
|
||||
/**
|
||||
* Decompressing a JDK tarball with the default single-threaded gzip is one of the
|
||||
* slowest parts of the install, so hand the decompression to `pigz` when the runner
|
||||
* provides it. Any failure falls back to the stock extraction.
|
||||
*/
|
||||
async function extractTarGz(toolPath) {
|
||||
const pigzPath = await _actions_io__WEBPACK_IMPORTED_MODULE_7__/* .which */ .K7('pigz');
|
||||
// tar splits --use-compress-program on whitespace, so a path containing a
|
||||
// space would be word-split into a bogus command.
|
||||
if (pigzPath && !/\s/.test(pigzPath)) {
|
||||
const dest = await createExtractFolder();
|
||||
try {
|
||||
return await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .extractTar */ .nN(toolPath, dest, [
|
||||
'--use-compress-program',
|
||||
`${pigzPath} -d`,
|
||||
'-x'
|
||||
]);
|
||||
}
|
||||
catch (error) {
|
||||
await _actions_io__WEBPACK_IMPORTED_MODULE_7__/* .rmRF */ .Yz(dest);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Failed to extract '${toolPath}' with pigz, falling back to gzip: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
return await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .extractTar */ .nN(toolPath);
|
||||
}
|
||||
/**
|
||||
* `tc.extractZip` shells out to PowerShell's `Expand-Archive` on Windows, which is
|
||||
* several times slower than the bundled bsdtar. Prefer `tar.exe` and fall back to
|
||||
* the stock extraction when it is unavailable or fails.
|
||||
*/
|
||||
async function extractZipArchive(toolPath) {
|
||||
if (process.platform === 'win32') {
|
||||
const systemTar = path__WEBPACK_IMPORTED_MODULE_1___default().join(process.env['SystemRoot'] || 'C:\\Windows', 'System32', 'tar.exe');
|
||||
if (fs__WEBPACK_IMPORTED_MODULE_2__.existsSync(systemTar)) {
|
||||
const dest = await createExtractFolder();
|
||||
try {
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_6__/* .exec */ .m(`"${systemTar}"`, ['-xf', toolPath, '-C', dest], {
|
||||
silent: true
|
||||
});
|
||||
return dest;
|
||||
}
|
||||
catch (error) {
|
||||
await _actions_io__WEBPACK_IMPORTED_MODULE_7__/* .rmRF */ .Yz(dest);
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Failed to extract '${toolPath}' with tar.exe, falling back to Expand-Archive: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .extractZip */ .JE(toolPath);
|
||||
}
|
||||
/**
|
||||
* Equivalent of `tc.cacheDir`, but moves the extracted JDK into the tool-cache
|
||||
* instead of copying it. `tc.cacheDir` recursively copies the whole tree, which
|
||||
* means a several hundred megabyte JDK is written to disk twice. The extraction
|
||||
* directory and the tool-cache normally live on the same filesystem, so a rename
|
||||
* is effectively free. Anything unexpected (a different filesystem, or a file
|
||||
* handle held open by anti-virus software on Windows) falls back to the copy.
|
||||
*/
|
||||
async function cacheJdkDir(sourceDir, toolName, version, architecture) {
|
||||
const destPath = getToolcacheDestination(toolName, version, architecture);
|
||||
if (destPath) {
|
||||
let moved = false;
|
||||
try {
|
||||
// lstat, not stat: renaming a symlinked source would put the link itself
|
||||
// in the tool-cache, leaving a dangling JAVA_HOME once RUNNER_TEMP is
|
||||
// cleaned. tc.cacheDir dereferences it, so let it handle that case.
|
||||
if (fs__WEBPACK_IMPORTED_MODULE_2__.lstatSync(sourceDir).isDirectory()) {
|
||||
await _actions_io__WEBPACK_IMPORTED_MODULE_7__/* .rmRF */ .Yz(destPath);
|
||||
await _actions_io__WEBPACK_IMPORTED_MODULE_7__/* .rmRF */ .Yz(`${destPath}.complete`);
|
||||
await _actions_io__WEBPACK_IMPORTED_MODULE_7__/* .mkdirP */ .U$(path__WEBPACK_IMPORTED_MODULE_1___default().dirname(destPath));
|
||||
// Renaming is atomic, so a failure here leaves sourceDir untouched and
|
||||
// the copy-based fallback below can still run.
|
||||
fs__WEBPACK_IMPORTED_MODULE_2__.renameSync(sourceDir, destPath);
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_4__/* .debug */ .Yz(`Failed to move '${sourceDir}' into the tool-cache, falling back to a copy: ${getErrorMessage(error)}`);
|
||||
}
|
||||
if (moved) {
|
||||
fs__WEBPACK_IMPORTED_MODULE_2__.writeFileSync(`${destPath}.complete`, '');
|
||||
return destPath;
|
||||
}
|
||||
}
|
||||
return await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_5__/* .cacheDir */ .e8(sourceDir, toolName, version, architecture);
|
||||
}
|
||||
function getToolcacheDestination(toolName, version, architecture) {
|
||||
const toolcacheRoot = process.env['RUNNER_TOOL_CACHE'];
|
||||
if (!toolcacheRoot) {
|
||||
return null;
|
||||
}
|
||||
// Mirrors the destination layout used by `tc.cacheDir`.
|
||||
return path__WEBPACK_IMPORTED_MODULE_1___default().join(toolcacheRoot, toolName, semver__WEBPACK_IMPORTED_MODULE_3__.clean(version) || version, architecture || os__WEBPACK_IMPORTED_MODULE_0___default().arch());
|
||||
}
|
||||
function getErrorMessage(error) {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
function getDownloadArchiveExtension() {
|
||||
return process.platform === 'win32' ? 'zip' : 'tar.gz';
|
||||
}
|
||||
@@ -31525,7 +31407,7 @@ function getVersionFromFileContent(content, distributionName, versionFile) {
|
||||
}
|
||||
// Apply DISTRIBUTIONS_ONLY_MAJOR_VERSION logic whenever the effective distribution
|
||||
// (either explicitly provided or extracted from the version file) is in the list.
|
||||
if (_constants_js__WEBPACK_IMPORTED_MODULE_9__/* .DISTRIBUTIONS_ONLY_MAJOR_VERSION */ ._V.includes(extractedDistribution || distributionName)) {
|
||||
if (_constants_js__WEBPACK_IMPORTED_MODULE_6__/* .DISTRIBUTIONS_ONLY_MAJOR_VERSION */ ._V.includes(extractedDistribution || distributionName)) {
|
||||
const coerceVersion = semver__WEBPACK_IMPORTED_MODULE_3__.coerce(version) ?? version;
|
||||
version = semver__WEBPACK_IMPORTED_MODULE_3__.major(coerceVersion).toString();
|
||||
}
|
||||
@@ -32008,7 +31890,6 @@ __nccwpck_require__.d(__webpack_exports__, {
|
||||
dN: () => (/* binding */ exportVariable),
|
||||
V4: () => (/* binding */ getInput),
|
||||
q3: () => (/* binding */ getMultilineInput),
|
||||
Gu: () => (/* binding */ getState),
|
||||
pq: () => (/* binding */ info),
|
||||
_o: () => (/* binding */ isDebug),
|
||||
LZ: () => (/* binding */ saveState),
|
||||
@@ -32019,7 +31900,7 @@ __nccwpck_require__.d(__webpack_exports__, {
|
||||
$e: () => (/* binding */ warning)
|
||||
});
|
||||
|
||||
// UNUSED EXPORTS: ExitCode, getBooleanInput, getIDToken, group, markdownSummary, notice, platform, setCommandEcho, summary, toPlatformPath, toPosixPath, toWin32Path
|
||||
// UNUSED EXPORTS: ExitCode, getBooleanInput, getIDToken, getState, group, markdownSummary, notice, platform, setCommandEcho, summary, toPlatformPath, toPosixPath, toWin32Path
|
||||
|
||||
// EXTERNAL MODULE: external "os"
|
||||
var external_os_ = __nccwpck_require__(857);
|
||||
@@ -36238,7 +36119,6 @@ async function run() {
|
||||
const packageType = setup_java_core/* getInput */.V4(constants/* INPUT_JAVA_PACKAGE */.p1);
|
||||
const jdkFile = getJdkFileInput();
|
||||
const cache = setup_java_core/* getInput */.V4(constants/* INPUT_CACHE */.gk);
|
||||
const cacheJdk = (0,util/* isJdkCacheEnabled */.lN)(cache);
|
||||
const cacheDependencyPath = setup_java_core/* getInput */.V4(constants/* INPUT_CACHE_DEPENDENCY_PATH */.At);
|
||||
const cachePath = setup_java_core/* getMultilineInput */.q3(constants/* INPUT_CACHE_PATH */.uW);
|
||||
const checkLatest = (0,util/* getBooleanInput */.Vt)(constants/* INPUT_CHECK_LATEST */.YM, false);
|
||||
@@ -36277,7 +36157,6 @@ async function run() {
|
||||
packageType,
|
||||
checkLatest,
|
||||
forceDownload,
|
||||
cacheJdk,
|
||||
setDefault,
|
||||
verifySignature,
|
||||
verifySignaturePublicKey,
|
||||
@@ -36300,7 +36179,6 @@ async function run() {
|
||||
packageType,
|
||||
checkLatest,
|
||||
forceDownload,
|
||||
cacheJdk,
|
||||
setDefault,
|
||||
verifySignature,
|
||||
verifySignaturePublicKey,
|
||||
@@ -36353,13 +36231,12 @@ function getJdkFileInput() {
|
||||
return jdkFile || deprecatedJdkFile;
|
||||
}
|
||||
async function installVersion(version, options, toolchainId = 0) {
|
||||
const { distributionName, jdkFile, architecture, packageType, checkLatest, forceDownload, cacheJdk, setDefault, verifySignature, verifySignaturePublicKey, toolchainIds } = options;
|
||||
const { distributionName, jdkFile, architecture, packageType, checkLatest, forceDownload, setDefault, verifySignature, verifySignaturePublicKey, toolchainIds } = options;
|
||||
const installerOptions = {
|
||||
architecture,
|
||||
packageType,
|
||||
checkLatest,
|
||||
forceDownload,
|
||||
cacheJdk,
|
||||
setDefault,
|
||||
verifySignature,
|
||||
verifySignaturePublicKey,
|
||||
|
||||
+7
-163
@@ -5,10 +5,8 @@
|
||||
- [Liberica](#Liberica)
|
||||
- [Liberica Native Image Kit](#Liberica-Native-Image-Kit)
|
||||
- [Microsoft](#Microsoft)
|
||||
- [IBM Semeru](#IBM-Semeru)
|
||||
- [Amazon Corretto](#Amazon-Corretto)
|
||||
- [Oracle](#Oracle)
|
||||
- [Oracle OpenJDK](#Oracle-OpenJDK)
|
||||
- [Alibaba Dragonwell](#Alibaba-Dragonwell)
|
||||
- [SapMachine](#SapMachine)
|
||||
- [GraalVM](#GraalVM)
|
||||
@@ -19,17 +17,13 @@
|
||||
- [Package compatibility](#Package-compatibility)
|
||||
- [JavaFX Maven project](#JavaFX-Maven-project)
|
||||
- [Ensuring the Maven cache is complete (plugin dependencies)](#ensuring-the-maven-cache-is-complete-plugin-dependencies)
|
||||
- [Caching JDK installations](#caching-jdk-installations)
|
||||
- [Platform and architecture compatibility](#platform-and-architecture-compatibility)
|
||||
- [Installing custom Java architecture](#Installing-custom-Java-architecture)
|
||||
- [Installing JDK without setting as default](#Installing-JDK-without-setting-as-default)
|
||||
- [Installing custom Java distribution from local file](#Installing-Java-from-local-file)
|
||||
- [Testing against different Java distributions](#Testing-against-different-Java-distributions)
|
||||
- [Testing against different platforms](#Testing-against-different-platforms)
|
||||
- [Publishing using Apache Maven](#Publishing-using-Apache-Maven)
|
||||
- [Apache Maven with a settings path](#apache-maven-with-a-settings-path)
|
||||
- [Maven transfer progress (download logs)](#Maven-transfer-progress-download-logs)
|
||||
- [Java problem matcher (compiler annotations)](#java-problem-matcher-compiler-annotations)
|
||||
- [Publishing using Gradle](#Publishing-using-Gradle)
|
||||
- [Hosted Tool Cache](#Hosted-Tool-Cache)
|
||||
- [Modifying Maven Toolchains](#Modifying-Maven-Toolchains)
|
||||
@@ -38,17 +32,8 @@
|
||||
|
||||
See [action.yml](../action.yml) for more details on task inputs.
|
||||
|
||||
> [!NOTE]
|
||||
> The examples on this page reference `actions/setup-java@v6`, which is still in
|
||||
> development on the `main` branch and is not yet published as a release tag. To
|
||||
> try the V6 features documented here (`cache-jdk`, `force-download`,
|
||||
> `problem-matcher`, `cache-path`, `cache-read-only`, `java-version: latest`,
|
||||
> `oracle-openjdk`, and the `*-env-var` input names), reference
|
||||
> `actions/setup-java@main`. For production workflows use the latest stable
|
||||
> release, `actions/setup-java@v5`, as shown in the [README](../README.md).
|
||||
|
||||
## Selecting a Java distribution
|
||||
`java-version` and `distribution` select what gets installed. `java-version` may be replaced by `java-version-file`, and `distribution` is optional only when `java-version-file` points to a `.sdkmanrc` or `.tool-versions` file that carries a recognized vendor identifier. In every other case both inputs must be provided. See [Supported distributions](../README.md#Supported-distributions) for a list of available options.
|
||||
Inputs `java-version` and `distribution` are mandatory and needs to be provided. See [Supported distributions](../README.md#Supported-distributions) for a list of available options.
|
||||
|
||||
### Eclipse Temurin
|
||||
|
||||
@@ -131,20 +116,6 @@ with:
|
||||
|
||||
If the runner is not able to access github.com, any Java versions requested during a workflow run must come from the runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)" for more information.
|
||||
|
||||
### IBM Semeru
|
||||
**NOTE:** IBM Semeru Runtime Open Edition provides OpenJ9-based builds. Stable releases only; `jdk` and `jre` packages are available.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'semeru'
|
||||
java-version: '21'
|
||||
java-package: jdk # optional (jdk or jre) - defaults to jdk
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
### Amazon Corretto
|
||||
**NOTE:** Amazon Corretto only supports the major version specification.
|
||||
|
||||
@@ -322,7 +293,7 @@ The package types have these meanings:
|
||||
| `temurin` | `jdk`, `jre`, `jdk+jmods` | `jdk` and `jre` follow the Adoptium catalog. `jdk+jmods` is available for Java 24 and later and resolves both artifacts at the exact same Java version. |
|
||||
| `zulu` | `jdk`, `jre`, `jdk+fx`, `jre+fx`, `jdk+crac`, `jre+crac` | Standard JDK builds go back to Java 6; JRE and JavaFX bundles start at Java 8. The vendor catalog has gaps among older non-LTS releases. CRaC bundles start at Java 17 and have more limited OS and architecture availability. |
|
||||
| `liberica` | `jdk`, `jre`, `jdk+fx`, `jre+fx` | Standard JDK builds go back to Java 8 in the supported action catalog; JRE and JavaFX "full" bundles also start at Java 8. Exact versions follow BellSoft's catalog for the requested platform. |
|
||||
| `liberica-nik` | `jdk`, `jdk+fx` | `java-version` selects the embedded JDK version, not the NIK/GraalVM release number. BellSoft currently publishes matching standard and JavaFX "full" bundles for JDK 11 and later, with gaps between feature releases. Any other `java-package` value is rejected. |
|
||||
| `liberica-nik` | `jdk`, `jdk+fx` | `java-version` selects the embedded JDK version, not the NIK/GraalVM release number. BellSoft currently publishes matching standard and JavaFX "full" bundles for JDK 11 and later, with gaps between feature releases. Other values are not meaningful: they resolve to the standard bundle. |
|
||||
| `microsoft` | `jdk` | Stable builds only. The bundled manifest contains Java 11, 16, 17, 21, and 25 releases; platform availability varies by release. |
|
||||
| `semeru` | `jdk`, `jre` | Stable OpenJ9 builds only. IBM publishes both image types for the supported release lines (currently 8, 11, 17, 21, and 25), subject to platform availability. |
|
||||
| `corretto` | `jdk`, `jre` | Accepts major versions only. JDK availability follows Amazon's platform catalog. For the operating systems directly selected by `setup-java`, JRE downloads are limited to Java 8 on Windows; Linux and macOS use `jdk`. |
|
||||
@@ -497,133 +468,6 @@ jobs:
|
||||
> which provides purpose-built caching (see the
|
||||
> [setup-gradle documentation](https://github.com/gradle/actions/blob/main/docs/setup-gradle.md)).
|
||||
|
||||
## Caching JDK installations
|
||||
|
||||
`cache-jdk` controls caching for downloaded JDK installations. The JDK cache is
|
||||
stored and restored as its own cache entry, separate from the dependency and
|
||||
build-tool wrapper caches selected by `cache`. Whether it is *enabled*, however,
|
||||
is coupled to `cache`: setting `cache` turns JDK caching on as well, unless
|
||||
`cache-jdk` is set explicitly.
|
||||
|
||||
| `cache` | `cache-jdk` | Dependency and wrapper caches | JDK cache |
|
||||
| --- | --- | --- | --- |
|
||||
| Omitted | Omitted | Disabled | Disabled |
|
||||
| Omitted | `true` | Disabled | Enabled |
|
||||
| Omitted | `false` | Disabled | Disabled |
|
||||
| Set | Omitted | Enabled | Enabled |
|
||||
| Set | `true` | Enabled | Enabled |
|
||||
| Set | `false` | Enabled | Disabled |
|
||||
|
||||
JDK entries are specific to the runner operating system and normalized
|
||||
architecture. They are additionally separated by distribution, package type,
|
||||
exact resolved Java version, release identity, and signature-verification
|
||||
identity. The release identity is the authoritative checksum when available and
|
||||
otherwise the download URL without its query string. These dimensions prevent
|
||||
incompatible JDKs from sharing an entry. They also mean that a matrix or workflow
|
||||
using multiple JDK versions, distributions, package types, architectures, or
|
||||
operating systems stores a separate JDK entry for each identity and consumes
|
||||
cache storage for each one.
|
||||
|
||||
For `distribution: jdkfile`, the release source is a SHA-256 hash of the local
|
||||
`jdk-file` contents, streamed so the archive is not held in memory. Changing the
|
||||
archive therefore creates a different JDK cache entry, even when its path and
|
||||
requested version are unchanged. The archive is only read when the runner tool
|
||||
cache holds no installation satisfying the requested version: a matching
|
||||
tool-cache installation short-circuits setup, so a changed `jdk-file` is not
|
||||
re-extracted for a version that is already installed. Use
|
||||
`force-download: true` when the archive contents change but the version does not.
|
||||
|
||||
The verification identity separates unverified downloads from packages verified
|
||||
with the distribution's bundled signing key and from packages verified with each
|
||||
custom key. Custom public keys are represented by a SHA-256 fingerprint of
|
||||
normalized key material; the key itself is not placed in the cache key, the logs,
|
||||
or action state. A verified exact-key hit reuses content that was
|
||||
signature-verified when it was downloaded by the run that saved the entry,
|
||||
instead of downloading and verifying it again.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The JDK cache **key** is what isolates verification modes and release
|
||||
> identity: a JDK cache entry created by an unverified download can never be
|
||||
> restored for a request that sets `verify-signature: true`, and vice versa.
|
||||
> `cache-jdk` does not change how the runner tool cache is used. setup-java
|
||||
> first looks for an installation in the runner tool cache — a preinstalled
|
||||
> JDK, or one installed by an earlier step of the same job — and uses it as-is. Such an installation is not downloaded again, and its checksum
|
||||
> and signature are not reverified, even when `verify-signature: true` is set,
|
||||
> because its verification history is not recorded in the tool cache. Use
|
||||
> `force-download: true` for a request that must download and verify the archive
|
||||
> itself.
|
||||
|
||||
`check-latest: true` and `java-version: latest` resolve remote metadata before
|
||||
looking up the exact resolved JDK entry. `force-download: true` bypasses both the
|
||||
runner tool cache and JDK cache restore, but an enabled JDK cache still records
|
||||
the downloaded installation for a post-job save. `cache-read-only: true` allows
|
||||
restores but suppresses post-job saves for JDK, dependency, and wrapper caches.
|
||||
|
||||
If the cache service fails to restore an entry, or the restored entry lacks the
|
||||
expected completed tool-cache path, setup continues by downloading the JDK.
|
||||
Post-job saves are best-effort and do not fail the job: cache keys are immutable,
|
||||
so an existing key or a concurrent job winning the save race is left unchanged,
|
||||
and a failure to save one JDK entry is reported as a warning without preventing
|
||||
the remaining entries from being saved.
|
||||
|
||||
A key is only ever populated with the installation it was computed for. Because
|
||||
tool-cache paths are shared per version and architecture, a later step — for
|
||||
example one using `force-download: true` — can replace the installation an
|
||||
earlier step registered. setup-java detects that replacement in the post-job
|
||||
step and skips the save with a warning, so a key is never saved with content
|
||||
other than the installation it identifies. This guarantee holds without
|
||||
rehashing hundreds of megabytes of JDK content on every job.
|
||||
|
||||
### Caching release resolution
|
||||
|
||||
Only Temurin is preinstalled in the runner tool cache, so for every other
|
||||
distribution setup-java has to ask the distribution's metadata API which release
|
||||
satisfies `java-version` before it can look up a JDK cache entry. That makes the
|
||||
vendor API a dependency of every job, even one whose JDK is already cached.
|
||||
|
||||
When JDK caching is enabled, setup-java also stores the resolved release itself
|
||||
in a small companion cache entry, keyed on the runner operating system,
|
||||
architecture, distribution, package type, requested version, and stability. A job
|
||||
that finds a current entry installs the JDK without contacting the distribution's
|
||||
metadata API at all.
|
||||
|
||||
Entries carry the seven-day window they were resolved in. An entry from an
|
||||
earlier window is not used directly: setup-java still queries the metadata API,
|
||||
so a floating request such as `java-version: 21` keeps picking up new releases.
|
||||
The older entry is used only when that query fails, which keeps a job working
|
||||
through a vendor outage or rate limit. Because the entry also holds the download
|
||||
URL and checksum, this fallback works even when the JDK itself is not cached and
|
||||
still has to be downloaded. When the fallback is used, setup-java reports it with
|
||||
a warning.
|
||||
|
||||
Seven days is deliberate. GitHub removes cache entries that have not been
|
||||
accessed for seven days, so a longer window would mean the previous entry is
|
||||
already evicted by the time the window rolls over, leaving no fallback at the
|
||||
moment one is most likely to be needed. It also comfortably covers JDK release
|
||||
cadence, which is monthly at its fastest and usually quarterly, and it means a
|
||||
repository whose workflows run infrequently still benefits. Use
|
||||
`check-latest: true` for a workflow that must resolve the newest release on every
|
||||
run.
|
||||
|
||||
Restored entries are validated before use: the download URL and any signature URL
|
||||
must be well-formed HTTPS URLs and the checksum must use a supported algorithm.
|
||||
An entry that fails validation is ignored and the metadata API is queried
|
||||
instead. `check-latest: true`, `java-version: latest`, and `force-download: true`
|
||||
always query the metadata API and never read or write these entries.
|
||||
|
||||
Releases whose download URL is not content-addressed are never stored. Oracle JDK
|
||||
and Oracle GraalVM build a `/latest/` URL when `java-version` names only a major
|
||||
version, and the bytes behind that URL change whenever a new build is published,
|
||||
so its URL and checksum are only consistent with each other at the moment they
|
||||
are resolved. Requesting a more specific version, such as `java-version: 21.0.2`,
|
||||
resolves an archived URL that is stored normally.
|
||||
|
||||
JDK caching trades cache storage and cold-run save work for faster warm setup.
|
||||
A warm run restores the installed JDK instead of downloading, verifying, and
|
||||
extracting it, while the first run pays to upload it and every cached identity
|
||||
consumes repository cache storage. How much time this saves depends on the
|
||||
runner, distribution, JDK size, network, and cache eviction pressure.
|
||||
|
||||
## Platform and architecture compatibility
|
||||
|
||||
The `architecture` input is normalized before setup-java checks the tool cache
|
||||
@@ -746,7 +590,7 @@ steps:
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
distribution: [ 'zulu', 'temurin' ]
|
||||
@@ -762,7 +606,7 @@ jobs:
|
||||
- run: java --version
|
||||
```
|
||||
|
||||
## Testing against different platforms
|
||||
#### Testing against different platforms
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
@@ -1101,7 +945,7 @@ The result is a Toolchain with entries for JDKs 8, 11 and 15. You can even combi
|
||||
architecture: x64
|
||||
```
|
||||
|
||||
This will generate a Toolchains entry with the following values: `version: 1.6`, `vendor: jdkfile`, `id: jdkfile_1.6`.
|
||||
This will generate a Toolchains entry with the following values: `version: 1.6`, `vendor: jdkfile`, `id: Oracle_1.6`.
|
||||
|
||||
### Modifying The Toolchain Vendor For JDKs
|
||||
Each JDK provider will receive a default `vendor` using the `distribution` input value but this can be overridden with the `mvn-toolchain-vendor` parameter as follows.
|
||||
@@ -1135,7 +979,7 @@ steps:
|
||||
```
|
||||
|
||||
### Modifying The Toolchain ID For JDKs
|
||||
Each JDK provider will receive a default `id` based on the combination of the toolchain vendor and `java-version` in the format of `vendor_java-version` (e.g. `temurin_11`). The vendor defaults to the `distribution` input, so overriding `mvn-toolchain-vendor` also changes the generated default `id`. Set `mvn-toolchain-id` to override the `id` directly.
|
||||
Each JDK provider will receive a default `id` based on the combination of `distribution` and `java-version` in the format of `distribution_java-version` (e.g. `temurin_11`) but this can be overridden with the `mvn-toolchain-id` parameter as follows.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
@@ -1300,7 +1144,7 @@ On **GitHub Enterprise Server**, traffic from your runners frequently passes thr
|
||||
|
||||
### Security warning: do not disable certificate verification
|
||||
|
||||
Do **not** work around this error by disabling TLS verification (for example, by setting `NODE_TLS_REJECT_UNAUTHORIZED=0`). Disabling verification would expose your workflow to a man-in-the-middle attacker who could serve a tampered JDK — which then becomes the `java` used by the rest of your pipeline, with access to your secrets and credentials. It also weakens the version metadata requests, which are not checksum-verified at all: a tampered manifest can redirect setup-java to an attacker-controlled download URL. `setup-java` does verify authoritative checksums for [supported distributions](../README.md#download-integrity-and-signatures), and can verify package signatures with `verify-signature: true`, but those checks are not a substitute for a trusted TLS chain. Always extend trust to your CA instead of turning verification off.
|
||||
Do **not** work around this error by disabling TLS verification (for example, by setting `NODE_TLS_REJECT_UNAUTHORIZED=0`). `setup-java` does not verify a pinned checksum or signature of the downloaded archive, so **TLS is effectively the only integrity guarantee** on the JDK download. Disabling verification would expose your workflow to a man-in-the-middle attacker who could serve a tampered JDK — which then becomes the `java` used by the rest of your pipeline, with access to your secrets and credentials. Always extend trust to your CA instead of turning verification off.
|
||||
|
||||
### Trusting an internal CA inside the installed JDK
|
||||
|
||||
|
||||
Generated
+3
-3
@@ -2635,9 +2635,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "5.0.9",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
|
||||
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
|
||||
"integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
"fix": "npm run format && npm run lint:fix && npm run build",
|
||||
"prepare": "husky install",
|
||||
"prerelease": "npm run-script build",
|
||||
"release": "git add -f dist/setup/*.js dist/setup/package.json dist/cleanup/*.js",
|
||||
"release": "git add -f dist/setup/*.js dist/setup/package.json dist/cleanup/index.js",
|
||||
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --runInBand --coverage"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
||||
+6
-21
@@ -1,11 +1,7 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as gpg from './gpg.js';
|
||||
import * as constants from './constants.js';
|
||||
import {
|
||||
getBooleanInput,
|
||||
isJdkCacheEnabled,
|
||||
isJobStatusSuccess
|
||||
} from './util.js';
|
||||
import {getBooleanInput, isJobStatusSuccess} from './util.js';
|
||||
import {fileURLToPath} from 'url';
|
||||
|
||||
async function removePrivateKeyFromKeychain() {
|
||||
@@ -28,11 +24,10 @@ async function removePrivateKeyFromKeychain() {
|
||||
* Check given input and run a save process for the specified package manager
|
||||
* @returns Promise that will be resolved when the save process finishes
|
||||
*/
|
||||
async function saveCaches() {
|
||||
async function saveCache() {
|
||||
const jobStatus = isJobStatusSuccess();
|
||||
const cache = core.getInput(constants.INPUT_CACHE);
|
||||
const cacheJdk = isJdkCacheEnabled(cache);
|
||||
if (!jobStatus || (!cache && !cacheJdk)) {
|
||||
if (!jobStatus || !cache) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,18 +36,8 @@ async function saveCaches() {
|
||||
return;
|
||||
}
|
||||
|
||||
const saves: Promise<void>[] = [];
|
||||
if (cache) {
|
||||
const {save} = await import('./cache.js');
|
||||
saves.push(save(cache));
|
||||
}
|
||||
if (cacheJdk) {
|
||||
const {saveJdkCaches} = await import('./jdk-cache.js');
|
||||
const {saveJdkResolutionCaches} = await import('./jdk-resolution-cache.js');
|
||||
saves.push(saveJdkCaches());
|
||||
saves.push(saveJdkResolutionCaches());
|
||||
}
|
||||
await Promise.all(saves);
|
||||
const {save} = await import('./cache.js');
|
||||
await save(cache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +59,7 @@ async function ignoreError(promise: Promise<void>) {
|
||||
|
||||
export async function run() {
|
||||
await removePrivateKeyFromKeychain();
|
||||
await ignoreError(saveCaches());
|
||||
await ignoreError(saveCache());
|
||||
}
|
||||
|
||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||
|
||||
@@ -37,7 +37,6 @@ export const MAVEN_GPG_PASSPHRASE_DEFAULT_ENV = 'MAVEN_GPG_PASSPHRASE';
|
||||
export const GPG_PASSPHRASE_PROFILE_ID = 'setup-java-gpg';
|
||||
|
||||
export const INPUT_CACHE = 'cache';
|
||||
export const INPUT_CACHE_JDK = 'cache-jdk';
|
||||
export const INPUT_CACHE_DEPENDENCY_PATH = 'cache-dependency-path';
|
||||
export const INPUT_CACHE_PATH = 'cache-path';
|
||||
export const INPUT_CACHE_READ_ONLY = 'cache-read-only';
|
||||
|
||||
@@ -21,7 +21,6 @@ import {RetryingHttpClient} from '../retrying-http-client.js';
|
||||
import os from 'os';
|
||||
import {expectedDigestLength, verifyChecksum} from '../checksum.js';
|
||||
import {normalizeArchitecture} from './platform-types.js';
|
||||
import type {JdkCache} from '../jdk-cache.js';
|
||||
|
||||
export abstract class JavaBase {
|
||||
protected http: httpm.HttpClient;
|
||||
@@ -32,7 +31,6 @@ export abstract class JavaBase {
|
||||
protected latest: boolean;
|
||||
protected checkLatest: boolean;
|
||||
protected forceDownload: boolean;
|
||||
protected cacheJdk: boolean;
|
||||
protected setDefault: boolean;
|
||||
protected verifySignature: boolean;
|
||||
protected verifySignaturePublicKey: string | undefined;
|
||||
@@ -54,7 +52,6 @@ export abstract class JavaBase {
|
||||
this.packageType = installerOptions.packageType;
|
||||
this.checkLatest = installerOptions.checkLatest;
|
||||
this.forceDownload = installerOptions.forceDownload ?? false;
|
||||
this.cacheJdk = installerOptions.cacheJdk ?? false;
|
||||
this.setDefault =
|
||||
installerOptions.setDefault !== undefined
|
||||
? installerOptions.setDefault
|
||||
@@ -178,53 +175,14 @@ export abstract class JavaBase {
|
||||
} else {
|
||||
core.info('Trying to resolve the latest version from remote');
|
||||
try {
|
||||
const javaRelease = await this.resolveJavaRelease();
|
||||
const javaRelease = await this.findPackageForDownload(this.version);
|
||||
core.info(`Resolved latest version as ${javaRelease.version}`);
|
||||
if (!this.forceDownload && foundJava?.version === javaRelease.version) {
|
||||
core.info(`Resolved Java ${foundJava.version} from tool-cache`);
|
||||
} else {
|
||||
let jdkCache: JdkCache | undefined;
|
||||
if (this.cacheJdk) {
|
||||
const {getJdkVerificationIdentity} =
|
||||
await import('../jdk-cache.js');
|
||||
jdkCache = {
|
||||
distribution: this.distribution,
|
||||
packageType: this.packageType,
|
||||
architecture: this.architecture,
|
||||
version: javaRelease.version,
|
||||
source: this.getJdkReleaseIdentity(javaRelease),
|
||||
verification: getJdkVerificationIdentity(
|
||||
this.verifySignature,
|
||||
this.verifySignaturePublicKey
|
||||
),
|
||||
path: this.getJdkCachePath(javaRelease.version)
|
||||
};
|
||||
}
|
||||
if (!this.forceDownload && jdkCache) {
|
||||
const {restoreJdk} = await import('../jdk-cache.js');
|
||||
const restored = await restoreJdk(jdkCache);
|
||||
if (restored) {
|
||||
const restoredPath = this.getRestoredJdkPath(javaRelease.version);
|
||||
if (restoredPath) {
|
||||
foundJava = {
|
||||
version: javaRelease.version,
|
||||
path: restoredPath
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundJava || foundJava.version !== javaRelease.version) {
|
||||
core.info('Trying to download...');
|
||||
foundJava = await this.downloadTool(javaRelease);
|
||||
core.info(`Java ${foundJava.version} was downloaded`);
|
||||
if (jdkCache) {
|
||||
// Register after the installation exists so its identity is
|
||||
// captured; the post-job save refuses to upload a path whose
|
||||
// installation was replaced afterwards.
|
||||
const {registerJdk} = await import('../jdk-cache.js');
|
||||
registerJdk(jdkCache);
|
||||
}
|
||||
}
|
||||
core.info('Trying to download...');
|
||||
foundJava = await this.downloadTool(javaRelease);
|
||||
core.info(`Java ${foundJava.version} was downloaded`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.logSetupError(error);
|
||||
@@ -256,67 +214,6 @@ export abstract class JavaBase {
|
||||
return foundJava;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the release to install, preferring a cached resolution over the
|
||||
* distribution's metadata API.
|
||||
*
|
||||
* Only Temurin is preinstalled on hosted runners, so for every other
|
||||
* distribution the tool-cache lookup misses and the vendor API becomes a
|
||||
* per-job dependency even when the JDK itself is already in the GitHub
|
||||
* Actions cache. A cached resolution removes that dependency, and because it
|
||||
* carries the download URL and checksum it also keeps a job working when the
|
||||
* vendor API is unavailable but the JDK still has to be downloaded.
|
||||
*/
|
||||
private async resolveJavaRelease(): Promise<JavaDownloadRelease> {
|
||||
if (
|
||||
!this.cacheJdk ||
|
||||
this.checkLatest ||
|
||||
this.latest ||
|
||||
this.forceDownload
|
||||
) {
|
||||
return this.findPackageForDownload(this.version);
|
||||
}
|
||||
|
||||
const {restoreJdkResolution, registerJdkResolution} =
|
||||
await import('../jdk-resolution-cache.js');
|
||||
const request = {
|
||||
distribution: this.distribution,
|
||||
packageType: this.packageType,
|
||||
architecture: this.architecture,
|
||||
versionSpec: this.version,
|
||||
stable: this.stable
|
||||
};
|
||||
|
||||
const restored = await restoreJdkResolution(request);
|
||||
if (restored?.fresh) {
|
||||
core.info(
|
||||
`Resolved ${this.distribution} ${restored.release.version} from the resolution cache`
|
||||
);
|
||||
return restored.release;
|
||||
}
|
||||
|
||||
try {
|
||||
const javaRelease = await this.findPackageForDownload(this.version);
|
||||
if (!javaRelease.floating) {
|
||||
registerJdkResolution(request, javaRelease);
|
||||
}
|
||||
return javaRelease;
|
||||
} catch (error) {
|
||||
if (!restored) {
|
||||
throw error;
|
||||
}
|
||||
// The cached resolution is older than the current bucket, but falling
|
||||
// back to it is strictly better than failing the job because the vendor
|
||||
// metadata API is down.
|
||||
core.warning(
|
||||
`Failed to resolve ${this.distribution} ${this.version} from remote (${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}); falling back to the cached resolution for ${restored.release.version}.`
|
||||
);
|
||||
return restored.release;
|
||||
}
|
||||
}
|
||||
|
||||
private logSetupError(error: any): void {
|
||||
const httpStatusCode =
|
||||
error instanceof tc.HTTPError
|
||||
@@ -402,42 +299,6 @@ export abstract class JavaBase {
|
||||
return version.replace('+', '-');
|
||||
}
|
||||
|
||||
protected getJdkCachePath(version: string): string {
|
||||
const toolCache = process.env['RUNNER_TOOL_CACHE'];
|
||||
if (!toolCache) {
|
||||
return '';
|
||||
}
|
||||
return path.join(
|
||||
toolCache,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(version)
|
||||
);
|
||||
}
|
||||
|
||||
protected getRestoredJdkPath(version: string): string | null {
|
||||
const basePath = this.getJdkCachePath(version);
|
||||
if (!basePath) {
|
||||
return null;
|
||||
}
|
||||
const architecturePath = path.join(basePath, this.architecture);
|
||||
return fs.existsSync(architecturePath) &&
|
||||
fs.existsSync(`${architecturePath}.complete`)
|
||||
? architecturePath
|
||||
: null;
|
||||
}
|
||||
|
||||
private getJdkReleaseIdentity(javaRelease: JavaDownloadRelease): string {
|
||||
if (javaRelease.checksum) {
|
||||
return `${javaRelease.checksum.algorithm}:${javaRelease.checksum.value}`;
|
||||
}
|
||||
try {
|
||||
const url = new URL(javaRelease.url);
|
||||
return `${url.origin}${url.pathname}`;
|
||||
} catch {
|
||||
return javaRelease.url;
|
||||
}
|
||||
}
|
||||
|
||||
protected findInToolcache(): JavaInstallerResults | null {
|
||||
// we can't use tc.find directly because firstly, we need to filter versions by stability flag
|
||||
// if *-ea is provided, take only ea versions from toolcache, otherwise - only stable versions
|
||||
|
||||
@@ -4,7 +4,6 @@ export interface JavaInstallerOptions {
|
||||
packageType: string;
|
||||
checkLatest: boolean;
|
||||
forceDownload?: boolean;
|
||||
cacheJdk?: boolean;
|
||||
setDefault?: boolean;
|
||||
verifySignature?: boolean;
|
||||
verifySignaturePublicKey?: string;
|
||||
@@ -28,11 +27,4 @@ export interface JavaDownloadRelease {
|
||||
url: string;
|
||||
signatureUrl?: string;
|
||||
checksum?: ChecksumMetadata;
|
||||
/**
|
||||
* Whether `url` points at a location whose contents change over time, such as
|
||||
* a vendor's `/latest/` path. The URL and its checksum are only consistent
|
||||
* with each other at the moment they are resolved, so such a release must not
|
||||
* be reused by a later job.
|
||||
*/
|
||||
floating?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
convertVersionToSemver,
|
||||
@@ -46,7 +46,7 @@ export class CorrettoDistribution extends JavaBase {
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import semver from 'semver';
|
||||
|
||||
import fs from 'fs';
|
||||
@@ -6,7 +7,6 @@ import path from 'path';
|
||||
|
||||
import {JavaBase} from '../base-installer.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
convertVersionToSemver,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
@@ -121,7 +121,7 @@ export class DragonwellDistribution extends JavaBase {
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
@@ -11,7 +12,6 @@ import {
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
convertVersionToSemver,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
@@ -97,7 +97,7 @@ export class GraalVMDistribution extends JavaBase {
|
||||
const archivePath = path.join(extractedJavaPath, dirContents[0]);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
@@ -149,10 +149,7 @@ export class GraalVMDistribution extends JavaBase {
|
||||
return {
|
||||
url: fileUrl,
|
||||
version: range,
|
||||
checksum: await this.fetchChecksum(`${fileUrl}.sha256`, 'sha256'),
|
||||
// A major-only range resolves to the vendor's `/latest/` path, whose
|
||||
// contents change when a new build is published.
|
||||
floating: !range.includes('.')
|
||||
checksum: await this.fetchChecksum(`${fileUrl}.sha256`, 'sha256')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
@@ -11,7 +12,7 @@ import {
|
||||
JavaInstallerOptions,
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {cacheJdkDir, extractJdkFile, isVersionSatisfies} from '../../util.js';
|
||||
import {extractJdkFile, isVersionSatisfies} from '../../util.js';
|
||||
import {OutgoingHttpHeaders} from 'http';
|
||||
import {HttpCodes} from '@actions/http-client';
|
||||
|
||||
@@ -78,7 +79,7 @@ export class JetBrainsDistribution extends JavaBase {
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import semver from 'semver';
|
||||
|
||||
import fs from 'fs';
|
||||
@@ -12,7 +13,6 @@ import {
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
isVersionSatisfies,
|
||||
@@ -48,7 +48,7 @@ export class KonaDistribution extends JavaBase {
|
||||
const jdkDirectory = path.join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
jdkDirectory,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
} from '../base-models.js';
|
||||
import semver from 'semver';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
isVersionSatisfies,
|
||||
@@ -14,6 +13,7 @@ import {
|
||||
} from '../../util.js';
|
||||
import * as core from '@actions/core';
|
||||
import {ArchitectureOptions, NikVersion, OsVersions} from './models.js';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
@@ -44,7 +44,7 @@ export class LibericaNikDistributions extends JavaBase {
|
||||
const archiveName = fs.readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(javaRelease.version),
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
} from '../base-models.js';
|
||||
import semver from 'semver';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
isVersionSatisfies,
|
||||
@@ -14,6 +13,7 @@ import {
|
||||
} from '../../util.js';
|
||||
import * as core from '@actions/core';
|
||||
import {ArchitectureOptions, LibericaVersion, OsVersions} from './models.js';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
@@ -44,7 +44,7 @@ export class LibericaDistributions extends JavaBase {
|
||||
const archiveName = fs.readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(javaRelease.version),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import fs from 'fs';
|
||||
@@ -9,11 +10,8 @@ import {
|
||||
JavaDownloadRelease,
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {cacheJdkDir, extractJdkFile} from '../../util.js';
|
||||
import {extractJdkFile} from '../../util.js';
|
||||
import {MACOS_JAVA_CONTENT_POSTFIX} from '../../constants.js';
|
||||
import {createReadStream} from 'fs';
|
||||
import {createHash} from 'crypto';
|
||||
import type {JdkCache} from '../../jdk-cache.js';
|
||||
|
||||
export class LocalDistribution extends JavaBase {
|
||||
constructor(
|
||||
@@ -29,11 +27,6 @@ export class LocalDistribution extends JavaBase {
|
||||
"The 'latest' version alias is not supported for the 'jdkfile' distribution. Please specify a concrete version."
|
||||
);
|
||||
}
|
||||
if (this.verifySignature) {
|
||||
throw new Error(
|
||||
`Input 'verify-signature' is not supported for distribution '${this.distribution}'.`
|
||||
);
|
||||
}
|
||||
|
||||
let foundJava = this.forceDownload ? null : this.findInToolcache();
|
||||
|
||||
@@ -53,60 +46,24 @@ export class LocalDistribution extends JavaBase {
|
||||
throw new Error(`JDK file was not found in path '${jdkFilePath}'`);
|
||||
}
|
||||
|
||||
let jdkCache: JdkCache | undefined;
|
||||
if (this.cacheJdk) {
|
||||
const [{getJdkVerificationIdentity}, source] = await Promise.all([
|
||||
import('../../jdk-cache.js'),
|
||||
hashFile(jdkFilePath)
|
||||
]);
|
||||
jdkCache = {
|
||||
distribution: this.distribution,
|
||||
packageType: this.packageType,
|
||||
architecture: this.architecture,
|
||||
version: this.version,
|
||||
source,
|
||||
verification: getJdkVerificationIdentity(false),
|
||||
path: this.getJdkCachePath(this.version)
|
||||
};
|
||||
}
|
||||
if (!this.forceDownload && jdkCache) {
|
||||
const {restoreJdk} = await import('../../jdk-cache.js');
|
||||
const restored = await restoreJdk(jdkCache);
|
||||
const restoredPath = restored
|
||||
? this.getRestoredJdkPath(this.version)
|
||||
: undefined;
|
||||
if (restoredPath) {
|
||||
foundJava = {
|
||||
version: this.version,
|
||||
path: restoredPath
|
||||
};
|
||||
}
|
||||
}
|
||||
core.info(`Extracting Java from '${jdkFilePath}'`);
|
||||
|
||||
if (!foundJava) {
|
||||
core.info(`Extracting Java from '${jdkFilePath}'`);
|
||||
const extractedJavaPath = await extractJdkFile(jdkFilePath);
|
||||
const archiveName = fs.readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const javaVersion = this.version;
|
||||
|
||||
const extractedJavaPath = await extractJdkFile(jdkFilePath);
|
||||
const archiveName = fs.readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const javaVersion = this.version;
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(javaVersion),
|
||||
this.architecture
|
||||
);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(javaVersion),
|
||||
this.architecture
|
||||
);
|
||||
|
||||
foundJava = {
|
||||
version: javaVersion,
|
||||
path: javaPath
|
||||
};
|
||||
if (jdkCache) {
|
||||
const {registerJdk} = await import('../../jdk-cache.js');
|
||||
registerJdk(jdkCache);
|
||||
}
|
||||
}
|
||||
foundJava = {
|
||||
version: javaVersion,
|
||||
path: javaPath
|
||||
};
|
||||
}
|
||||
|
||||
// JDK folder may contain postfix "Contents/Home" on macOS
|
||||
@@ -146,11 +103,3 @@ export class LocalDistribution extends JavaBase {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function hashFile(file: string): Promise<string> {
|
||||
const hash = createHash('sha256');
|
||||
for await (const chunk of createReadStream(file)) {
|
||||
hash.update(chunk);
|
||||
}
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
getGitHubHttpHeaders,
|
||||
@@ -65,7 +64,7 @@ export class MicrosoftDistributions extends JavaBase {
|
||||
const archiveName = fs.readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(javaRelease.version),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
@@ -10,7 +11,6 @@ import {
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
convertVersionToSemver,
|
||||
extractJdkFile,
|
||||
isVersionSatisfies,
|
||||
@@ -74,7 +74,7 @@ export class OpenJdkDistribution extends JavaBase {
|
||||
|
||||
const archiveName = fs.readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(javaRelease.version),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
@@ -10,7 +11,6 @@ import {
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
getLatestMajorVersion,
|
||||
@@ -45,7 +45,7 @@ export class OracleDistribution extends JavaBase {
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
@@ -99,7 +99,6 @@ export class OracleDistribution extends JavaBase {
|
||||
`${ORACLE_DL_BASE}/${major}/latest/jdk-${major}_${platform}-${arch}_bin.${extension}`
|
||||
);
|
||||
}
|
||||
const floatingUrl = isOnlyMajorProvided ? possibleUrls[0] : undefined;
|
||||
|
||||
possibleUrls.push(
|
||||
`${ORACLE_DL_BASE}/${major}/archive/jdk-${range}_${platform}-${arch}_bin.${extension}`
|
||||
@@ -116,8 +115,7 @@ export class OracleDistribution extends JavaBase {
|
||||
return {
|
||||
url,
|
||||
version: range,
|
||||
checksum: await this.fetchChecksum(`${url}.sha256`, 'sha256'),
|
||||
floating: url === floatingUrl
|
||||
checksum: await this.fetchChecksum(`${url}.sha256`, 'sha256')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import semver from 'semver';
|
||||
import fs from 'fs';
|
||||
import {OutgoingHttpHeaders} from 'http';
|
||||
import path from 'path';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
convertVersionToSemver,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
@@ -124,7 +124,7 @@ export class SapMachineDistribution extends JavaBase {
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
} from '../base-models.js';
|
||||
import semver from 'semver';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getNextPageUrlFromLinkHeader,
|
||||
getDownloadArchiveExtension,
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
validatePaginationUrl
|
||||
} from '../../util.js';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {ISemeruAvailableVersions} from './models.js';
|
||||
@@ -125,7 +125,7 @@ export class SemeruDistribution extends JavaBase {
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath: string = await cacheJdkDir(
|
||||
const javaPath: string = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
@@ -15,7 +16,6 @@ import {
|
||||
JavaInstallerResults
|
||||
} from '../base-models.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getNextPageUrlFromLinkHeader,
|
||||
getDownloadArchiveExtension,
|
||||
@@ -122,7 +122,7 @@ export class TemurinDistribution extends JavaBase {
|
||||
}
|
||||
const version = this.getToolcacheVersionName(javaRelease.version);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
version,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
@@ -7,7 +8,6 @@ import semver from 'semver';
|
||||
import {JavaBase} from '../base-installer.js';
|
||||
import {IZuluPackageDetails, IZuluVersions} from './models.js';
|
||||
import {
|
||||
cacheJdkDir,
|
||||
extractJdkFile,
|
||||
getDownloadArchiveExtension,
|
||||
convertVersionToSemver,
|
||||
@@ -122,7 +122,7 @@ export class ZuluDistribution extends JavaBase {
|
||||
const archiveName = fs.readdirSync(extractedJavaPath)[0];
|
||||
const archivePath = path.join(extractedJavaPath, archiveName);
|
||||
|
||||
const javaPath = await cacheJdkDir(
|
||||
const javaPath = await tc.cacheDir(
|
||||
archivePath,
|
||||
this.toolcacheFolderName,
|
||||
this.getToolcacheVersionName(javaRelease.version),
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
import {createHash} from 'crypto';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import {isCacheFeatureAvailable} from './cache-feature.js';
|
||||
|
||||
const STATE_JDK_CACHES = 'jdk-caches';
|
||||
const JDK_CACHE_KEY_VERSION = 1;
|
||||
|
||||
export interface JdkCache {
|
||||
distribution: string;
|
||||
packageType: string;
|
||||
architecture: string;
|
||||
version: string;
|
||||
source: string;
|
||||
verification: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
interface JdkCacheState {
|
||||
key: string;
|
||||
path: string;
|
||||
architecture: string;
|
||||
matchedKey?: string;
|
||||
// Cheap identity of the installation that occupied `path` when the entry was
|
||||
// registered. The tool-cache path is shared per version/architecture, so a
|
||||
// later step (e.g. one using `force-download`) can replace those bytes; the
|
||||
// post-job save must not upload content that does not match the identity the
|
||||
// key was computed for.
|
||||
installation?: string;
|
||||
}
|
||||
|
||||
const restoredCaches: JdkCacheState[] = [];
|
||||
|
||||
export async function restoreJdk(jdk: JdkCache): Promise<boolean> {
|
||||
if (!jdk.path || !isCacheFeatureAvailable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const key = buildJdkCacheKey(jdk);
|
||||
let matchedKey: string | undefined;
|
||||
try {
|
||||
matchedKey = await cache.restoreCache([jdk.path], key);
|
||||
} catch (error) {
|
||||
core.warning(`Failed to restore JDK cache: ${(error as Error).message}`);
|
||||
}
|
||||
|
||||
const architecturePath = path.join(jdk.path, jdk.architecture);
|
||||
if (
|
||||
matchedKey &&
|
||||
(!fs.existsSync(architecturePath) ||
|
||||
!fs.existsSync(`${architecturePath}.complete`))
|
||||
) {
|
||||
core.warning(
|
||||
`JDK cache key ${matchedKey} was restored without the expected tool-cache path; downloading the JDK instead.`
|
||||
);
|
||||
matchedKey = undefined;
|
||||
}
|
||||
|
||||
recordJdkCache({
|
||||
key,
|
||||
path: jdk.path,
|
||||
architecture: jdk.architecture,
|
||||
matchedKey
|
||||
});
|
||||
|
||||
if (matchedKey) {
|
||||
core.info(`JDK cache restored from key: ${matchedKey}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
core.info(`JDK cache is not found for ${jdk.distribution} ${jdk.version}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
export function registerJdk(jdk: JdkCache): void {
|
||||
if (!jdk.path) {
|
||||
return;
|
||||
}
|
||||
recordJdkCache({
|
||||
key: buildJdkCacheKey(jdk),
|
||||
path: jdk.path,
|
||||
architecture: jdk.architecture,
|
||||
installation: getInstallationIdentity(jdk.path, jdk.architecture)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cheap fingerprint of the installation stored at a tool-cache path. The
|
||||
* `<architecture>.complete` marker is (re)created by `tc.cacheDir` every time an
|
||||
* installation is written, so its inode and timestamps change whenever the
|
||||
* installation is replaced. This avoids rehashing a multi-hundred-megabyte JDK
|
||||
* directory while still detecting that the bytes behind a key were swapped.
|
||||
*/
|
||||
function getInstallationIdentity(
|
||||
jdkPath: string,
|
||||
architecture: string
|
||||
): string | undefined {
|
||||
const architecturePath = path.join(jdkPath, architecture);
|
||||
try {
|
||||
const marker = fs.statSync(`${architecturePath}.complete`);
|
||||
const installation = fs.statSync(architecturePath);
|
||||
return [
|
||||
marker.ino,
|
||||
marker.mtimeMs,
|
||||
marker.ctimeMs,
|
||||
marker.size,
|
||||
installation.ino,
|
||||
installation.mtimeMs,
|
||||
installation.ctimeMs
|
||||
].join(':');
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function getJdkVerificationIdentity(
|
||||
verifySignature: boolean,
|
||||
publicKey?: string
|
||||
): string {
|
||||
if (!verifySignature) {
|
||||
return 'unverified';
|
||||
}
|
||||
if (!publicKey) {
|
||||
return 'verified:bundled';
|
||||
}
|
||||
|
||||
const normalizedKey = publicKey.replace(/\r\n?/g, '\n').trim();
|
||||
const fingerprint = createHash('sha256').update(normalizedKey).digest('hex');
|
||||
return `verified:custom:sha256:${fingerprint}`;
|
||||
}
|
||||
|
||||
export async function saveJdkCaches(): Promise<void> {
|
||||
const state = core.getState(STATE_JDK_CACHES);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
|
||||
const caches = parseJdkCacheState(state);
|
||||
for (const jdk of caches) {
|
||||
if (jdk.matchedKey === jdk.key) {
|
||||
core.info(
|
||||
`Cache hit occurred on the JDK primary key ${jdk.key}, not saving cache.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(jdk.path)) {
|
||||
core.debug(`JDK cache path does not exist, not saving: ${jdk.path}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!jdk.installation) {
|
||||
core.debug(
|
||||
`No JDK installation was registered for the key ${jdk.key}, not saving cache.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
getInstallationIdentity(jdk.path, jdk.architecture) !== jdk.installation
|
||||
) {
|
||||
core.warning(
|
||||
`The JDK installation in ${jdk.path} was replaced after it was registered for the key ${jdk.key}; not saving cache.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const cacheId = await cache.saveCache([jdk.path], jdk.key);
|
||||
if (cacheId !== -1) {
|
||||
core.info(`JDK cache saved with the key: ${jdk.key}`);
|
||||
}
|
||||
} catch (error) {
|
||||
const err = error as Error;
|
||||
if (err.name === cache.ReserveCacheError.name) {
|
||||
core.info(err.message);
|
||||
} else {
|
||||
// Saving is best-effort and per entry: one failure must not suppress
|
||||
// the remaining JDK caches.
|
||||
core.warning(
|
||||
`Failed to save the JDK cache with the key ${jdk.key}: ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function buildJdkCacheKey(jdk: JdkCache): string {
|
||||
const runnerOs = process.env['RUNNER_OS'] ?? process.platform;
|
||||
const normalizedArchitecture = jdk.architecture.toLowerCase();
|
||||
const identity = JSON.stringify({
|
||||
keyVersion: JDK_CACHE_KEY_VERSION,
|
||||
runnerOs,
|
||||
distribution: jdk.distribution.toLowerCase(),
|
||||
packageType: jdk.packageType.toLowerCase(),
|
||||
architecture: normalizedArchitecture,
|
||||
version: jdk.version,
|
||||
source: jdk.source,
|
||||
verification: jdk.verification
|
||||
});
|
||||
const digest = createHash('sha256').update(identity).digest('hex');
|
||||
return `setup-java-jdk-v${JDK_CACHE_KEY_VERSION}-${runnerOs}-${normalizedArchitecture}-${digest}`;
|
||||
}
|
||||
|
||||
function recordJdkCache(jdk: JdkCacheState): void {
|
||||
const existing = restoredCaches.findIndex(
|
||||
item => item.key === jdk.key && item.path === jdk.path
|
||||
);
|
||||
if (existing === -1) {
|
||||
restoredCaches.push(jdk);
|
||||
} else {
|
||||
restoredCaches[existing] = {...restoredCaches[existing], ...jdk};
|
||||
}
|
||||
core.saveState(STATE_JDK_CACHES, JSON.stringify(restoredCaches));
|
||||
}
|
||||
|
||||
function parseJdkCacheState(state: string): JdkCacheState[] {
|
||||
const value: unknown = JSON.parse(state);
|
||||
if (
|
||||
!Array.isArray(value) ||
|
||||
!value.every(
|
||||
item =>
|
||||
typeof item === 'object' &&
|
||||
item !== null &&
|
||||
typeof (item as JdkCacheState).key === 'string' &&
|
||||
typeof (item as JdkCacheState).path === 'string' &&
|
||||
typeof (item as JdkCacheState).architecture === 'string' &&
|
||||
((item as JdkCacheState).matchedKey === undefined ||
|
||||
typeof (item as JdkCacheState).matchedKey === 'string') &&
|
||||
((item as JdkCacheState).installation === undefined ||
|
||||
typeof (item as JdkCacheState).installation === 'string')
|
||||
)
|
||||
) {
|
||||
throw new Error('Invalid JDK cache information retrieved from state.');
|
||||
}
|
||||
return value as JdkCacheState[];
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
import {createHash} from 'crypto';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import {
|
||||
ChecksumMetadata,
|
||||
JavaDownloadRelease
|
||||
} from './distributions/base-models.js';
|
||||
|
||||
const STATE_JDK_RESOLUTIONS = 'jdk-resolutions';
|
||||
const JDK_RESOLUTION_KEY_VERSION = 1;
|
||||
const RESOLUTION_DIRECTORY = 'setup-java-jdk-resolution';
|
||||
const RESOLUTION_FILE_NAME = 'release.json';
|
||||
|
||||
/**
|
||||
* Everything that identifies a resolution request before any remote metadata is
|
||||
* fetched. Distribution-specific inputs are already folded into `distribution`
|
||||
* (for example Temurin's `jvm-impl`) or `packageType` (`jdk+jmods`), so these
|
||||
* fields fully determine which artifact a distribution would resolve.
|
||||
*/
|
||||
export interface JdkResolutionRequest {
|
||||
distribution: string;
|
||||
packageType: string;
|
||||
architecture: string;
|
||||
versionSpec: string;
|
||||
stable: boolean;
|
||||
}
|
||||
|
||||
export interface RestoredJdkResolution {
|
||||
release: JavaDownloadRelease;
|
||||
/**
|
||||
* Whether the entry was written within the current freshness window. A stale
|
||||
* entry is only a fallback for the case where the vendor metadata API is
|
||||
* unreachable, so a floating version spec cannot be pinned indefinitely.
|
||||
*/
|
||||
fresh: boolean;
|
||||
}
|
||||
|
||||
interface JdkResolutionState {
|
||||
key: string;
|
||||
path: string;
|
||||
/**
|
||||
* The payload the key was computed for. A restore in a later step writes to
|
||||
* the same path, so the post-job save rewrites the file from state instead of
|
||||
* uploading whatever happens to be on disk.
|
||||
*/
|
||||
release: string;
|
||||
}
|
||||
|
||||
const pendingResolutions: JdkResolutionState[] = [];
|
||||
|
||||
/**
|
||||
* Restores a previously resolved release so a distribution can skip its vendor
|
||||
* metadata API.
|
||||
*
|
||||
* The cache path deliberately excludes the freshness window: `@actions/cache`
|
||||
* derives
|
||||
* a cache version by hashing the requested paths, so a bucket-independent path
|
||||
* is what allows the restore keys to fall back to an older bucket.
|
||||
*/
|
||||
export async function restoreJdkResolution(
|
||||
request: JdkResolutionRequest
|
||||
): Promise<RestoredJdkResolution | undefined> {
|
||||
// Deliberately not `isCacheFeatureAvailable()`: this is an optional
|
||||
// optimization, and the JDK cache already warns once when the service is
|
||||
// unreachable.
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const cachePath = getResolutionCachePath(request);
|
||||
if (!cachePath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const keyPrefix = getResolutionKeyPrefix(request);
|
||||
const primaryKey = `${keyPrefix}${getFreshnessBucket()}`;
|
||||
|
||||
let matchedKey: string | undefined;
|
||||
try {
|
||||
matchedKey = await cache.restoreCache([cachePath], primaryKey, [keyPrefix]);
|
||||
} catch (error) {
|
||||
core.debug(
|
||||
`Failed to restore the JDK resolution cache: ${getErrorMessage(error)}`
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!matchedKey) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let release: JavaDownloadRelease;
|
||||
try {
|
||||
const contents = fs.readFileSync(
|
||||
path.join(cachePath, RESOLUTION_FILE_NAME),
|
||||
'utf8'
|
||||
);
|
||||
release = parseResolvedRelease(contents);
|
||||
} catch (error) {
|
||||
core.debug(
|
||||
`Ignoring the JDK resolution cache entry ${matchedKey}: ${getErrorMessage(error)}`
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {release, fresh: matchedKey === primaryKey};
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists a freshly resolved release for later jobs. The entry is written to
|
||||
* disk immediately and uploaded by the post-job step.
|
||||
*/
|
||||
export function registerJdkResolution(
|
||||
request: JdkResolutionRequest,
|
||||
release: JavaDownloadRelease
|
||||
): void {
|
||||
if (!cache.isFeatureAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cachePath = getResolutionCachePath(request);
|
||||
if (!cachePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = JSON.stringify(release);
|
||||
try {
|
||||
fs.mkdirSync(cachePath, {recursive: true});
|
||||
fs.writeFileSync(path.join(cachePath, RESOLUTION_FILE_NAME), payload);
|
||||
} catch (error) {
|
||||
core.debug(
|
||||
`Failed to record the JDK resolution cache entry: ${getErrorMessage(error)}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const key = `${getResolutionKeyPrefix(request)}${getFreshnessBucket()}`;
|
||||
if (!pendingResolutions.some(item => item.key === key)) {
|
||||
pendingResolutions.push({key, path: cachePath, release: payload});
|
||||
}
|
||||
core.saveState(STATE_JDK_RESOLUTIONS, JSON.stringify(pendingResolutions));
|
||||
}
|
||||
|
||||
export async function saveJdkResolutionCaches(): Promise<void> {
|
||||
const state = core.getState(STATE_JDK_RESOLUTIONS);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
|
||||
let resolutions: JdkResolutionState[];
|
||||
try {
|
||||
resolutions = parseJdkResolutionState(state);
|
||||
} catch (error) {
|
||||
core.debug(
|
||||
`Invalid JDK resolution cache state, not saving: ${getErrorMessage(error)}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const resolution of resolutions) {
|
||||
// A restore performed by a later step overwrites this path, so the payload
|
||||
// the key was computed for is written again rather than trusted to still be
|
||||
// on disk.
|
||||
try {
|
||||
fs.mkdirSync(resolution.path, {recursive: true});
|
||||
fs.writeFileSync(
|
||||
path.join(resolution.path, RESOLUTION_FILE_NAME),
|
||||
resolution.release
|
||||
);
|
||||
} catch (error) {
|
||||
core.debug(
|
||||
`Failed to write the JDK resolution cache entry for the key ${resolution.key}: ${getErrorMessage(error)}`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await cache.saveCache([resolution.path], resolution.key);
|
||||
} catch (error) {
|
||||
// A matrix of jobs resolving the same JDK races on the same daily key, so
|
||||
// an already-reserved key is the expected outcome rather than a problem.
|
||||
core.debug(
|
||||
`Failed to save the JDK resolution cache with the key ${resolution.key}: ${getErrorMessage(error)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getResolutionCachePath(
|
||||
request: JdkResolutionRequest
|
||||
): string | undefined {
|
||||
const runnerTemp = process.env['RUNNER_TEMP'];
|
||||
if (!runnerTemp) {
|
||||
return undefined;
|
||||
}
|
||||
return path.join(
|
||||
runnerTemp,
|
||||
RESOLUTION_DIRECTORY,
|
||||
getResolutionIdentity(request)
|
||||
);
|
||||
}
|
||||
|
||||
function getResolutionIdentity(request: JdkResolutionRequest): string {
|
||||
const identity = JSON.stringify({
|
||||
keyVersion: JDK_RESOLUTION_KEY_VERSION,
|
||||
runnerOs: getRunnerOs(),
|
||||
distribution: request.distribution.toLowerCase(),
|
||||
packageType: request.packageType.toLowerCase(),
|
||||
architecture: request.architecture.toLowerCase(),
|
||||
versionSpec: request.versionSpec,
|
||||
stable: request.stable
|
||||
});
|
||||
return createHash('sha256').update(identity).digest('hex');
|
||||
}
|
||||
|
||||
function getResolutionKeyPrefix(request: JdkResolutionRequest): string {
|
||||
const architecture = request.architecture.toLowerCase();
|
||||
const digest = getResolutionIdentity(request);
|
||||
return `setup-java-jdkres-v${JDK_RESOLUTION_KEY_VERSION}-${getRunnerOs()}-${architecture}-${digest}-`;
|
||||
}
|
||||
|
||||
function getRunnerOs(): string {
|
||||
return process.env['RUNNER_OS'] ?? process.platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start of the seven-day window the entry was resolved in, which bounds how long
|
||||
* a floating version spec such as `21` can keep resolving to an already known
|
||||
* release.
|
||||
*
|
||||
* Seven days is the longest usable window: GitHub evicts cache entries that have
|
||||
* not been accessed for seven days, so a longer one would mean the previous
|
||||
* entry is already gone when the window rolls over, taking the stale-fallback
|
||||
* path with it. It also comfortably covers the real release cadence, which is
|
||||
* monthly at its fastest and usually quarterly.
|
||||
*/
|
||||
function getFreshnessBucket(): string {
|
||||
const week = 7 * 24 * 60 * 60 * 1000;
|
||||
return new Date(Math.floor(Date.now() / week) * week)
|
||||
.toISOString()
|
||||
.slice(0, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* The restored payload drives a download, so it is validated as untrusted input
|
||||
* rather than trusted because it came back from the cache service.
|
||||
*/
|
||||
function parseResolvedRelease(contents: string): JavaDownloadRelease {
|
||||
const value: unknown = JSON.parse(contents);
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
throw new Error('The cached resolution is not an object.');
|
||||
}
|
||||
|
||||
const candidate = value as Record<string, unknown>;
|
||||
const version = candidate['version'];
|
||||
const url = candidate['url'];
|
||||
const signatureUrl = candidate['signatureUrl'];
|
||||
|
||||
if (typeof version !== 'string' || !version) {
|
||||
throw new Error('The cached resolution has no version.');
|
||||
}
|
||||
assertHttpsUrl(url, 'url');
|
||||
if (signatureUrl !== undefined) {
|
||||
assertHttpsUrl(signatureUrl, 'signatureUrl');
|
||||
}
|
||||
|
||||
const release: JavaDownloadRelease = {
|
||||
version,
|
||||
url: url as string
|
||||
};
|
||||
if (signatureUrl !== undefined) {
|
||||
release.signatureUrl = signatureUrl as string;
|
||||
}
|
||||
|
||||
const checksum = candidate['checksum'];
|
||||
if (checksum !== undefined) {
|
||||
release.checksum = parseChecksum(checksum);
|
||||
}
|
||||
|
||||
return release;
|
||||
}
|
||||
|
||||
function parseChecksum(value: unknown): ChecksumMetadata {
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
throw new Error('The cached checksum is not an object.');
|
||||
}
|
||||
|
||||
const candidate = value as Record<string, unknown>;
|
||||
const algorithm = candidate['algorithm'];
|
||||
const checksumValue = candidate['value'];
|
||||
const source = candidate['source'];
|
||||
|
||||
if (algorithm !== 'sha256' && algorithm !== 'sha512') {
|
||||
throw new Error(`Unsupported cached checksum algorithm: ${algorithm}`);
|
||||
}
|
||||
if (typeof checksumValue !== 'string' || !checksumValue) {
|
||||
throw new Error('The cached checksum has no value.');
|
||||
}
|
||||
if (source !== undefined && typeof source !== 'string') {
|
||||
throw new Error('The cached checksum source is not a string.');
|
||||
}
|
||||
|
||||
const checksum: ChecksumMetadata = {algorithm, value: checksumValue};
|
||||
if (source !== undefined) {
|
||||
checksum.source = source;
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
|
||||
function assertHttpsUrl(value: unknown, field: string): void {
|
||||
if (typeof value !== 'string' || !value) {
|
||||
throw new Error(`The cached resolution has no ${field}.`);
|
||||
}
|
||||
let parsed: URL;
|
||||
try {
|
||||
parsed = new URL(value);
|
||||
} catch {
|
||||
throw new Error(`The cached resolution has a malformed ${field}.`);
|
||||
}
|
||||
if (parsed.protocol !== 'https:') {
|
||||
throw new Error(
|
||||
`The cached resolution ${field} does not use HTTPS: ${parsed.protocol}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function parseJdkResolutionState(state: string): JdkResolutionState[] {
|
||||
const value: unknown = JSON.parse(state);
|
||||
if (
|
||||
!Array.isArray(value) ||
|
||||
!value.every(
|
||||
item =>
|
||||
typeof item === 'object' &&
|
||||
item !== null &&
|
||||
typeof (item as JdkResolutionState).key === 'string' &&
|
||||
typeof (item as JdkResolutionState).path === 'string' &&
|
||||
typeof (item as JdkResolutionState).release === 'string'
|
||||
)
|
||||
) {
|
||||
throw new Error('Invalid JDK resolution information retrieved from state.');
|
||||
}
|
||||
return value as JdkResolutionState[];
|
||||
}
|
||||
|
||||
function getErrorMessage(error: unknown): string {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
+1
-11
@@ -1,10 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import * as core from '@actions/core';
|
||||
import {
|
||||
getBooleanInput,
|
||||
getVersionFromFileContent,
|
||||
isJdkCacheEnabled
|
||||
} from './util.js';
|
||||
import {getBooleanInput, getVersionFromFileContent} from './util.js';
|
||||
import * as constants from './constants.js';
|
||||
import * as path from 'path';
|
||||
import {fileURLToPath} from 'url';
|
||||
@@ -21,7 +17,6 @@ export async function run() {
|
||||
const packageType = core.getInput(constants.INPUT_JAVA_PACKAGE);
|
||||
const jdkFile = getJdkFileInput();
|
||||
const cache = core.getInput(constants.INPUT_CACHE);
|
||||
const cacheJdk = isJdkCacheEnabled(cache);
|
||||
const cacheDependencyPath = core.getInput(
|
||||
constants.INPUT_CACHE_DEPENDENCY_PATH
|
||||
);
|
||||
@@ -85,7 +80,6 @@ export async function run() {
|
||||
packageType,
|
||||
checkLatest,
|
||||
forceDownload,
|
||||
cacheJdk,
|
||||
setDefault,
|
||||
verifySignature,
|
||||
verifySignaturePublicKey,
|
||||
@@ -111,7 +105,6 @@ export async function run() {
|
||||
packageType,
|
||||
checkLatest,
|
||||
forceDownload,
|
||||
cacheJdk,
|
||||
setDefault,
|
||||
verifySignature,
|
||||
verifySignaturePublicKey,
|
||||
@@ -190,7 +183,6 @@ async function installVersion(
|
||||
packageType,
|
||||
checkLatest,
|
||||
forceDownload,
|
||||
cacheJdk,
|
||||
setDefault,
|
||||
verifySignature,
|
||||
verifySignaturePublicKey,
|
||||
@@ -202,7 +194,6 @@ async function installVersion(
|
||||
packageType,
|
||||
checkLatest,
|
||||
forceDownload,
|
||||
cacheJdk,
|
||||
setDefault,
|
||||
verifySignature,
|
||||
verifySignaturePublicKey,
|
||||
@@ -247,7 +238,6 @@ interface installerInputsOptions {
|
||||
packageType: string;
|
||||
checkLatest: boolean;
|
||||
forceDownload: boolean;
|
||||
cacheJdk: boolean;
|
||||
setDefault: boolean;
|
||||
verifySignature: boolean;
|
||||
verifySignaturePublicKey: string | undefined;
|
||||
|
||||
+2
-151
@@ -5,14 +5,10 @@ import * as semver from 'semver';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as io from '@actions/io';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import {randomUUID} from 'crypto';
|
||||
import {
|
||||
INPUT_JOB_STATUS,
|
||||
DISTRIBUTIONS_ONLY_MAJOR_VERSION,
|
||||
INPUT_CACHE_JDK
|
||||
DISTRIBUTIONS_ONLY_MAJOR_VERSION
|
||||
} from './constants.js';
|
||||
import {OutgoingHttpHeaders} from 'http';
|
||||
|
||||
@@ -41,12 +37,6 @@ export function getBooleanInput(inputName: string, defaultValue = false) {
|
||||
);
|
||||
}
|
||||
|
||||
export function isJdkCacheEnabled(cache: string): boolean {
|
||||
return core.getInput(INPUT_CACHE_JDK).trim()
|
||||
? getBooleanInput(INPUT_CACHE_JDK)
|
||||
: Boolean(cache.trim());
|
||||
}
|
||||
|
||||
export function getVersionFromToolcachePath(toolPath: string) {
|
||||
if (toolPath) {
|
||||
return path.basename(path.dirname(toolPath));
|
||||
@@ -67,154 +57,15 @@ export async function extractJdkFile(toolPath: string, extension?: string) {
|
||||
|
||||
switch (extension) {
|
||||
case 'tar.gz':
|
||||
return await extractTarGz(toolPath);
|
||||
case 'tar':
|
||||
return await tc.extractTar(toolPath);
|
||||
case 'zip':
|
||||
return await extractZipArchive(toolPath);
|
||||
return await tc.extractZip(toolPath);
|
||||
default:
|
||||
return await tc.extract7z(toolPath);
|
||||
}
|
||||
}
|
||||
|
||||
async function createExtractFolder(): Promise<string> {
|
||||
const dest = path.join(getTempDir(), randomUUID());
|
||||
await io.mkdirP(dest);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompressing a JDK tarball with the default single-threaded gzip is one of the
|
||||
* slowest parts of the install, so hand the decompression to `pigz` when the runner
|
||||
* provides it. Any failure falls back to the stock extraction.
|
||||
*/
|
||||
async function extractTarGz(toolPath: string): Promise<string> {
|
||||
const pigzPath = await io.which('pigz');
|
||||
// tar splits --use-compress-program on whitespace, so a path containing a
|
||||
// space would be word-split into a bogus command.
|
||||
if (pigzPath && !/\s/.test(pigzPath)) {
|
||||
const dest = await createExtractFolder();
|
||||
try {
|
||||
return await tc.extractTar(toolPath, dest, [
|
||||
'--use-compress-program',
|
||||
`${pigzPath} -d`,
|
||||
'-x'
|
||||
]);
|
||||
} catch (error) {
|
||||
await io.rmRF(dest);
|
||||
core.debug(
|
||||
`Failed to extract '${toolPath}' with pigz, falling back to gzip: ${getErrorMessage(error)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return await tc.extractTar(toolPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* `tc.extractZip` shells out to PowerShell's `Expand-Archive` on Windows, which is
|
||||
* several times slower than the bundled bsdtar. Prefer `tar.exe` and fall back to
|
||||
* the stock extraction when it is unavailable or fails.
|
||||
*/
|
||||
async function extractZipArchive(toolPath: string): Promise<string> {
|
||||
if (process.platform === 'win32') {
|
||||
const systemTar = path.join(
|
||||
process.env['SystemRoot'] || 'C:\\Windows',
|
||||
'System32',
|
||||
'tar.exe'
|
||||
);
|
||||
|
||||
if (fs.existsSync(systemTar)) {
|
||||
const dest = await createExtractFolder();
|
||||
try {
|
||||
await exec.exec(`"${systemTar}"`, ['-xf', toolPath, '-C', dest], {
|
||||
silent: true
|
||||
});
|
||||
|
||||
return dest;
|
||||
} catch (error) {
|
||||
await io.rmRF(dest);
|
||||
core.debug(
|
||||
`Failed to extract '${toolPath}' with tar.exe, falling back to Expand-Archive: ${getErrorMessage(error)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await tc.extractZip(toolPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent of `tc.cacheDir`, but moves the extracted JDK into the tool-cache
|
||||
* instead of copying it. `tc.cacheDir` recursively copies the whole tree, which
|
||||
* means a several hundred megabyte JDK is written to disk twice. The extraction
|
||||
* directory and the tool-cache normally live on the same filesystem, so a rename
|
||||
* is effectively free. Anything unexpected (a different filesystem, or a file
|
||||
* handle held open by anti-virus software on Windows) falls back to the copy.
|
||||
*/
|
||||
export async function cacheJdkDir(
|
||||
sourceDir: string,
|
||||
toolName: string,
|
||||
version: string,
|
||||
architecture: string
|
||||
): Promise<string> {
|
||||
const destPath = getToolcacheDestination(toolName, version, architecture);
|
||||
|
||||
if (destPath) {
|
||||
let moved = false;
|
||||
try {
|
||||
// lstat, not stat: renaming a symlinked source would put the link itself
|
||||
// in the tool-cache, leaving a dangling JAVA_HOME once RUNNER_TEMP is
|
||||
// cleaned. tc.cacheDir dereferences it, so let it handle that case.
|
||||
if (fs.lstatSync(sourceDir).isDirectory()) {
|
||||
await io.rmRF(destPath);
|
||||
await io.rmRF(`${destPath}.complete`);
|
||||
await io.mkdirP(path.dirname(destPath));
|
||||
// Renaming is atomic, so a failure here leaves sourceDir untouched and
|
||||
// the copy-based fallback below can still run.
|
||||
fs.renameSync(sourceDir, destPath);
|
||||
moved = true;
|
||||
}
|
||||
} catch (error) {
|
||||
core.debug(
|
||||
`Failed to move '${sourceDir}' into the tool-cache, falling back to a copy: ${getErrorMessage(error)}`
|
||||
);
|
||||
}
|
||||
|
||||
if (moved) {
|
||||
fs.writeFileSync(`${destPath}.complete`, '');
|
||||
|
||||
return destPath;
|
||||
}
|
||||
}
|
||||
|
||||
return await tc.cacheDir(sourceDir, toolName, version, architecture);
|
||||
}
|
||||
|
||||
function getToolcacheDestination(
|
||||
toolName: string,
|
||||
version: string,
|
||||
architecture: string
|
||||
): string | null {
|
||||
const toolcacheRoot = process.env['RUNNER_TOOL_CACHE'];
|
||||
if (!toolcacheRoot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Mirrors the destination layout used by `tc.cacheDir`.
|
||||
return path.join(
|
||||
toolcacheRoot,
|
||||
toolName,
|
||||
semver.clean(version) || version,
|
||||
architecture || os.arch()
|
||||
);
|
||||
}
|
||||
|
||||
function getErrorMessage(error: unknown): string {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
|
||||
export function getDownloadArchiveExtension() {
|
||||
return process.platform === 'win32' ? 'zip' : 'tar.gz';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user